From: Asanka Herath Date: Wed, 11 Oct 2006 05:32:16 +0000 (+0000) Subject: windows-netidmgr-plugin-20061010 X-Git-Tag: BP-openafs-windows-kdfs-ifs~990 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=f72c2fc3e75a13e3736a275df35597ad43f620fa windows-netidmgr-plugin-20061010 Secure Endpoints Inc. is contributing its AFS plug-in for KFW 3.1's Network Identity Manager to OpenAFS under an MIT style license. --- diff --git a/src/NTMakefile b/src/NTMakefile index 42a6306..f6b59fb 100644 --- a/src/NTMakefile +++ b/src/NTMakefile @@ -563,7 +563,14 @@ aklog: client_creds $(NTMAKE) $(CD) ..\..\.. -extra: aklog +netidmgr_plugin: aklog + echo ***** $@ + $(DOCD) $(SRC)\WINNT\$@ + $(CD) $(SRC)\WINNT\$@ + $(NTMAKE) + $(CD) ..\..\.. + +extra: netidmgr_plugin ! IF EXIST($(SRC)\WINNT\extra) && EXIST($(SRC)\WINNT\extra\NTMakefile) echo ***** $@ $(DOCD) $(SRC)\WINNT\$@ diff --git a/src/WINNT/install/NSIS/OpenAFS.nsi b/src/WINNT/install/NSIS/OpenAFS.nsi index a8823ec..2126146 100644 --- a/src/WINNT/install/NSIS/OpenAFS.nsi +++ b/src/WINNT/install/NSIS/OpenAFS.nsi @@ -85,6 +85,7 @@ VIAddVersionKey "PrivateBuild" "Checked/Debug" !define AFS_COMPANY_NAME "OpenAFS" !define AFS_PRODUCT_NAME "OpenAFS" !define AFS_REGKEY_ROOT "Software\TransarcCorporation" + !define NID_PLUGIN_MGR "Software\MIT\NetIDMgr\PluginManager" CRCCheck force ;Folder selection page @@ -539,7 +540,7 @@ Section "!AFS Client" secClient File "${AFS_CLIENT_BUILDDIR}\afsdacl.exe" File "${AFS_CLIENT_BUILDDIR}\cmdebug.exe" File "${AFS_CLIENT_BUILDDIR}\aklog.exe" - File "${AFS_CLIENT_BUILDDIR}\afscreds.exe" + !insertmacro ReplaceDLL "${AFS_CLIENT_BUILDDIR}\afscreds.exe" "$INSTDIR\Client\Program\afscreds.exe" "$INSTDIR" !insertmacro ReplaceDLL "${AFS_CLIENT_BUILDDIR}\afs_shl_ext.dll" "$INSTDIR\Client\Program\afs_shl_ext.dll" "$INSTDIR" File "${AFS_CLIENT_BUILDDIR}\afsd_service.exe" File "${AFS_CLIENT_BUILDDIR}\symlink.exe" @@ -553,6 +554,9 @@ Section "!AFS Client" secClient File "${AFS_DESTDIR}\etc\rxdebug.exe" File "${AFS_DESTDIR}\etc\backup.exe" !insertmacro ReplaceDLL "${AFS_CLIENT_BUILDDIR}\afs_cpa.cpl" "$INSTDIR\Client\Program\afs_cpa.cpl" "$INSTDIR" + !insertmacro ReplaceDLL "${AFS_CLIENT_BUILDDIR}\afscred.dll" "$INSTDIR\Client\Program\afscred.dll" "$INSTDIR" + !insertmacro ReplaceDLL "${AFS_CLIENT_BUILDDIR}\afscred_en_us.dll" "$INSTDIR\Client\Program\afscred_en_us.dll" "$INSTDIR" + File "${AFS_CLIENT_BUILDDIR}\afsplhlp.chm" SetOutPath "$SYSDIR" !insertmacro ReplaceDLL "${AFS_CLIENT_BUILDDIR}\afslogon.dll" "$SYSDIR\afslogon.dll" "$INSTDIR" @@ -626,6 +630,18 @@ Section "!AFS Client" secClient DeleteRegValue HKLM "${AFS_REGKEY_ROOT}\AFS Client\${AFS_VERSION}" "Debug" !endif + ;NetIDMgr Plug-in Reg Entries + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Modules\OpenAFS" "ImagePath" "$INSTDIR\Client\Program\afscred.dll" + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Modules\OpenAFS" "Description" "OpenAFS Module" + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Modules\OpenAFS" "Vendor" "Secure Endpoints Inc." + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Modules\OpenAFS" "PluginList" "AfsCred" + WriteRegDWORD HKLM "${NID_PLUGIN_MGR}\Modules\OpenAFS" "NoUnload" "1" + + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Plugins\AfsCred" "Module" "OpenAFS" + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Plugins\AfsCred" "Description" "AFS Credentials Provider" + WriteRegStr HKLM "${NID_PLUGIN_MGR}\Plugins\AfsCred" "Dependencies" "Krb5Cred" + WriteRegDWORD HKLM "${NID_PLUGIN_MGR}\Plugins\AfsCred" "Type" "1" + ; On Windows 2000 work around KB301673. This is fixed in Windows XP and 2003 Call GetWindowsVersion Pop $R1 @@ -1133,6 +1149,7 @@ Section /o "Debug symbols" secDebug File "${AFS_DESTDIR}\etc\rxdebug.pdb" File "${AFS_DESTDIR}\etc\backup.pdb" File "${AFS_CLIENT_BUILDDIR}\afs_cpa.pdb" + File "${AFS_CLIENT_BUILDDIR}\afscred.pdb" SetOutPath "$SYSDIR" File "${AFS_CLIENT_BUILDDIR}\afslogon.pdb" @@ -1998,6 +2015,9 @@ StartRemove: DeleteRegKey HKLM "${AFS_REGKEY_ROOT}\AFS Server\CurrentVersion" DeleteRegKey HKLM "${AFS_REGKEY_ROOT}\AFS Server" DeleteRegKey /ifempty HKLM "${AFS_REGKEY_ROOT}" + DeleteRegKey HKLM "${NID_PLUGIN_MGR}\Modules\OpenAFS" + DeleteRegKey HKLM "${NID_PLUGIN_MGR}\Plugins\AfsCred" + DeleteRegKey /ifempty HKLM "Software\MIT\NetIDMgr" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenAFS" DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Services\NetBT\Parameters" "SmbDeviceEnabled" diff --git a/src/WINNT/install/wix/feature.wxi b/src/WINNT/install/wix/feature.wxi index bb36097..684b68e 100644 --- a/src/WINNT/install/wix/feature.wxi +++ b/src/WINNT/install/wix/feature.wxi @@ -24,33 +24,48 @@ - - - VersionNT = 500 And ServicePackLevel < 3 - + + + + + + + + + + + + + + + + VersionNT = 500 And ServicePackLevel < 3 + - - - CREDSSTARTUP = 0 - + + + CREDSSTARTUP = 0 + - - - - - - - - - + + + + + + + + + - + - + @@ -263,16 +278,31 @@ - - + + - + + + + + + + + + + + + + + diff --git a/src/WINNT/install/wix/files.wxi b/src/WINNT/install/wix/files.wxi index 3d34d2a..9959d17 100644 --- a/src/WINNT/install/wix/files.wxi +++ b/src/WINNT/install/wix/files.wxi @@ -851,6 +851,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/WINNT/install/wix/lang/en_US/strings.wxl b/src/WINNT/install/wix/lang/en_US/strings.wxl index 72a2843..5737a82 100644 --- a/src/WINNT/install/wix/lang/en_US/strings.wxl +++ b/src/WINNT/install/wix/lang/en_US/strings.wxl @@ -27,6 +27,10 @@ Loopback adapter for AFS. It is recommended that you install the loopback adapter if you are installing the client components. OpenAFS command-line utilities and libraries. Tools and libraries + NetIDMgr Plug-in + OpenAFS plug-in for Network Identity Manager. Adds AFS token management capabilities to Network Identity Manager. + Debug symbols for NetIDMgr plug-in + Debugging symbols for the OpenAFS NetIDMgr plug-in. AFS Context Menu Shell Extension Authentication for AFS diff --git a/src/WINNT/install/wix/openafs.wxs b/src/WINNT/install/wix/openafs.wxs index 933f2be..3fde40a 100644 --- a/src/WINNT/install/wix/openafs.wxs +++ b/src/WINNT/install/wix/openafs.wxs @@ -207,7 +207,7 @@ - IBMAFS_UPGRADE OR OPENAFS_UPGRADE + IBMAFS_UPGRADE OR OPENAFS_UPGRADE OR AFSPLUGIN_UPGRADE NSISUNINSTALL <> "" AND UILevel >= 4 NSISUNINSTALL <> "" AND UILevel < 4 @@ -243,6 +243,13 @@ + + + + + + + diff --git a/src/WINNT/install/wix/platform.wxi b/src/WINNT/install/wix/platform.wxi index e8b1d8f..53ccc92 100644 --- a/src/WINNT/install/wix/platform.wxi +++ b/src/WINNT/install/wix/platform.wxi @@ -198,7 +198,10 @@ - + + + + diff --git a/src/WINNT/netidmgr_plugin/NTMakefile b/src/WINNT/netidmgr_plugin/NTMakefile new file mode 100644 index 0000000..ba84673 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/NTMakefile @@ -0,0 +1,183 @@ +# +# Copyright (c) 2005,2006 Secure Endpoints Inc. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +AFSDEV_AUXRCFLAGS=/i ..\kfw\inc\netidmgr +RELDIR=WINNT\netidmgr_plugin +!INCLUDE ..\..\config\NTMakefile.$(SYS_NAME) +!INCLUDE ..\..\config\NTMakefile.version + +AFSPLUGIN_VERSION_MAJOR=$(AFSPRODUCT_VER_MAJOR) +AFSPLUGIN_VERSION_MINOR=$(AFSPRODUCT_VER_MINOR) +AFSPLUGIN_VERSION_PATCH=$(AFSPRODUCT_VER_PATCH) +AFSPLUGIN_VERSION_AUX =$(AFSPRODUCT_VER_BUILD) + +AFSPLUGIN_VERSION=$(AFSPLUGIN_VERSION_MAJOR).$(AFSPLUGIN_VERSION_MINOR).$(AFSPLUGIN_VERSION_PATCH).$(AFSPLUGIN_VERSION_AUX) +AFSPLUGIN_VERLIST=$(AFSPLUGIN_VERSION_MAJOR),$(AFSPLUGIN_VERSION_MINOR),$(AFSPLUGIN_VERSION_PATCH),$(AFSPLUGIN_VERSION_AUX) + +# short form version numbers +TAFSPLUGIN_VERSION=$(AFSPLUGIN_VERSION_MAJOR).$(AFSPLUGIN_VERSION_MINOR).$(AFSPLUGIN_VERSION_PATCH) + +# Directories + +EXEDIR = $(DESTDIR)\root.client\usr\vice\etc + +INCFILEDIR = $(DESTDIR)\include\WINNT + +LIBFILEDIR = $(DESTDIR)\lib + +KFWINCDIR = ..\kfw\inc + +KFWLIBDIR = ..\kfw\lib\$(CPU) + +# Build environment + +kfwincflags=-I$(KFWINCDIR)\krb5\KerberosIV -I$(KFWINCDIR)\loadfuncs -I$(KFWINCDIR)\krb5 -I$(KFWINCDIR)\netidmgr -I$(KFWINCDIR) +afsincflags=-I$(DESTDIR)\include + +incflags=$(kfwincflags) $(afsincflags) -I. +pldefines=-DUNICODE -D_UNICODE +cdebug=$(cdebug) -Os -Zi +cwarn=$(cwarn) /Wp64 /WX + +plcflags=$(cdebug) $(cflags) $(incflags) $(pldefines) $(cwarn) $(cvarsmt) + +PC2OBJ=$(CC) $(plcflags) /Fo"$@" /c $** + +{}.c{$(OBJ)}.obj: + $(PC2OBJ) + +# Targets + +CHMFILE=$(EXEDIR)\afsplhlp.chm + +DLLFILE=$(EXEDIR)\afscred.dll + +LIBFILE=$(LIBFILEDIR)\afscred.lib + +INCFILES= \ + $(INCFILEDIR)\afspext.h \ + $(INCFILEDIR)\afsp_version.h + +OBJFILES= \ + $(OUT)\afsfuncs.obj \ + $(OUT)\afsplugin.obj \ + $(OUT)\main.obj \ + $(OUT)\afsconfig.obj \ + $(OUT)\afsconfigdlg.obj \ + $(OUT)\afsnewcreds.obj \ + $(OUT)\afsext.obj \ + $(OUT)\afshelp.obj \ + $(OUT)\dynimport.obj \ + $(OUT)\krb5common.obj + +LIBFILES= \ + $(KFWLIBDIR)\nidmgr32.lib + +SDKLIBFILES= \ + $(DESTDIR)\lib\afsauthent.lib \ + $(DESTDIR)\lib\libafsconf.lib \ + $(KFWLIBDIR)\loadfuncs.lib \ + htmlhelp.lib \ + shell32.lib \ + comctl32.lib \ + version.lib \ + shlwapi.lib \ + psapi.lib + +VERRESFILE=$(OUT)\version.res + +$(OUT)\afsfuncs.obj: afsfuncs.c + $(PC2OBJ) + +$(OUT)\afsplugin.obj: afsplugin.c + $(PC2OBJ) + +$(OUT)\main.obj: main.c + $(PC2OBJ) + +$(OUT)\afsconfig.obj: afsconfig.c + $(PC2OBJ) + +$(OUT)\afsconfigdlg.obj: afsconfigdlg.c + $(PC2OBJ) + +$(OUT)\afsnewcreds.obj: afsnewcreds.c + $(PC2OBJ) + +$(OUT)\afsext.obj: afsext.c + $(PC2OBJ) + +$(OUT)\afshelp.obj: afshelp.c + $(PC2OBJ) + +$(OUT)\dynimport.obj: dynimport.c + $(PC2OBJ) + +$(OUT)\krb5common.obj: krb5common.c + $(PC2OBJ) + +!include afsp_version.h.in + +$(DLLFILE): $(OBJFILES) $(VERRESFILE) + $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) + $(_VC_MANIFEST_EMBED_DLL) + $(_VC_MANIFEST_CLEAN) + +dummy: + +$(CHMFILE): dummy + $(CD) help + nmake /f NTMakefile install + $(CD) .. + +install: $(INCFILES) $(CHMFILE) $(DLLFILE) lang + +lang:: + +# Repeat this block as necessary redefining LANG for additional +# languages. + +# Begin language block +LANG=en_us + +LANGDLL=$(EXEDIR)\afscred_$(LANG).dll + +lang:: $(LANGDLL) + +$(LANGDLL): $(OUT)\langres_$(LANG).res $(OUT)\langres_ver_$(LANG).res + $(DLLRESLINK) + +$(OUT)\langres_ver_$(LANG).res: version.rc + $(RC) /d LANGVER /d LANG_$(LANG) /fo $@ $** + +$(OUT)\langres_$(LANG).res: lang\$(LANG)\langres.rc + $(RC) /fo $@ $** +# End language block + +clean:: +!ifdef INCFILES + $(DEL) $(INCFILES) +!endif + $(CD) help + $(MAKECMD) /f NTMakefile clean + $(CD) .. diff --git a/src/WINNT/netidmgr_plugin/afsconfig.c b/src/WINNT/netidmgr_plugin/afsconfig.c new file mode 100644 index 0000000..512e2a0 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsconfig.c @@ -0,0 +1,36 @@ +/* +This file was autogenerated from: + c:\work\pismere\athena\auth\krb5\src\windows\identity\config\csvschema.cfg + afsconfig.csv + +Do not modify directly. +*/ +#include + +kconf_schema schema_afsconfig[] = { +{L"AfsCred",KC_SPACE,0,L"AFS Credentials Provider"}, +{L"Module",KC_STRING,(khm_int64) L"OpenAFS",L""}, +{L"Description",KC_STRING,(khm_int64) L"AFS Credentials Provider",L""}, +{L"Dependencies",KC_STRING,(khm_int64) L"Krb5Cred",L""}, +{L"Type",KC_INT32,1,L""}, +{L"Flags",KC_INT32,0,L""}, +{L"Cells",KC_STRING,(khm_int64) L"",L"Multi string giving list of cells to authenticate to"}, +{L"Disableafscreds",KC_INT32,0,L"Disable afscreds.exe"}, +{L"Parameters",KC_SPACE,0,L"Parameters for AfsCred"}, +{L"AFSEnabled",KC_INT32,1,L"Is AFS enabled?"}, +{L"LRUCells",KC_STRING,(khm_int64) L"",L"List of recently used cells"}, +{L"LRURealms",KC_STRING,(khm_int64) L"",L"List of recently used realms"}, +{L"DefaultCells",KC_STRING,(khm_int64) L"",L"List of default cells to authenticate to."}, +{L"Parameters",KC_ENDSPACE,0,L""}, +{L"Cells",KC_SPACE,0,L"Per identity cells list and plugin settings"}, +{L"cellname",KC_STRING,(khm_int64) L"identity",L"Cell-identity mapping kept in the plugin configuration for the user."}, +{L"_Schema",KC_SPACE,0,L"Schema is named for each cell to authenticate"}, +{L"MethodName",KC_STRING,(khm_int64) L"",L"Name of method"}, +{L"Method",KC_INT32,0,L"(Deprecated) Method identifier"}, +{L"Realm",KC_STRING,(khm_int64) L"",L"Kerberos realm to use for authentication"}, +{L"_Schema",KC_ENDSPACE,0,L""}, +{L"Cells",KC_ENDSPACE,0,L""}, +{L"AfsCred",KC_ENDSPACE,0,L""} +}; + + diff --git a/src/WINNT/netidmgr_plugin/afsconfigdlg.c b/src/WINNT/netidmgr_plugin/afsconfigdlg.c new file mode 100644 index 0000000..1fbf84b --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsconfigdlg.c @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include + +/* disable the 'name was marked as deprecated' warnings. These get + issued for Str?Cat? and Str?Cpy? functions. We don't use those + anyway. */ +#pragma warning(push) +#pragma warning(disable: 4995) +#include +#include +#pragma warning(pop) + +#include + +typedef struct tag_afs_ids_dlg_data { + khui_config_init_data cfg; + + khm_boolean afs_enabled; +} afs_ids_dlg_data; + +INT_PTR CALLBACK +afs_cfg_ids_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + afs_ids_dlg_data * d = NULL; + + switch(uMsg) { + case WM_INITDIALOG: + { + khm_int32 t = 1; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + d->cfg = *((khui_config_init_data *) lParam); + + khc_read_int32(csp_params, L"AFSEnabled", &t); + + d->afs_enabled = !!t; + + CheckDlgButton(hwnd, IDC_CFG_OBTAIN, + (d->afs_enabled)? BST_CHECKED: BST_UNCHECKED); + } + return FALSE; + + case WM_DESTROY: + { + d = (afs_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + PFREE(d); + } + return TRUE; + + case WM_COMMAND: + { + d = (afs_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (wParam == MAKEWPARAM(IDC_CFG_OBTAIN, BN_CLICKED)) { + d->afs_enabled = + (IsDlgButtonChecked(hwnd, IDC_CFG_OBTAIN) == + BST_CHECKED); + khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + return TRUE; + } + } + return FALSE; + + case KHUI_WM_CFG_NOTIFY: + { + d = (afs_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == WMCFG_APPLY) { + khm_int32 t; + + if (KHM_FAILED(khc_read_int32(csp_params, + L"AFSEnabled", &t)) || + !!t != !!d->afs_enabled) { + khc_write_int32(csp_params, L"AFSEnabled", + !!d->afs_enabled); + + khui_cfg_set_flags_inst(&d->cfg, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | + KHUI_CNFLAG_MODIFIED); + } else { + khui_cfg_set_flags_inst(&d->cfg, + 0, + KHUI_CNFLAG_MODIFIED); + } + } + } + return TRUE; + } + + return FALSE; +} + +INT_PTR CALLBACK +afs_cfg_id_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + switch(uMsg) { + + case WM_INITDIALOG: + { + INT_PTR rv; + afs_dlg_data * d; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + rv = afs_dlg_proc(hwnd, uMsg, wParam, 0); + + d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + d->cfg = *((khui_config_init_data *) lParam); + + idname[0] = L'\0'; + cb = sizeof(idname); + khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); + + d->ident = NULL; + kcdb_identity_create(idname, 0, &d->ident); + +#ifdef DEBUG + assert(d->ident); +#endif + + d->config_dlg = TRUE; + + afs_cred_get_identity_creds(&d->creds, d->ident, &d->afs_enabled); + + afs_dlg_proc(hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0); + + return rv; + } + break; /* not reached */ + + case WM_DESTROY: + { + afs_dlg_data * d; + + d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); +#ifdef DEBUG + assert(d && d->ident); +#endif + kcdb_identity_release(d->ident); + + return afs_dlg_proc(hwnd, uMsg, wParam, lParam); + } + break; /* not reached */ + + case KHUI_WM_CFG_NOTIFY: + { + afs_dlg_data * d; + + d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == WMCFG_APPLY) { + afs_cred_write_ident_data(d); + } + } + return TRUE; + + default: + return afs_dlg_proc(hwnd, uMsg, wParam, lParam); + } +} + +static void +set_service_status(HWND hwnd) { + static DWORD wait_start = 0; + DWORD status = 0; + DWORD wait_hint = 0; + int i; + wchar_t status_strings_csv[1024]; + wchar_t status_strings_ms[1024]; + khm_size cb; + wchar_t *t; + + GetServiceStatus(NULL, + TRANSARCAFSDAEMON, + &status, &wait_hint); + + LoadString(hResModule, IDS_CFG_SVCSTATUS, + status_strings_csv, ARRAYLENGTH(status_strings_csv)); + + cb = sizeof(status_strings_ms); + csv_to_multi_string(status_strings_ms, &cb, status_strings_csv); + + for(i=0, t = status_strings_ms; t && *t && *t != L' '; + t = multi_string_next(t), i++) { + if (i == status) + break; + } + + if (!t || !*t) + t = status_strings_ms; /* the first one is "unknown". */ + + SetDlgItemText(hwnd, IDC_CFG_STATUS, t); + + if (status != SERVICE_RUNNING) { + HWND hw; + + hw = GetDlgItem(hwnd, IDC_CFG_STOP); + if (hw == GetFocus()) + SetFocus(GetNextDlgTabItem(hwnd, hw, FALSE)); + + EnableWindow(hw, FALSE); + } else { + EnableWindow(GetDlgItem(hwnd, IDC_CFG_STOP), TRUE); + } + + if (status != SERVICE_STOPPED && + status != SERVICE_PAUSED) { + HWND hw; + + hw = GetDlgItem(hwnd, IDC_CFG_START); + if (hw == GetFocus()) + SetFocus(GetNextDlgTabItem(hwnd, hw, FALSE)); + + EnableWindow(hw, FALSE); + } else { + EnableWindow(GetDlgItem(hwnd, IDC_CFG_START), TRUE); + } + + if (status == SERVICE_START_PENDING || + status == SERVICE_STOP_PENDING) { + HWND hw; + DWORD now; + int progress; + + hw = GetDlgItem(hwnd, IDC_CFG_PROGRESS); +#ifdef DEBUG + assert(hw); +#endif + if (!IsWindowVisible(hw)) + ShowWindow(hw, SW_SHOW); + + if (wait_start == 0) + wait_start = GetTickCount(); + + now = GetTickCount(); + + if (now + wait_hint != wait_start) + progress = (now - wait_start) * 100 / + (now + wait_hint - wait_start); + else + progress = 0; + + SendMessage(hw, PBM_SETPOS, progress, 0); + + SetTimer(hwnd, 1, 500, NULL); + } else { + HWND hw; + + hw = GetDlgItem(hwnd, IDC_CFG_PROGRESS); +#ifdef DEBUG + assert(hw); +#endif + wait_start = 0; + if (IsWindowVisible(hw)) + ShowWindow(hw, SW_HIDE); + } +} + +void +afs_cfg_show_last_error(HWND hwnd, wchar_t * prefix, DWORD code) { + DWORD r; + wchar_t * err_desc = NULL; + wchar_t title[64]; + wchar_t msg[1024]; + wchar_t tmp[128]; + + r = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + code, + 0, + (LPWSTR) &err_desc, + 0, + NULL); + + if (r == 0 || err_desc == NULL) + return; + + LoadString(hResModule, IDS_PLUGIN_DESC, + title, ARRAYLENGTH(title)); + if (prefix == NULL) + tmp[0] = L'\0'; + else if (IS_INTRESOURCE(prefix)) + LoadString(hResModule, (UINT)(UINT_PTR) prefix, + tmp, ARRAYLENGTH(tmp)); + else + StringCbCopy(tmp, sizeof(tmp), prefix); + + StringCbPrintf(msg, sizeof(msg), L"%s%s", + tmp, err_desc); + + MessageBox(hwnd, msg, title, MB_OK | MB_APPLMODAL); + + LocalFree(err_desc); +} + +#define SCNAME_AFSCREDS L"AFS Credentials.lnk" + +BOOL +afs_cfg_get_afscreds_shortcut(wchar_t * wpath) { + HRESULT hr; + BOOL shortcut_found = FALSE; + + hr = SHGetFolderPath(NULL, CSIDL_COMMON_STARTUP, + NULL, SHGFP_TYPE_CURRENT, + wpath); + if (FAILED(hr)) + goto _noshortcut; + + if (!PathAppend(wpath, SCNAME_AFSCREDS)) { + goto _noshortcut; + } + + if (PathFileExists(wpath)) { + shortcut_found = TRUE; + } + + _noshortcut: + + return shortcut_found; +} + +INT_PTR CALLBACK +afs_cfg_main_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + { + wchar_t imagepath[MAX_PATH]; + wchar_t blockname[MAX_PATH]; + HKEY service_key; + LONG l; + DWORD cb; + DWORD dummy; + LPVOID ver_info; + wchar_t * value; + + struct LANGANDCODEPATH { + WORD wLanguage; + WORD wCodePage; + } *translations; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (DWORD_PTR) lParam); +#pragma warning(pop) + + /* Try to figure out if afscreds.exe is on the startup + group for all users. */ + { + khm_handle csp_afscred = NULL; + khm_int32 disable = FALSE; + + if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, + 0, + &csp_afscred))) { + + khc_read_int32(csp_afscred, L"Disableafscreds", + &disable); + + khc_close_space(csp_afscred); + } + + if (!disable) { + CheckDlgButton(hwnd, IDC_CFG_STARTAFSCREDS, + BST_UNCHECKED); + } else { + CheckDlgButton(hwnd, IDC_CFG_STARTAFSCREDS, + BST_CHECKED); + } + } + + l = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon", + 0, + KEY_READ, + &service_key); + + if (l != ERROR_SUCCESS) + goto _set_status; + + cb = sizeof(imagepath); + l = RegQueryValueEx(service_key, + L"ImagePath", + NULL, NULL, + (LPBYTE) imagepath, + &cb); + if (l != ERROR_SUCCESS) + goto _close_key; + + PathUnquoteSpaces(imagepath); + + dummy = 1; + cb = GetFileVersionInfoSize(imagepath, &dummy); + if (cb == 0 || dummy) + goto _close_key; + + ver_info = malloc(cb); +#ifdef DEBUG + assert(ver_info); +#endif + if (!ver_info) + goto _close_key; + + if (!GetFileVersionInfo(imagepath, + 0, cb, ver_info)) + goto _free_buffer; + + cb = 0; + if (!VerQueryValue(ver_info, + L"\\VarFileInfo\\Translation", + (LPVOID*) &translations, + &cb) || + cb == 0) + goto _free_buffer; + + StringCbPrintf(blockname, sizeof(blockname), + L"\\StringFileInfo\\%04x%04x\\FileVersion", + translations[0].wLanguage, + translations[0].wCodePage); + + if (!VerQueryValue(ver_info, + blockname, + (LPVOID*) &value, + &cb) || + cb == 0) + goto _free_buffer; + + SetDlgItemText(hwnd, IDC_CFG_VERSION, value); + + StringCbPrintf(blockname, sizeof(blockname), + L"\\StringFileInfo\\%04x%04x\\CompanyName", + translations[0].wLanguage, + translations[0].wCodePage); + + if (!VerQueryValue(ver_info, + blockname, + (LPVOID*) &value, + &cb) || + cb == 0) + goto _free_buffer; + + SetDlgItemText(hwnd, IDC_CFG_COMPANY, value); + + _free_buffer: + free(ver_info); + _close_key: + RegCloseKey(service_key); + _set_status: + set_service_status(hwnd); + } + return FALSE; + + case WM_COMMAND: + switch(wParam) { + case MAKEWPARAM(IDC_CFG_STOP, BN_CLICKED): + { + DWORD r; + + r = ServiceControl(NULL, TRANSARCAFSDAEMON, SERVICE_STOPPED); + + if (r) + afs_cfg_show_last_error(hwnd, + MAKEINTRESOURCE(IDS_CFG_CANTSTOP), + r); + else + set_service_status(hwnd); + } + break; + + case MAKEWPARAM(IDC_CFG_START,BN_CLICKED): + { + DWORD r; + r = ServiceControl(NULL, TRANSARCAFSDAEMON, SERVICE_RUNNING); + + if (r) + afs_cfg_show_last_error(hwnd, + MAKEINTRESOURCE(IDS_CFG_CANTSTART), + r); + else + set_service_status(hwnd); + } + break; + + case MAKEWPARAM(IDC_CFG_CPL, BN_CLICKED): + if (32 >= (LRESULT) ShellExecute (NULL, NULL, + L"AFS_CONFIG.EXE", NULL, + NULL, SW_SHOW)) { + MessageBox(NULL, + L"Can't find file AFS_CONFIG.EXE", + L"Error", MB_OK); + } + break; + + case MAKEWPARAM(IDC_CFG_STARTAFSCREDS, BN_CLICKED): + { + khui_config_node node; + + node = (khui_config_node) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + khui_cfg_set_flags(node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } + break; + } + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + { + if (HIWORD(wParam) == WMCFG_APPLY) { + wchar_t wpath[MAX_PATH]; + int dlg_state; + khui_config_node node; + khm_handle csp_afscred = NULL; + khm_int32 disable = FALSE; + + node = (khui_config_node) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + kmm_get_plugin_config(AFS_PLUGIN_NAME, KHM_PERM_WRITE, + &csp_afscred); + + if (csp_afscred) + khc_read_int32(csp_afscred, L"Disableafscreds", + &disable); + + dlg_state = IsDlgButtonChecked(hwnd, IDC_CFG_STARTAFSCREDS); + + if (!!disable != + (dlg_state == BST_CHECKED)) { + if (csp_afscred) + khc_write_int32(csp_afscred, + L"Disableafscreds", + (dlg_state == BST_CHECKED)); + + khui_cfg_set_flags(node, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_MODIFIED | + KHUI_CNFLAG_APPLIED); + } else { + khui_cfg_set_flags(node, 0, + KHUI_CNFLAG_MODIFIED); + } + + if (dlg_state == BST_CHECKED && + afs_cfg_get_afscreds_shortcut(wpath)) { + + DeleteFile(wpath); + } + } + } + return TRUE; + + case WM_TIMER: + if (wParam == 1) { + KillTimer(hwnd, 1); + set_service_status(hwnd); + } + break; + + case WM_DESTROY: + return FALSE; + + case WM_HELP: + { + static const DWORD ctx_help[] = { + IDC_CFG_STATUS, IDH_SVCSTATUS, + IDC_CFG_STOP, IDH_SVCSTOP, + IDC_CFG_START, IDH_SVCSTART, + IDC_CFG_VERSION, IDH_SVCVERSION, + IDC_CFG_COMPANY, IDH_SVCCOMPANY, + IDC_CFG_CPL, IDH_SVCCPL, + IDC_CFG_STARTAFSCREDS, IDH_STARTAFSCREDS, + 0 + }; + + LPHELPINFO hlp; + + hlp = (LPHELPINFO) lParam; + + if (hlp->iContextType != HELPINFO_WINDOW) + break; + + afs_html_help(hlp->hItemHandle, L"::/popups_cfg.txt", + HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help); + } + return TRUE; + } + return FALSE; +} diff --git a/src/WINNT/netidmgr_plugin/afscred.h b/src/WINNT/netidmgr_plugin/afscred.h new file mode 100644 index 0000000..3dad7ab --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afscred.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_AFSCRED_H +#define __KHIMAIRA_AFSCRED_H + +#define _WINSOCKAPI_ +#include +#include + +#define KHERR_FACILITY L"AfsCred" +#define KHERR_HMODULE hResModule +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#ifndef NOSTRSAFE +#include +#endif + +#define AFS_PLUGIN_NAME L"AfsCred" +#define AFS_CREDTYPE_NAME L"AfsCred" + +#define AFS_PLUGIN_DEPS L"Krb5Cred\0" + +#define KRB5_CREDTYPE_NAME L"Krb5Cred" +#define KRB4_CREDTYPE_NAME L"Krb4Cred" + +#define AFS_TYPENAME_PRINCIPAL L"AFSPrincipal" +#define AFS_TYPENAME_METHOD L"AFSTokenMethod" +#define AFS_ATTRNAME_CLIENT_PRINC L"AFSClientPrinc" +#define AFS_ATTRNAME_SERVER_PRINC L"AFSServerPrinc" +#define AFS_ATTRNAME_CELL L"AFSCell" +#define AFS_ATTRNAME_METHOD L"AFSMethod" +#define AFS_ATTRNAME_REALM L"AFSRealm" + +#define AFS_VALID_CELL_CHARS L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-" +#define AFS_VALID_REALM_CHARS AFS_VALID_CELL_CHARS + +#define AFS_CONFIG_NODE_IDS L"AfsIdentities" +#define AFS_CONFIG_NODE_ID L"AfsIdentity" +#define AFS_CONFIG_NODE_MAIN L"AfsOptions" + +#define AFS_HELPFILE L"afsplhlp.chm" + +/* token acquisition methods provided by extensions begin with this + ID */ +#define AFS_TOKEN_USER 8 + +void init_afs(); +void exit_afs(); +KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module); +KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module); + +/* globals */ +extern kmm_module h_khModule; +extern HMODULE hResModule; +extern HINSTANCE hInstance; + +extern khm_int32 afs_credtype_id; +extern khm_int32 krb5_credtype_id; +extern khm_int32 krb4_credtype_id; +extern khm_int32 afs_msg_type_id; +extern khm_handle afs_credset; + +extern khm_int32 afs_type_principal; +extern khm_int32 afs_attr_client_princ; +extern khm_int32 afs_attr_server_princ; +extern khm_int32 afs_attr_cell; +extern khm_int32 afs_attr_method; +extern khm_int32 afs_attr_realm; + +/* Configuration spaces */ +#define CSNAME_PLUGINS L"Plugins" +#define CSNAME_AFSCRED L"AfsCred" +#define CSNAME_PARAMS L"Parameters" + +extern khm_handle csp_plugins; +extern khm_handle csp_afscred; +extern khm_handle csp_params; + +extern khm_handle afs_sub; + +/* defined in afsconfig.c which is generated from afsconfig.csv */ +extern kconf_schema schema_afsconfig[]; + + +/* plugin callback procedure */ +khm_int32 KHMAPI +afs_plugin_cb(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam); + +INT_PTR CALLBACK +afs_cfg_ids_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +afs_cfg_id_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +afs_cfg_main_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +HWND +afs_html_help(HWND caller, + wchar_t * postfix, + UINT cmd, + DWORD_PTR data); + +/* extensions */ +typedef afs_msg_announce afs_extension; + +/* not thread safe. only call from the plugin thread */ +afs_extension * +afs_find_extension(const wchar_t * name); + +/* not thread safe. only call from the plugin thread */ +afs_extension * +afs_get_extension(khm_size i); + +/* not thread safe. only call from the plugin thread */ +afs_extension * +afs_get_next_token_acq(afs_extension * f); + +/* not thread safe. only call from the plugin thread */ +khm_boolean +afs_is_valid_method_id(afs_tk_method method); + +afs_tk_method +afs_get_next_method_id(afs_tk_method method); + +afs_tk_method +afs_get_method_id(wchar_t * name); + +khm_boolean +afs_get_method_name(afs_tk_method method, wchar_t * buf, khm_size cbbuf); + +afs_extension * +afs_get_method_ext(afs_tk_method method); + +khm_boolean +afs_method_describe(afs_tk_method method, khm_int32 flags, + wchar_t * wbuf, khm_size cbbuf); + +khm_boolean +afs_ext_resolve_token(const wchar_t * cell, + const struct ktc_token * token, + const struct ktc_principal * serverp, + const struct ktc_principal * clientp, + khm_handle * pident, + afs_tk_method * pmethod); + +khm_boolean +afs_ext_klog(afs_tk_method method, + khm_handle identity, + const char * service, + const char * cell, + const char * realm, + const afs_conf_cell * cell_config, + khm_int32 lifetime); + +BOOL +afs_cfg_get_afscreds_shortcut(wchar_t * wpath); + +#endif diff --git a/src/WINNT/netidmgr_plugin/afsext.c b/src/WINNT/netidmgr_plugin/afsext.c new file mode 100644 index 0000000..5a3e5d3 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsext.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include +#include +#include + +/* supported API versions */ +#define AFS_PLUGIN_VERSION_MIN 0x00000001 +#define AFS_PLUGIN_VERSION_MAX AFS_PLUGIN_VERSION + +#define MAX_EXTENSIONS 8 + +afs_extension extensions[MAX_EXTENSIONS]; +khm_size n_extensions = 0; +khm_int32 next_method_id = AFS_TOKEN_USER; + +/* not threadsafe. should only be called from the plugin thread */ +khm_int32 +afs_add_extension(afs_msg_announce * ann) { + size_t cbname = 0; + size_t cbtashort = 0; + size_t cbtalong = 0; + afs_extension * ext; + wchar_t * tmp; + + if (ann->cbsize != sizeof(afs_msg_announce) || + FAILED(StringCbLength(ann->name, KHUI_MAXCB_NAME, &cbname)) || + ann->sub == NULL || + (ann->provide_token_acq && + ((FAILED(StringCbLength(ann->token_acq.short_desc, + KHUI_MAXCB_SHORT_DESC, + &cbtashort))) || + (ann->token_acq.long_desc && + FAILED(StringCbLength(ann->token_acq.long_desc, + KHUI_MAXCB_LONG_DESC, + &cbtalong))))) || + ann->version < AFS_PLUGIN_VERSION_MIN || + ann->version > AFS_PLUGIN_VERSION_MAX) + + return KHM_ERROR_INVALID_PARAM; + + if (n_extensions == MAX_EXTENSIONS) + return KHM_ERROR_NO_RESOURCES; + + cbname += sizeof(wchar_t); + cbtashort += sizeof(wchar_t); + cbtalong += sizeof(wchar_t); + + ext = &extensions[n_extensions]; + + *ext = *ann; + + tmp = PMALLOC(cbname); +#ifdef DEBUG + assert(tmp); +#endif + StringCbCopy(tmp, cbname, ann->name); + ext->name = tmp; + + if (ann->provide_token_acq) { + tmp = PMALLOC(cbtashort); +#ifdef DEBUG + assert(tmp); +#endif + StringCbCopy(tmp, cbtashort, ann->token_acq.short_desc); + ext->token_acq.short_desc = tmp; + + if (ann->token_acq.long_desc) { + tmp = PMALLOC(cbtalong); +#ifdef DEBUG + assert(tmp); +#endif + StringCbCopy(tmp, cbtalong, + ann->token_acq.long_desc); + ext->token_acq.long_desc = tmp; + } else { + ext->token_acq.long_desc = NULL; + } + + ann->token_acq.method_id = next_method_id++; + ext->token_acq.method_id = ann->token_acq.method_id; + } else { + ZeroMemory(&ext->token_acq, sizeof(ext->token_acq)); + } + + n_extensions++; + + return KHM_ERROR_SUCCESS; +} + +void +afs_free_extension(khm_int32 idx) { + afs_extension * ext; + +#ifdef DEBUG + assert(idx >= 0 && idx < (khm_int32) n_extensions); +#endif + + ext = &extensions[idx]; + + if (ext->name) + PFREE((void *) ext->name); + if (ext->token_acq.short_desc) + PFREE((void *) ext->token_acq.short_desc); + if (ext->token_acq.long_desc) + PFREE((void *) ext->token_acq.long_desc); + if (ext->sub) + kmq_delete_subscription(ext->sub); + + ZeroMemory(ext, sizeof(*ext)); +} + +/* not thread safe. only call from plugin thread */ +void +afs_remove_extension(khm_int32 idx) { + if (idx < 0 || idx > (khm_int32) n_extensions) + return; + + afs_free_extension(idx); + + if (idx == n_extensions-1) { + n_extensions--; + } else { + MoveMemory(&extensions[idx], &extensions[idx + 1], + (n_extensions - (idx+1)) * sizeof(*extensions)); + } +} + +/* not thread safe. only call from the plugin thread */ +afs_extension * +afs_find_extension(const wchar_t * name) { + khm_size i; + + for (i=0; i < n_extensions; i++) { + if (extensions[i].name && + !wcscmp(extensions[i].name, name)) + return &extensions[i]; + } + + return NULL; +} + +/* not thread safe. only call from the plugin thread */ +khm_boolean +afs_is_valid_method_id(afs_tk_method method) { + khm_size i; + + if (method == AFS_TOKEN_AUTO || + method == AFS_TOKEN_KRB5 || + method == AFS_TOKEN_KRB524 || + method == AFS_TOKEN_KRB4) + return TRUE; + + for (i=0; i < n_extensions; i++) { + if (extensions[i].provide_token_acq && + extensions[i].token_acq.method_id == method) + return TRUE; + } + + return FALSE; +} + +khm_boolean +afs_method_describe(afs_tk_method method, khm_int32 flags, + wchar_t * wbuf, khm_size cbbuf) { + khm_size idx; + + switch(method) { + case AFS_TOKEN_AUTO: + return LoadString(hResModule, + ((flags & KCDB_TS_SHORT)? + IDS_NC_METHOD_AUTO: + IDS_NC_METHODL_AUTO), + wbuf, (int) cbbuf / sizeof(wchar_t)); + + case AFS_TOKEN_KRB5: + return LoadString(hResModule, + ((flags & KCDB_TS_SHORT)? + IDS_NC_METHOD_KRB5: + IDS_NC_METHODL_KRB5), + wbuf, (int) cbbuf / sizeof(wchar_t)); + + case AFS_TOKEN_KRB524: + return LoadString(hResModule, + ((flags & KCDB_TS_SHORT)? + IDS_NC_METHOD_KRB524: + IDS_NC_METHODL_KRB524), + wbuf, (int) cbbuf / sizeof(wchar_t)); + + case AFS_TOKEN_KRB4: + return LoadString(hResModule, + ((flags & KCDB_TS_SHORT)? + IDS_NC_METHOD_KRB4: + IDS_NC_METHODL_KRB4), + wbuf, (int) cbbuf / sizeof(wchar_t)); + + default: + for (idx = 0; idx < n_extensions; idx++) { + if(!extensions[idx].provide_token_acq || + extensions[idx].token_acq.method_id != method) + continue; + + if ((flags & KCDB_TS_SHORT) || + extensions[idx].token_acq.long_desc == NULL) + return SUCCEEDED(StringCbCopy(wbuf, cbbuf, + extensions[idx].token_acq.short_desc)); + else + return SUCCEEDED(StringCbCopy(wbuf, cbbuf, + extensions[idx].token_acq.long_desc)); + } + } + + return FALSE; +} + +afs_tk_method +afs_get_next_method_id(afs_tk_method method) { + khm_size idx; + + switch(method) { + case -1: + return AFS_TOKEN_AUTO; + case AFS_TOKEN_AUTO: + return AFS_TOKEN_KRB5; + case AFS_TOKEN_KRB5: + return AFS_TOKEN_KRB524; + case AFS_TOKEN_KRB524: + return AFS_TOKEN_KRB4; + case AFS_TOKEN_KRB4: + idx = 0; + break; + default: + for(idx = 0; idx < n_extensions; idx ++) { + if (extensions[idx].provide_token_acq && + extensions[idx].token_acq.method_id == method) + break; + } + idx++; + } + + for(; idx < n_extensions; idx++) { + if (extensions[idx].provide_token_acq) + return extensions[idx].token_acq.method_id; + } + + return -1; +} + +/* not thread safe. only call from the plugin thread */ +afs_extension * +afs_get_next_token_acq(afs_extension * f) { + khm_size idx; + + if (f == NULL) + idx = 0; + else + idx = (f - extensions) + 1; + + for(; idx < n_extensions; idx++) { + if (extensions[idx].provide_token_acq) + return &extensions[idx]; + } + + return NULL; +} + +afs_extension * +afs_get_extension(khm_size i) { + if (i >= n_extensions) + return NULL; + else + return &extensions[i]; +} + +afs_tk_method +afs_get_method_id(wchar_t * name) { + if (!wcscmp(name, AFS_TOKENNAME_AUTO)) + return AFS_TOKEN_AUTO; + else if (!wcscmp(name, AFS_TOKENNAME_KRB5)) + return AFS_TOKEN_KRB5; + else if (!wcscmp(name, AFS_TOKENNAME_KRB524)) + return AFS_TOKEN_KRB524; + else if (!wcscmp(name, AFS_TOKENNAME_KRB4)) + return AFS_TOKEN_KRB4; + else { + khm_size i; + + for (i=0; i < n_extensions; i++) { + if (!extensions[i].provide_token_acq) + continue; + + if (!wcscmp(extensions[i].name, name)) + return extensions[i].token_acq.method_id; + } + } + + return AFS_TOKEN_AUTO; +} + +khm_boolean +afs_get_method_name(afs_tk_method method, wchar_t * buf, khm_size cbbuf) { + if (method == AFS_TOKEN_AUTO) + return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_AUTO)); + else if (method == AFS_TOKEN_KRB5) + return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB5)); + else if (method == AFS_TOKEN_KRB524) + return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB524)); + else if (method == AFS_TOKEN_KRB4) + return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB4)); + else { + khm_size i; + + for (i=0; i < n_extensions; i++) { + if (!extensions[i].provide_token_acq) + continue; + if (extensions[i].token_acq.method_id == method) + return SUCCEEDED(StringCbCopy(buf, cbbuf, + extensions[i].name)); + } + } + + return FALSE; +} + +/* not thread safe. only call from the plugin thread */ +khm_boolean +afs_ext_resolve_token(const wchar_t * cell, + const struct ktc_token * token, + const struct ktc_principal * serverp, + const struct ktc_principal * clientp, + khm_handle * pident, + afs_tk_method * pmethod) { + + afs_msg_resolve_token rt; + khm_size idx; + khm_int32 rv; + + ZeroMemory(&rt, sizeof(rt)); + + rt.cbsize = sizeof(rt); + + rt.cell = cell; + rt.token = token; + rt.serverp = serverp; + rt.clientp = clientp; + rt.method = AFS_TOKEN_AUTO; + rt.ident = NULL; + + for (idx = 0; idx < n_extensions; idx++) { + if (!extensions[idx].provide_token_acq) + continue; + + rv = kmq_send_sub_msg(extensions[idx].sub, + afs_msg_type_id, + AFS_MSG_RESOLVE_TOKEN, + 0, + (void *) &rt); + + if (KHM_SUCCEEDED(rv)) { + assert(rt.ident != NULL); + + *pident = rt.ident; + *pmethod = rt.method; + + return TRUE; + } + } + + return FALSE; +} + +/* not thread safe. only call from the plugin thread */ +khm_boolean +afs_ext_klog(afs_tk_method method, + khm_handle identity, + const char * service, + const char * cell, + const char * realm, + const afs_conf_cell * cell_config, + khm_int32 lifetime) { + + khm_size idx; + khm_int32 rv = KHM_ERROR_GENERAL; + afs_msg_klog msg; + afs_conf_cell cellconfig; + + ZeroMemory(&msg, sizeof(msg)); + ZeroMemory(&cellconfig, sizeof(cellconfig)); + + msg.cbsize = sizeof(msg); + + msg.identity = identity; + msg.service = service; + msg.cell = cell; + msg.realm = realm; + msg.lifetime = lifetime; + + msg.cell_config = &cellconfig; + + cellconfig = *cell_config; + cellconfig.cbsize = sizeof(cellconfig); + + for (idx = 0; idx < n_extensions; idx++) { + if (!extensions[idx].provide_token_acq || + (method != AFS_TOKEN_AUTO && + extensions[idx].token_acq.method_id != method)) + continue; + + rv = kmq_send_sub_msg(extensions[idx].sub, + afs_msg_type_id, + AFS_MSG_KLOG, + 0, + (void *) &msg); + + if (KHM_SUCCEEDED(rv)) + return TRUE; + } + + return FALSE; +} + +khm_int32 KHMAPI +afs_msg_ext(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { + switch(msg_subtype) { + case AFS_MSG_ANNOUNCE: + return afs_add_extension((afs_msg_announce *) vparam); + } + + return KHM_ERROR_SUCCESS; +} diff --git a/src/WINNT/netidmgr_plugin/afsfuncs.c b/src/WINNT/netidmgr_plugin/afsfuncs.c new file mode 100644 index 0000000..f27f323 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsfuncs.c @@ -0,0 +1,1432 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Disable the 'macro redefinition' warning which is getting + triggerred by a redefinition of the ENCRYPT and DECRYPT macros. */ +#pragma warning (push) +#pragma warning (disable: 4005) + +#include +#include +#include + +#pragma warning (pop) + +BOOL +afs_is_running(void) { + DWORD CurrentState; + + if (!AfsAvailable) + return FALSE; + + if (GetServiceStatus(NULL, TRANSARCAFSDAEMON, + &CurrentState, NULL) != NOERROR) + return FALSE; + if (CurrentState != SERVICE_RUNNING) + return FALSE; + + return TRUE; +} + +int +afs_unlog(void) +{ + long rc; + + if (!afs_is_running()) + return 0; + + rc = ktc_ForgetAllTokens(); + + return rc; +} + +int +afs_unlog_cred(khm_handle cred) +{ + long rc; + struct ktc_principal princ; + khm_size cbbuf; + wchar_t name[KCDB_MAXCCH_NAME]; + + if (!afs_is_running()) + return 0; + + cbbuf = sizeof(princ); + if(KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_server_princ, + NULL, &princ, &cbbuf))) + return 1; + + afs_princ_to_string(&princ, name, sizeof(name)); + + _report_cs1(KHERR_INFO, L"Destroying token %1!s!", + _cstr(name)); + _resolve(); + + rc = ktc_ForgetToken(&princ); + + return rc; +} + +/* convert a ktc_principal to a wchar_t string form that looks like + name.instance@cell return 0 if it worked. non-zero otherwise +*/ +int +afs_princ_to_string(struct ktc_principal * p, + wchar_t * buf, + size_t cbbuf) +{ + wchar_t wbuf[256]; + int rv = 0; + int l; + + l = AnsiStrToUnicode(wbuf, sizeof(wbuf), p->name); + wbuf[l] = L'\0'; + + rv = FAILED(StringCbCopy(buf, cbbuf, wbuf)); + if(p->instance[0]) { + StringCbCat(buf, cbbuf, L"."); + if((l = AnsiStrToUnicode(wbuf, sizeof(wbuf), p->instance)) > 0) { + wbuf[l] = L'\0'; + rv = rv || FAILED(StringCbCat(buf, cbbuf, wbuf)); + } + else + rv = 1; + } + if(p->cell[0]) { + rv = rv || FAILED(StringCbCat(buf, cbbuf, L"@")); + if((l = AnsiStrToUnicode(wbuf, sizeof(wbuf), p->cell)) > 0) { + wbuf[l] = L'\0'; + rv = rv || FAILED(StringCbCat(buf, cbbuf, wbuf)); + } + else + rv = 1; + } + + return rv; +} + +int +afs_list_tokens(void) +{ + int r; + + kcdb_credset_flush(afs_credset); + r = afs_list_tokens_internal(); + kcdb_credset_collect(NULL, afs_credset, NULL, afs_credtype_id, NULL); + + return r; +} + +/* is the credential provided an AFS token and is it from the + specified cell? */ +static khm_int32 KHMAPI +afs_filter_by_cell(khm_handle cred, khm_int32 flags, void * rock) +{ + wchar_t wcell[MAXCELLCHARS]; + wchar_t * tcell; + khm_size cbsize; + khm_int32 type; + + tcell = (wchar_t *) rock; + + if(KHM_FAILED(kcdb_cred_get_type(cred, &type)) || + type != afs_credtype_id) + return FALSE; + + cbsize = sizeof(wcell); + if(KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, + NULL, wcell, &cbsize))) + return FALSE; + + if(wcscmp(wcell, tcell)) + return FALSE; + + return TRUE; +} + +struct token_filter_data { + wchar_t * cell; +}; + +khm_int32 KHMAPI +afs_filter_for_token(khm_handle cred, khm_int32 flags, void * rock) { + struct token_filter_data * pdata; + wchar_t ccell[MAXCELLCHARS]; + khm_size cb; + khm_int32 ctype; + + pdata = (struct token_filter_data *) rock; + + if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) || + ctype != afs_credtype_id) + + return 0; + + cb = sizeof(ccell); + + if (KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, + NULL, + ccell, + &cb)) || + _wcsicmp(ccell, pdata->cell)) + + return 0; + + return 1; +} + +khm_handle +afs_find_token(khm_handle credset, wchar_t * cell) { + struct token_filter_data fdata; + khm_handle cred = NULL; + + fdata.cell = cell; + + if (KHM_FAILED(kcdb_credset_find_filtered(credset, + -1, + afs_filter_for_token, + &fdata, + &cred, + NULL))) + return NULL; + else + return cred; +} + +static khm_int32 KHMAPI +afs_filter_krb5_tkt(khm_handle cred, khm_int32 flags, void * rock) +{ + wchar_t cname[KCDB_CRED_MAXCCH_NAME]; + khm_int32 type; + wchar_t * tcell; + wchar_t * t, *tkt_cell; + khm_size cbsize; + + tcell = (wchar_t *) rock; + + if(KHM_FAILED(kcdb_cred_get_type(cred, &type)) || + type != krb5_credtype_id) + return FALSE; + + cbsize = sizeof(cname); + if (KHM_FAILED(kcdb_cred_get_name(cred, cname, &cbsize))) + return FALSE; + + if (!wcsncmp(cname, L"afs/", 4)) { + + tkt_cell = cname + 4; + + t = wcschr(tkt_cell, L'@'); + if (t == NULL) + return FALSE; + *t = L'\0'; + + } else if (!wcsncmp(cname, L"afs@", 4)) { + + tkt_cell = cname + 4; + + } else { + return FALSE; + } + + if (_wcsicmp(tcell, tkt_cell)) + return FALSE; + + return TRUE; +} + +static khm_int32 KHMAPI +afs_filter_krb4_tkt(khm_handle cred, khm_int32 flags, void * rock) +{ + wchar_t cname[KCDB_CRED_MAXCCH_NAME]; + khm_int32 type; + wchar_t * tcell; + wchar_t * t, *tkt_cell; + khm_size cbsize; + + tcell = (wchar_t *) rock; + + if(KHM_FAILED(kcdb_cred_get_type(cred, &type)) || + type != krb4_credtype_id) + return FALSE; + + cbsize = sizeof(cname); + if (KHM_FAILED(kcdb_cred_get_name(cred, cname, &cbsize))) + return FALSE; + + if (!wcsncmp(cname, L"afs.", 4)) { + + tkt_cell = cname + 4; + + t = wcschr(tkt_cell, L'@'); + if (t == NULL) + return FALSE; + *t = L'\0'; + + } else if (!wcsncmp(cname, L"afs@", 4)) { + + tkt_cell = cname + 4; + + } else { + return FALSE; + } + + if (_wcsicmp(tcell, tkt_cell)) + return FALSE; + + return TRUE; +} + +/* collects all AFS tokens to the root credential set using the + generic afs_credset credential set + */ +int +afs_list_tokens_internal(void) +{ + struct ktc_principal aserver; + struct ktc_principal aclient; + struct ktc_token atoken; + int cellNum; + int BreakAtEnd; + wchar_t idname[256]; + wchar_t crname[256]; + wchar_t location[256]; + wchar_t *cell; + + DWORD rc; + + khm_handle ident = NULL; + khm_handle cred = NULL; + afs_tk_method method; + + FILETIME ft; + + if (!afs_is_running()) + return 0; + + kcdb_credset_flush(afs_credset); + + LoadString(hResModule, IDS_DEF_LOCATION, location, ARRAYLENGTH(location)); + + BreakAtEnd = 0; + cellNum = 0; + while (1) + { + memset(&aserver, 0, sizeof(aserver)); + if (rc = ktc_ListTokens(cellNum, &cellNum, &aserver)) + { + if (rc != KTC_NOENT) + return(0); + + if (BreakAtEnd == 1) + break; + } + BreakAtEnd = 1; + memset(&atoken, '\0', sizeof(atoken)); + if (rc = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient)) + { + if (rc == KTC_ERROR) + return(0); + + continue; + } + +#if 0 + /* failed attempt at trying to figure out the principal name from + the token. The ticket that is attached to the token is not + in a form that is useful at this point */ + idname[0] = L'\0'; + if(atoken.kvno == RXKAD_TKT_TYPE_KERBEROS_V5) { + krb5_context ctx = 0; + krb5_ccache cc = 0; + krb5_creds * k5c; + krb5_error_code code; + char * princ; + + code = khm_krb5_initialize(&ctx, &cc); + if(code) + goto _no_krb5; + + k5c = (krb5_creds *) atoken.ticket; + + code = pkrb5_unparse_name(ctx, k5c->client, &princ); + if(code) + goto _no_krb5; + + MultiByteToWideChar(CP_ACP, 0, princ, strlen(princ), idname, sizeof(idname)/sizeof(idname[0])); + + pkrb5_free_unparsed_name(ctx, princ); +_no_krb5: + ; + } +#endif + + method = AFS_TOKEN_AUTO; + + afs_princ_to_string(&aclient, idname, sizeof(idname)); + + /* We need to figure out a good client name which we can use + to create an identity which looks familiar to the user. No + good way of doing this, so we use a heuristic. + + Note that, we use another heuristic to find out which + identity to associate the token with. + + ASSUMPTION: + + The assumption here is that the principal for the token is + computed as follows: + + if realm != cell : principal looks like user@realm@cell + if realm == cell : principal looks like user@realm + + HEURISTIC: + + We strip the part of the string that follows the second '@' + sign to obtain the 'user@realm' part, which we use as the + credential name. If there is no second '@', we use the + whole principal name. */ + { + wchar_t * ats; + + ats = wcschr(idname, L'@'); + if(ats && (ats = wcschr(ats + 1, L'@'))) + *ats = L'\0'; + } + + afs_princ_to_string(&aserver, crname, sizeof(crname)); + + /* Ok, now we need to figure out which identity to associate + this token with. This is a little bit tricky, and there is + currently no good way of determining the original identity + used to obtain the token if it was done outside of + NetIDMgr. So we use a heuristic here. + + REQUIREMENT: + + Elsewhere, (actually in afsnewcreds.c) just after obtaining + AFS tokens through NetIDMgr, we enumerate the AFS tokens + and assign the root identity (used to obtain new creds) + with the AFS tokens. This would still be there in the root + credential set when we list tokens later on. + + HEURISTIC: + + If there exists an AFS token in the root credential set for + the same cell, we associate this token with the same + identity as that credential. + */ + cell = wcschr(crname, L'@'); + if(cell) { + cell++; + if(!*cell) + cell = NULL; + } + + ident = NULL; + if(cell) { + khm_handle c; + + if(KHM_SUCCEEDED(kcdb_credset_find_filtered(NULL, -1, + afs_filter_by_cell, + (void *) cell, + &c, NULL))) { + khm_size cb; + + kcdb_cred_get_identity(c, &ident); + cb = sizeof(method); + kcdb_cred_get_attr(c, afs_attr_method, NULL, + &method, &cb); + kcdb_cred_release(c); + } + } + + /* If that failed, we have try another trick. If there is a + Krb5 ticket of the form afs/@ or afs@ + where matches our cell, then we pick the identity + off of that. + + ASSUMPTION: + + If Krb5 was used to obatain the token, then there is a Krb5 + ticket of the form afs/@ or afs@ still + in the cache. This is also true for Krb524 token + acquisition. + + HEURISTIC: + + If such a Krb5 ticket is found, use the identity of that + credential as the identity of the AFS token. + + */ + if (ident == NULL && cell != NULL) { + khm_handle c; + + if(KHM_SUCCEEDED(kcdb_credset_find_filtered(NULL, -1, + afs_filter_krb5_tkt, + (void *) cell, + &c, NULL))) { + kcdb_cred_get_identity(c, &ident); + /* this could be Krb5 or Krb524, so we leave method at + AFS_TOKEN_AUTO. */ + method = AFS_TOKEN_AUTO; + kcdb_cred_release(c); + } + } + + /* If that didn't work either, we look for a Krb4 ticket of + the form afs.@ or afs@ which matches the + cell. + + ASSUMPTION: + + If Krb4 was used to obtain an AFS token, then there should + be a Krb4 ticket of the form afs.@ or + afs@ in the cache. + + HEURISTIC: + + If such a ticket is found, then use the identity of that + credential as the identity of the AFS token. + */ + if (ident == NULL && cell != NULL) { + khm_handle c; + + if (krb4_credtype_id < 0) { + kcdb_credtype_get_id(KRB4_CREDTYPE_NAME, + &krb4_credtype_id); + } + + if (krb4_credtype_id > 0 && + KHM_SUCCEEDED(kcdb_credset_find_filtered(NULL, -1, + afs_filter_krb4_tkt, + (void *) cell, + &c, NULL))) { + + kcdb_cred_get_identity(c, &ident); + kcdb_cred_release(c); + method = AFS_TOKEN_KRB4; + + } + } + + /* Finally, we allow any extension plugins to give this a shot */ + if (ident == NULL && cell != NULL) { + afs_ext_resolve_token(cell, + &atoken, + &aserver, + &aclient, + &ident, + &method); + } + + /* One more thing to try. If we have a cell->identity + mapping, then we try that. */ + if (ident == NULL && cell != NULL) { + khm_handle h_cellmap; + wchar_t tidname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(tidname); + + if (KHM_SUCCEEDED(khc_open_space(csp_afscred, + L"Cells", 0, + &h_cellmap))) { + if (KHM_SUCCEEDED(khc_read_string(h_cellmap, + cell, + tidname, + &cb))) { + kcdb_identity_create(tidname, + KCDB_IDENT_FLAG_CREATE, + &ident); + } + khc_close_space(h_cellmap); + } + } + + /* all else failed */ + if(ident == NULL) { + if(KHM_FAILED(kcdb_identity_create(idname, + KCDB_IDENT_FLAG_CREATE, + &ident))) + goto _exit; + } + + if(KHM_FAILED(kcdb_cred_create(crname, ident, afs_credtype_id, &cred))) + goto _exit; + + kcdb_cred_set_attr(cred, afs_attr_method, &method, sizeof(method)); + + TimetToFileTime(atoken.endTime, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &ft, sizeof(ft)); + if (atoken.startTime != 0) { + TimetToFileTime(atoken.startTime, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft)); + } + kcdb_cred_set_attr(cred, afs_attr_client_princ, + &aclient, sizeof(aclient)); + kcdb_cred_set_attr(cred, afs_attr_server_princ, + &aserver, sizeof(aserver)); + + if(cell) { + kcdb_cred_set_attr(cred, afs_attr_cell, cell, KCDB_CBSIZE_AUTO); + } + + kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, + location, KCDB_CBSIZE_AUTO); + + kcdb_credset_add_cred(afs_credset, cred, -1); + + /* both these calls are NULL pointer safe */ + kcdb_cred_release(cred); + cred = NULL; + kcdb_identity_release(ident); + ident = NULL; + } + +_exit: + if(ident) + kcdb_identity_release(ident); + if(cred) + kcdb_cred_release(cred); + + return(0); +} + + +#define ALLOW_REGISTER 1 +static int +ViceIDToUsername(char *username, + char *realm_of_user, + char *realm_of_cell, + char * cell_to_use, + struct ktc_principal *aclient, + struct ktc_principal *aserver, + struct ktc_token *atoken) +{ + static char lastcell[MAXCELLCHARS+1] = { 0 }; + static char confname[512] = { 0 }; +#ifdef AFS_ID_TO_NAME + char username_copy[BUFSIZ]; +#endif /* AFS_ID_TO_NAME */ + long viceId = ANONYMOUSID; /* AFS uid of user */ + int status = 0; +#ifdef ALLOW_REGISTER + afs_int32 id; +#endif /* ALLOW_REGISTER */ + + if (confname[0] == '\0') { + StringCbCopyA(confname, sizeof(confname), AFSDIR_CLIENT_ETC_DIRPATH); + } + + StringCbCopyA(lastcell, sizeof(lastcell), aserver->cell); + + if (!pr_Initialize (0, confname, aserver->cell)) { + char sname[PR_MAXNAMELEN]; + StringCbCopyA(sname, sizeof(sname), username); + status = pr_SNameToId (sname, &viceId); + pr_End(); + } + + /* + * This is a crock, but it is Transarc's crock, so + * we have to play along in order to get the + * functionality. The way the afs id is stored is + * as a string in the username field of the token. + * Contrary to what you may think by looking at + * the code for tokens, this hack (AFS ID %d) will + * not work if you change %d to something else. + */ + + /* + * This code is taken from cklog -- it lets people + * automatically register with the ptserver in foreign cells + */ + +#ifdef ALLOW_REGISTER + if (status == 0) { + if (viceId != ANONYMOUSID) { +#else /* ALLOW_REGISTER */ + if ((status == 0) && (viceId != ANONYMOUSID)) +#endif /* ALLOW_REGISTER */ + { +#ifdef AFS_ID_TO_NAME + StringCbCopyA(username_copy, BUFSIZ, username); + StringCchPrintfA(username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId); +#endif /* AFS_ID_TO_NAME */ + } +#ifdef ALLOW_REGISTER + } else if (strcmp(realm_of_user, realm_of_cell) != 0) { + id = 0; + StringCbCopyA(aclient->name, sizeof(aclient->name), username); + StringCbCopyA(aclient->instance, sizeof(aclient->instance), ""); + StringCbCopyA(aclient->cell, sizeof(aclient->cell), realm_of_user); + if (status = ktc_SetToken(aserver, atoken, aclient, 0)) + return status; + if (status = pr_Initialize(1L, confname, aserver->cell)) + return status; + status = pr_CreateUser(username, &id); + pr_End(); + if (status) + return status; +#ifdef AFS_ID_TO_NAME + StringCbCopyA(username_copy, BUFSIZ, username); + StringCchPrintfA(username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId); +#endif /* AFS_ID_TO_NAME */ + } + } +#endif /* ALLOW_REGISTER */ + return status; +} + + +int +afs_klog(khm_handle identity, + char *service, + char *cell, + char *realm, + int LifeTime, + afs_tk_method method, + time_t * tok_expiration) { + + long rc; + CREDENTIALS creds; + struct ktc_principal aserver; + struct ktc_principal aclient; + char realm_of_user[REALM_SZ]; /* Kerberos realm of user */ + char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */ + char local_cell[MAXCELLCHARS+1]; + char Dmycell[MAXCELLCHARS+1]; + struct ktc_token atoken; + struct ktc_token btoken; + afs_conf_cell ak_cellconfig; /* General information about the cell */ + char RealmName[128]; + char CellName[128]; + char ServiceName[128]; + khm_handle confighandle; + khm_int32 supports_krb4 = 1; + + /* signalling */ + BOOL bGotCreds = FALSE; /* got creds? */ + + if (tok_expiration) + *tok_expiration = (time_t) 0; + + if (!afs_is_running()) { + _report_sr0(KHERR_WARNING, IDS_ERR_NOSERVICE); + return(0); + } + + if ( !realm ) realm = ""; + if ( !cell ) cell = ""; + if ( !service ) service = ""; + + memset(RealmName, '\0', sizeof(RealmName)); + memset(CellName, '\0', sizeof(CellName)); + memset(ServiceName, '\0', sizeof(ServiceName)); + memset(realm_of_user, '\0', sizeof(realm_of_user)); + memset(realm_of_cell, '\0', sizeof(realm_of_cell)); + memset(Dmycell, '\0', sizeof(Dmycell)); + + // NULL or empty cell returns information on local cell + if (cell && cell[0]) + StringCbCopyA(Dmycell, sizeof(Dmycell), cell); + + rc = afs_get_cellconfig(Dmycell, &ak_cellconfig, local_cell); + if (rc) { + _reportf(L"afs_get_cellconfig returns %ld", rc); + + _report_sr2(KHERR_ERROR, IDS_ERR_CELLCONFIG, _cstr(Dmycell), _int32(rc)); + _suggest_sr(IDS_ERR_CELLCONFIG_S, KHERR_SUGGEST_NONE); + _resolve(); + return(rc); + } + + StringCbCopyA(realm_of_cell, sizeof(realm_of_cell), + afs_realm_of_cell(&ak_cellconfig)); + + if (strlen(service) == 0) + StringCbCopyA(ServiceName, sizeof(ServiceName), "afs"); + else + StringCbCopyA(ServiceName, sizeof(ServiceName), service); + + if (strlen(cell) == 0) + StringCbCopyA(CellName, sizeof(CellName), local_cell); + else + StringCbCopyA(CellName, sizeof(CellName), cell); + + if (strlen(realm) == 0) + StringCbCopyA(RealmName, sizeof(RealmName), realm_of_cell); + else + StringCbCopyA(RealmName, sizeof(RealmName), realm); + + memset(&creds, '\0', sizeof(creds)); + + /*** Kerberos 5 and 524 ***/ + + if (method == AFS_TOKEN_AUTO || + method == AFS_TOKEN_KRB5 || + method == AFS_TOKEN_KRB524) { + + krb5_context context = 0; + krb5_ccache k5cc = 0; + krb5_creds increds; + krb5_creds * k5creds = 0; + krb5_error_code r; + krb5_principal client_principal = 0; + krb5_flags flags = 0; + + int retry = 0; + int len; + char *p; + + _reportf(L"Trying Kerberos 5"); + + if (!(r = khm_krb5_initialize(identity, &context, &k5cc))) { + int i; + + memset((char *)&increds, 0, sizeof(increds)); + + (*pkrb5_cc_get_principal)(context, k5cc, &client_principal); + i = krb5_princ_realm(context, client_principal)->length; + if (i > REALM_SZ-1) + i = REALM_SZ-1; + StringCchCopyNA(realm_of_user, ARRAYLENGTH(realm_of_user), + krb5_princ_realm(context, client_principal)->data, + i); + } else { + _reportf(L"khm_krb5_initialize returns code %d", r); + goto try_krb4; + } + + /* First try Service/Cell@REALM */ + if (r = (*pkrb5_build_principal)(context, &increds.server, + (int) strlen(RealmName), + RealmName, + ServiceName, + CellName, + 0)) { + _reportf(L"krb5_build_principal returns %d", r); + goto end_krb5; + } + + increds.client = client_principal; + increds.times.endtime = 0; + /* Ask for DES since that is what V4 understands */ + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + +#ifdef KRB5_TC_NOTICKET + flags = 0; + r = pkrb5_cc_set_flags(context, k5cc, flags); +#endif + r = pkrb5_get_credentials(context, 0, k5cc, &increds, &k5creds); + if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || + r == KRB5KRB_ERR_GENERIC /* Heimdal */) { + /* Next try Service@REALM */ + pkrb5_free_principal(context, increds.server); + r = (*pkrb5_build_principal)(context, &increds.server, + (int) strlen(RealmName), + RealmName, + ServiceName, + 0); + if (r == 0) + r = pkrb5_get_credentials(context, 0, k5cc, + &increds, &k5creds); + } + + pkrb5_free_principal(context, increds.server); + pkrb5_free_principal(context, client_principal); + client_principal = 0; +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; + pkrb5_cc_set_flags(context, k5cc, flags); +#endif + + (void) pkrb5_cc_close(context, k5cc); + k5cc = 0; + + if (r) { + _reportf(L"Code %d while getting credentials", r); + goto end_krb5; + } + + if ( k5creds->ticket.length > MAXKTCTICKETLEN || + method == AFS_TOKEN_KRB524) { + goto try_krb524d; + } + + /* This code inserts the entire K5 ticket into the token */ + + _reportf(L"Trying K5 SetToken"); + + memset(&aserver, '\0', sizeof(aserver)); + StringCchCopyA(aserver.name, MAXKTCNAMELEN, ServiceName); + StringCchCopyA(aserver.cell, MAXKTCREALMLEN, CellName); + + memset(&atoken, '\0', sizeof(atoken)); + atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; + atoken.startTime = k5creds->times.starttime; + atoken.endTime = k5creds->times.endtime; + memcpy(&atoken.sessionKey, + k5creds->keyblock.contents, + k5creds->keyblock.length); + atoken.ticketLen = k5creds->ticket.length; + memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen); + + if (tok_expiration) + *tok_expiration = k5creds->times.endtime; + + retry_gettoken5: + rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient); + if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) { + if ( rc == KTC_NOCM && retry < 20 ) { + Sleep(500); + retry++; + goto retry_gettoken5; + } + goto try_krb524d; + } + + if (atoken.kvno == btoken.kvno && + atoken.ticketLen == btoken.ticketLen && + !memcmp(&atoken.sessionKey, &btoken.sessionKey, + sizeof(atoken.sessionKey)) && + !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { + + /* success */ + if (k5creds && context) + pkrb5_free_creds(context, k5creds); + + if (context) + pkrb5_free_context(context); + + _reportf(L"Same token already exists"); + + return 0; + } + + // * Reset the "aclient" structure before we call ktc_SetToken. + // * This structure was first set by the ktc_GetToken call when + // * we were comparing whether identical tokens already existed. + + len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1); + StringCchCopyNA(aclient.name, MAXKTCNAMELEN, + k5creds->client->data[0].data, len); + + if ( k5creds->client->length > 1 ) { + StringCbCatA(aclient.name, sizeof(aclient.name), "."); + p = aclient.name + strlen(aclient.name); + len = (int) min(k5creds->client->data[1].length, + MAXKTCNAMELEN - strlen(aclient.name) - 1); + StringCchCopyNA(p, MAXKTCNAMELEN - strlen(aclient.name), + k5creds->client->data[1].data, len); + } + + aclient.instance[0] = '\0'; + + StringCbCopyA(aclient.cell, sizeof(aclient.cell), realm_of_cell); + + StringCbCatA(aclient.name, sizeof(aclient.name), "@"); + p = aclient.name + strlen(aclient.name); + len = (int) min(k5creds->client->realm.length, + MAXKTCNAMELEN - strlen(aclient.name) - 1); + StringCchCopyNA(p, MAXKTCNAMELEN - strlen(aclient.name), + k5creds->client->realm.data, len); + + ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, + &aclient, &aserver, &atoken); + + rc = ktc_SetToken(&aserver, &atoken, &aclient, 0); + if (!rc) { + /* success */ + + if (k5creds && context) + pkrb5_free_creds(context, k5creds); + + if (context) + pkrb5_free_context(context); + + return 0; + } + + _reportf(L"SetToken returns code %d", rc); + + try_krb524d: + + _reportf(L"Trying Krb524"); + + if (method == AFS_TOKEN_AUTO || + method == AFS_TOKEN_KRB524) { + /* This requires krb524d to be running with the KDC */ + r = pkrb524_convert_creds_kdc(context, k5creds, &creds); + if (r) { + _reportf(L"Code %d while converting credentials", r); + goto end_krb5; + } + rc = KSUCCESS; + bGotCreds = TRUE; + } + + end_krb5: + if (client_principal) + pkrb5_free_principal(context, client_principal); + + if (k5creds && context) + pkrb5_free_creds(context, k5creds); + + if (context) + pkrb5_free_context(context); + } + + /* Kerberos 4 */ + try_krb4: + + kcdb_identity_get_config(identity, 0, &confighandle); + khc_read_int32(confighandle, L"Krb4Cred\\Krb4NewCreds", &supports_krb4); + khc_close_space(confighandle); + + if (!supports_krb4) { + _reportf(L"Kerberos 4 not configured"); + } + + if (!bGotCreds && supports_krb4 && + (method == AFS_TOKEN_AUTO || + method == AFS_TOKEN_KRB4)) { + + KTEXT_ST ticket; + + _reportf(L"Trying Kerberos 4"); + + if (!realm_of_user[0] ) { + if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) + != KSUCCESS) { + /* can't determine realm of user */ + _reportf(L"krb_get_tf_realm returns %d", rc); + goto end_krb4; + } + } + + _reportf(L"Trying to find %S.%S@%S", ServiceName, CellName, RealmName); + rc = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds); + if (rc == NO_TKT_FIL) { + // if the problem is that we have no krb4 tickets + // do not attempt to continue + _reportf(L"krb_get_cred returns %d (no ticket file)", rc); + goto end_krb4; + } + + if (rc != KSUCCESS) { + _reportf(L"Trying to find %S@%S", ServiceName, RealmName); + rc = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds); + } + + if (rc != KSUCCESS) { + _reportf(L"Trying to obtain new ticket"); + if ((rc = (*pkrb_mk_req)(&ticket, ServiceName, + CellName, RealmName, 0)) + == KSUCCESS) { + if ((rc = (*pkrb_get_cred)(ServiceName, CellName, + RealmName, &creds)) != KSUCCESS) { + goto end_krb4; + } else { + _reportf(L"Got %S.%S@%S", ServiceName, CellName, RealmName); + } + } else if ((rc = (*pkrb_mk_req)(&ticket, ServiceName, + "", RealmName, 0)) + == KSUCCESS) { + if ((rc = (*pkrb_get_cred)(ServiceName, "", + RealmName, &creds)) != KSUCCESS) { + goto end_krb4; + } else { + _reportf(L"Got %S@%S", ServiceName, RealmName); + } + } else { + goto end_krb4; + } + } + + bGotCreds = TRUE; + + end_krb4: + ; + } + + if (bGotCreds) { + + memset(&aserver, '\0', sizeof(aserver)); + StringCchCopyA(aserver.name, MAXKTCNAMELEN, ServiceName); + StringCchCopyA(aserver.cell, MAXKTCREALMLEN, CellName); + + memset(&atoken, '\0', sizeof(atoken)); + atoken.kvno = creds.kvno; + atoken.startTime = creds.issue_date; + atoken.endTime = (*pkrb_life_to_time)(creds.issue_date,creds.lifetime); + memcpy(&atoken.sessionKey, creds.session, 8); + atoken.ticketLen = creds.ticket_st.length; + memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen); + + if (tok_expiration) + *tok_expiration = atoken.endTime; + + if (!(rc = ktc_GetToken(&aserver, &btoken, + sizeof(btoken), &aclient)) && + atoken.kvno == btoken.kvno && + atoken.ticketLen == btoken.ticketLen && + !memcmp(&atoken.sessionKey, &btoken.sessionKey, + sizeof(atoken.sessionKey)) && + !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { + + /* success! */ + return(0); + } + + // Reset the "aclient" structure before we call ktc_SetToken. + // This structure was first set by the ktc_GetToken call when + // we were comparing whether identical tokens already existed. + + StringCchCopyA(aclient.name, MAXKTCNAMELEN, creds.pname); + if (creds.pinst[0]) { + StringCchCatA(aclient.name, MAXKTCNAMELEN, "."); + StringCchCatA(aclient.name, MAXKTCNAMELEN, creds.pinst); + } + + StringCbCopyA(aclient.instance, sizeof(aclient.instance), ""); + + StringCchCatA(aclient.name, MAXKTCNAMELEN, "@"); + StringCchCatA(aclient.name, MAXKTCNAMELEN, creds.realm); + + StringCbCopyA(aclient.cell, sizeof(aclient.cell), CellName); + + ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, + &aclient, &aserver, &atoken); + + // NOTE: On WIN32, the order of SetToken params changed... + // to ktc_SetToken(&aserver, &aclient, &atoken, 0) + // from ktc_SetToken(&aserver, &atoken, &aclient, 0) on + // Unix... The afscompat ktc_SetToken provides the Unix order + + if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0)) { + afs_report_error(rc, "ktc_SetToken()"); + return(rc); + } + } else if (method == AFS_TOKEN_AUTO || + method >= AFS_TOKEN_USER) { + /* we couldn't get a token using Krb5, Krb524 or Krb4, either + because we couldn't get the necessary credentials or + because the method was set to not use those. Now we + dispatch to any extensions to see if they have better + luck. */ + + rc = !afs_ext_klog(method, + identity, + ServiceName, + CellName, + RealmName, + &ak_cellconfig, + LifeTime); + } else { + /* if the return code was not set, we should set it now. + Otherwise we let the code go through. */ + if (!rc) { + /* No tokens were obtained. We should report something */ + _report_sr1(KHERR_ERROR, IDS_ERR_GENERAL, + _cptr(CellName)); + _resolve(); + + rc = KHM_ERROR_GENERAL; + } + } + + return rc; +} + +/**************************************/ +/* afs_realm_of_cell(): */ +/**************************************/ +static char * +afs_realm_of_cell(afs_conf_cell *cellconfig) +{ + char krbhst[MAX_HSTNM]=""; + static char krbrlm[REALM_SZ+1]=""; + krb5_context ctx = 0; + char ** realmlist=NULL; + krb5_error_code r; + + if (!cellconfig) + return 0; + + if ( pkrb5_init_context ) { + r = pkrb5_init_context(&ctx); + if ( !r ) + r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist); + if ( !r && realmlist && realmlist[0] ) { + StringCbCopyA(krbrlm, sizeof(krbrlm), realmlist[0]); + pkrb5_free_host_realm(ctx, realmlist); + } + if (ctx) + pkrb5_free_context(ctx); + } + + if ( !krbrlm[0] ) { + StringCbCopyA(krbrlm, sizeof(krbrlm), + (char *)(*pkrb_realmofhost)(cellconfig->hostName[0])); + if ((*pkrb_get_krbhst)(krbhst, krbrlm, 1) != KSUCCESS) + krbrlm[0] = '\0'; + } + + if ( !krbrlm[0] ) { + char *s = krbrlm; + char *t = cellconfig->name; + int c; + + while (c = *t++) + { + if (islower(c)) c=toupper(c); + *s++ = c; + } + *s++ = 0; + } + return(krbrlm); +} + +/**************************************/ +/* afs_get_cellconfig(): */ +/**************************************/ +static int +afs_get_cellconfig(char *cell, afs_conf_cell *cellconfig, char *local_cell) +{ + int rc; + int ttl; + + local_cell[0] = (char)0; + memset(cellconfig, 0, sizeof(*cellconfig)); + + cellconfig->cbsize = sizeof(*cellconfig); + + /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */ + if (rc = cm_GetRootCellName(local_cell)) { + return(rc); + } + + if (strlen(cell) == 0) + StringCbCopyA(cell, (MAXCELLCHARS+1) * sizeof(char), local_cell); + + /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */ + StringCbCopyA(cellconfig->name, (MAXCELLCHARS+1) * sizeof(char), cell); + + rc = cm_SearchCellFile(cell, NULL, afs_get_cellconfig_callback, + (void*)cellconfig); + if(rc) + rc = cm_SearchCellByDNS(cell, NULL, &ttl, + afs_get_cellconfig_callback, + (void*) cellconfig); + + return rc; +} + +/**************************************/ +/* afs_get_cellconfig_callback(): */ +/**************************************/ +static long +afs_get_cellconfig_callback(void *cellconfig, + struct sockaddr_in *addrp, + char *namep) +{ + afs_conf_cell *cc = (afs_conf_cell *)cellconfig; + + cc->hostAddr[cc->numServers] = *addrp; + StringCbCopyA(cc->hostName[cc->numServers], + sizeof(cc->hostName[0]), namep); + cc->numServers++; + return(0); +} + + +/**************************************/ +/* afs_report_error(): */ +/**************************************/ +void +afs_report_error(LONG rc, LPCSTR FailedFunctionName) +{ + char message[256]; + const char *errText; + + // Using AFS defines as error messages for now, until Transarc + // gets back to me with "string" translations of each of these + // const. defines. + if (rc == KTC_ERROR) + errText = "KTC_ERROR"; + else if (rc == KTC_TOOBIG) + errText = "KTC_TOOBIG"; + else if (rc == KTC_INVAL) + errText = "KTC_INVAL"; + else if (rc == KTC_NOENT) + errText = "KTC_NOENT"; + else if (rc == KTC_PIOCTLFAIL) + errText = "KTC_PIOCTLFAIL"; + else if (rc == KTC_NOPIOCTL) + errText = "KTC_NOPIOCTL"; + else if (rc == KTC_NOCELL) + errText = "KTC_NOCELL"; + else if (rc == KTC_NOCM) + errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!"; + else + errText = "Unknown error!"; + + StringCbPrintfA(message, sizeof(message), + "%s\n(%s failed)", errText, FailedFunctionName); + _report_cs1(KHERR_ERROR, L"%1!S!", _cptr(message)); + _resolve(); + return; +} + +DWORD +GetServiceStatus(LPSTR lpszMachineName, + LPSTR lpszServiceName, + DWORD *lpdwCurrentState, + DWORD *lpdwWaitHint) +{ + DWORD hr = NOERROR; + SC_HANDLE schSCManager = NULL; + SC_HANDLE schService = NULL; + DWORD fdwDesiredAccess = 0; + SERVICE_STATUS ssServiceStatus = {0}; + BOOL fRet = FALSE; + + *lpdwCurrentState = 0; + + fdwDesiredAccess = GENERIC_READ; + + schSCManager = OpenSCManagerA(lpszMachineName, + NULL, + fdwDesiredAccess); + + if(schSCManager == NULL) { + hr = GetLastError(); + goto cleanup; + } + + schService = OpenServiceA(schSCManager, + lpszServiceName, + fdwDesiredAccess); + + if(schService == NULL) { + hr = GetLastError(); + goto cleanup; + } + + fRet = QueryServiceStatus(schService, + &ssServiceStatus); + + if(fRet == FALSE) { + hr = GetLastError(); + goto cleanup; + } + + *lpdwCurrentState = ssServiceStatus.dwCurrentState; + if (lpdwWaitHint) + *lpdwWaitHint = ssServiceStatus.dwWaitHint; +cleanup: + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + + return(hr); +} + +DWORD ServiceControl(LPSTR lpszMachineName, + LPSTR lpszServiceName, + DWORD dwNewState) { + + DWORD hr = NOERROR; + SC_HANDLE schSCManager = NULL; + SC_HANDLE schService = NULL; + DWORD fdwDesiredAccess = 0; + SERVICE_STATUS ssServiceStatus = {0}; + BOOL fRet = FALSE; + DWORD dwCurrentState = 0; + + dwCurrentState = 0; + + fdwDesiredAccess = GENERIC_READ; + + schSCManager = OpenSCManagerA(lpszMachineName, NULL, + fdwDesiredAccess); + + if(schSCManager == NULL) { + hr = GetLastError(); + goto cleanup; + } + + fdwDesiredAccess = GENERIC_READ | GENERIC_EXECUTE; + + schService = OpenServiceA(schSCManager, lpszServiceName, + fdwDesiredAccess); + + if(schService == NULL) { + hr = GetLastError(); + goto cleanup; + } + + fRet = QueryServiceStatus(schService, &ssServiceStatus); + + if(fRet == FALSE) { + hr = GetLastError(); + goto cleanup; + } + + dwCurrentState = ssServiceStatus.dwCurrentState; + + if (dwCurrentState == SERVICE_STOPPED && + dwNewState == SERVICE_RUNNING) { + + fRet = StartService(schService, 0, NULL); + + if (fRet == FALSE) { + hr = GetLastError(); + goto cleanup; + } + } + + if (dwCurrentState == SERVICE_RUNNING && + dwNewState == SERVICE_STOPPED) { + fRet = ControlService(schService, SERVICE_CONTROL_STOP, + &ssServiceStatus); + + if (fRet == FALSE) { + hr = GetLastError(); + goto cleanup; + } + } + +cleanup: + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + + return(hr); +} diff --git a/src/WINNT/netidmgr_plugin/afsfuncs.h b/src/WINNT/netidmgr_plugin/afsfuncs.h new file mode 100644 index 0000000..6a163cd --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsfuncs.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_AFSFUNCS_H +#define __KHIMAIRA_AFSFUNCS_H + + +BOOL +afs_is_running(void); + +int +afs_princ_to_string(struct ktc_principal * p, wchar_t * buf, size_t cbbuf); + +int +afs_list_tokens(void); + +khm_handle +afs_find_token(khm_handle credset, wchar_t * cell); + +int +afs_list_tokens_internal(void); + +int +afs_klog(khm_handle identity, + char *service, + char *cell, + char *realm, + int LifeTime, + afs_tk_method method, + time_t * tok_expiration /* OUT: expiration time of new + token */ + ); + +int +afs_unlog(void); + +int +afs_unlog_cred(khm_handle cred); + +DWORD +GetServiceStatus(LPSTR lpszMachineName, + LPSTR lpszServiceName, + DWORD *lpdwCurrentState, + DWORD *lpdwWaitHint); + +DWORD +ServiceControl(LPSTR lpszMachineName, + LPSTR lpszServiceName, + DWORD dwNewState); + +void afs_report_error(LONG rc, LPCSTR FailedFunctionName); + +static char *afs_realm_of_cell(afs_conf_cell *); +static long afs_get_cellconfig_callback(void *, struct sockaddr_in *, char *); +static int afs_get_cellconfig(char *, afs_conf_cell *, char *); + +#endif diff --git a/src/WINNT/netidmgr_plugin/afshelp.c b/src/WINNT/netidmgr_plugin/afshelp.c new file mode 100644 index 0000000..e143c06 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afshelp.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#define NOSTRSAFE + +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#include + +static wchar_t helpfile[MAX_PATH] = L""; + +/* can only be called from the UI thread */ +HWND +afs_html_help(HWND caller, + wchar_t * postfix, + UINT cmd, + DWORD_PTR data) { + + wchar_t fullp[MAX_PATH + MAX_PATH]; + + if (!helpfile[0]) { + DWORD rv; + + rv = GetModuleFileNameEx(GetCurrentProcess(), + hInstance, + helpfile, + ARRAYLENGTH(helpfile)); +#ifdef DEBUG + assert(rv != 0); +#endif + PathRemoveFileSpec(helpfile); + PathAppend(helpfile, AFS_HELPFILE); + } + + StringCbCopy(fullp, sizeof(fullp), helpfile); + if (postfix) + StringCbCat(fullp, sizeof(fullp), postfix); + + return HtmlHelp(caller, fullp, cmd, data); +} diff --git a/src/WINNT/netidmgr_plugin/afsnewcreds.c b/src/WINNT/netidmgr_plugin/afsnewcreds.c new file mode 100644 index 0000000..e35c347 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsnewcreds.c @@ -0,0 +1,2781 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include + +/* UI stuff */ + +#define WMNC_AFS_UPDATE_ROWS (WMNC_USER + 1) + +typedef struct tag_afs_ident_token_set { + khm_handle ident; + afs_cred_list * l; + khm_boolean add_new; + khm_boolean update_info; +} afs_ident_token_set; + + +void +afs_cred_flush_rows(afs_cred_list * l) { + int i; + + for(i=0; in_rows; i++) { + if(l->rows[i].cell) + PFREE(l->rows[i].cell); + if(l->rows[i].realm) + PFREE(l->rows[i].realm); + } + + if(l->nc_rows) { + ZeroMemory(l->rows, sizeof(l->rows[0]) * l->nc_rows); + } + + l->n_rows = 0; +} + +void +afs_cred_free_rows(afs_cred_list * l) { + + afs_cred_flush_rows(l); + + if(l->rows) + PFREE(l->rows); + l->rows = NULL; + l->n_rows = 0; + l->nc_rows = 0; +} + +void +afs_cred_assert_rows(afs_cred_list * l, int n) { + afs_cred_row * rows; + + if(n > l->nc_rows) { + l->nc_rows = UBOUNDSS(n, AFS_DLG_ROW_ALLOC, AFS_DLG_ROW_ALLOC); + rows = PMALLOC(sizeof(afs_cred_row) * l->nc_rows); + ZeroMemory(rows, sizeof(afs_cred_row) * l->nc_rows); + + if(l->rows) { + if(l->n_rows) + memcpy(rows, l->rows, sizeof(afs_cred_row) * l->n_rows); + PFREE(l->rows); + } + l->rows = rows; + } +} + +void +afs_cred_delete_row(afs_cred_list * l, int i) { + if (i < 0 || i >= l->n_rows) + return; + + if(i < (l->n_rows - 1)) { + if(l->rows[i].cell) + PFREE(l->rows[i].cell); + if(l->rows[i].realm) + PFREE(l->rows[i].realm); + memmove(&(l->rows[i]), + &(l->rows[i+1]), + ((l->n_rows - (i+1)) * + sizeof(l->rows[0]))); + } + l->n_rows--; +} + +afs_cred_row * +afs_cred_get_new_row(afs_cred_list * l) { + afs_cred_row * r; + + afs_cred_assert_rows(l, l->n_rows + 1); + r = &(l->rows[l->n_rows]); + l->n_rows++; + + ZeroMemory(r, sizeof(*r)); + + return r; +} + +afs_cred_row * +afs_cred_add_row_from_cred(afs_cred_list * l, + khm_handle cred) { + khm_int32 rv; + afs_cred_row * row; + khm_size cb; + wchar_t cell[MAXCELLCHARS]; + int i; + + cb = sizeof(cell); + rv = kcdb_cred_get_attr(cred, + afs_attr_cell, + NULL, + cell, + &cb); +#ifdef DEBUG + assert(rv == KHM_ERROR_SUCCESS && cb != 0); +#endif + + /* check if we already have the cell listed. */ + for (i=0; in_rows; i++) { + if (!_wcsicmp(l->rows[i].cell, cell)) + return &l->rows[i]; + } + + row = afs_cred_get_new_row(l); + + row->cell = PMALLOC(cb); + StringCbCopy(row->cell, cb, cell); + + cb = sizeof(row->method); + rv = kcdb_cred_get_attr(cred, + afs_attr_method, + NULL, + &row->method, + &cb); + + if (KHM_FAILED(rv)) { + row->method = AFS_TOKEN_AUTO; + row->realm = NULL; + return row; + } + + rv = kcdb_cred_get_attr(cred, + afs_attr_realm, + NULL, + NULL, + &cb); + + if (rv == KHM_ERROR_TOO_LONG && cb > sizeof(wchar_t)) { + row->realm = PMALLOC(cb); +#ifdef DEBUG + assert(row->realm); +#endif + rv = kcdb_cred_get_attr(cred, + afs_attr_realm, + NULL, + row->realm, + &cb); + + if (KHM_FAILED(rv)) { + if (row->realm) + PFREE(row->realm); + row->realm = NULL; + } + } else { + row->realm = NULL; + } + + return row; +} + +khm_int32 KHMAPI +afs_cred_add_cred_proc(khm_handle cred, void * rock) { + afs_cred_list * l = (afs_cred_list *) rock; + khm_int32 t; + + if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) || + t != afs_credtype_id) + return KHM_ERROR_SUCCESS; + + afs_cred_add_row_from_cred(l, cred); + + return KHM_ERROR_SUCCESS; +} + +void +afs_cred_get_context_creds(afs_cred_list *l, + khui_action_context * ctx) { + khm_handle credset = NULL; + + if (KHM_FAILED(kcdb_credset_create(&credset))) + return; + + if (KHM_FAILED(kcdb_credset_extract_filtered(credset, + NULL, + khui_context_cursor_filter, + (void *) ctx))) + goto _cleanup; + + kcdb_credset_apply(credset, + afs_cred_add_cred_proc, + (void *) l); + + _cleanup: + if (credset) + kcdb_credset_delete(credset); +} + +khm_int32 KHMAPI +afs_get_id_creds_apply_proc(khm_handle cred, void * rock) { + khm_int32 t; + afs_ident_token_set * ts; + afs_cred_list * l; + khm_handle ident; + wchar_t cell[MAXCELLCHARS]; + khm_size cb; + int i; + khm_int32 cflags = 0; + + ts = (afs_ident_token_set *) rock; + l = ts->l; + + kcdb_cred_get_type(cred, &t); + if (t != afs_credtype_id) + return KHM_ERROR_SUCCESS; + + cb = sizeof(cell); + if (KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, + NULL, + cell, &cb))) + return KHM_ERROR_SUCCESS; + + kcdb_cred_get_flags(cred, &cflags); + + kcdb_cred_get_identity(cred, &ident); + + if (kcdb_identity_is_equal(ident, ts->ident)) { + + for (i=0; i < l->n_rows; i++) { + if (!_wcsicmp(l->rows[i].cell, cell)) { + khm_int32 method; + + /* if the token exists, then these are implied */ + l->rows[i].flags = + DLGROW_FLAG_EXISTS | + DLGROW_FLAG_CHECKED | + DLGROW_FLAG_VALID; + + if (cflags & KCDB_CRED_FLAG_EXPIRED) + l->rows[i].flags |= DLGROW_FLAG_EXPIRED; + + if (ts->update_info) { + wchar_t realm[KHUI_MAXCCH_NAME]; + + cb = sizeof(method); + if (KHM_SUCCEEDED + (kcdb_cred_get_attr(cred, afs_attr_method, + NULL, + &method, &cb)) && + afs_is_valid_method_id(method)) + l->rows[i].method = method; + + cb = sizeof(realm); + if (KHM_SUCCEEDED + (kcdb_cred_get_attr(cred, afs_attr_realm, + NULL, + realm, &cb)) && + cb > sizeof(wchar_t)) { + + if (l->rows[i].realm) + PFREE(l->rows[i].realm); + l->rows[i].realm = PMALLOC(cb); + StringCbCopy(l->rows[i].realm, + cb, + realm); + } + } + break; + } + } + + /* not found? add! */ + if (i >= l->n_rows && ts->add_new) { + afs_cred_row * r; + + r = afs_cred_add_row_from_cred(l, cred); + + r->flags = DLGROW_FLAG_VALID | DLGROW_FLAG_CHECKED | + DLGROW_FLAG_EXISTS; + + if (cflags & KCDB_CRED_FLAG_EXPIRED) + r->flags |= DLGROW_FLAG_EXPIRED; + } + + } else { /* different identities */ + + for (i=0; i < l->n_rows; i++) { + if (!_wcsicmp(l->rows[i].cell, cell)) { + l->rows[i].flags = + DLGROW_FLAG_NOTOWNED | DLGROW_FLAG_EXISTS | + DLGROW_FLAG_VALID | DLGROW_FLAG_CHECKED; + if (cflags & KCDB_CRED_FLAG_EXPIRED) + l->rows[i].flags |= DLGROW_FLAG_EXPIRED; + } + } + + } + + kcdb_identity_release(ident); + + return KHM_ERROR_SUCCESS; +} + +void +afs_remove_token_from_identities(wchar_t * cell) { + wchar_t * idents = NULL; + wchar_t * t; + khm_size cb_id; + khm_size n_id = 0; + + do { + if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + NULL, + &cb_id, + &n_id) != KHM_ERROR_TOO_LONG || + n_id == 0) { + if (idents) + PFREE(idents); + return; + } + + if (idents) + PFREE(idents); + idents = PMALLOC(cb_id); + + if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + idents, + &cb_id, + &n_id) == KHM_ERROR_SUCCESS) + break; + } while(TRUE); + + for (t=idents; + t && *t; + t = multi_string_next(t)) { + + khm_handle h_id = NULL; + khm_handle csp_ident = NULL; + khm_handle csp_afs = NULL; + khm_size cb; + wchar_t vbuf[1024]; + wchar_t * tbuf = NULL; + + kcdb_identity_create(t, 0, &h_id); + if (h_id == NULL) { +#ifdef DEBUG + assert(FALSE); +#endif + continue; + } + + if (KHM_FAILED(kcdb_identity_get_config(h_id, 0, &csp_ident))) + goto _cleanup_loop; + + if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_AFSCRED, + 0, &csp_afs))) + goto _cleanup_loop; + + if (khc_read_multi_string(csp_afs, L"Cells", NULL, &cb) + != KHM_ERROR_TOO_LONG) + goto _cleanup_loop; + + if (cb < sizeof(vbuf)) + tbuf = vbuf; + else + tbuf = PMALLOC(cb); + + if (khc_read_multi_string(csp_afs, L"Cells", tbuf, &cb) + != KHM_ERROR_SUCCESS) + goto _cleanup_loop; + + if (multi_string_find(tbuf, cell, 0) == NULL) + goto _cleanup_loop; + + multi_string_delete(tbuf, cell, 0); + + khc_write_multi_string(csp_afs, L"Cells", tbuf); + + _cleanup_loop: + kcdb_identity_release(h_id); + if (csp_ident) + khc_close_space(csp_ident); + if (csp_afs) + khc_close_space(csp_afs); + if (tbuf && tbuf != vbuf) + PFREE(tbuf); + } + + if (idents) + PFREE(idents); +} + +khm_boolean +afs_check_add_token_to_identity(wchar_t * cell, khm_handle ident, + khm_handle * ident_conflict) { + wchar_t * idents = NULL; + wchar_t * t; + khm_size cb_id; + khm_size n_id = 0; + khm_boolean ok_to_add = TRUE; + + /* check if this cell is listed for any other identity. */ + + do { + if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + NULL, + &cb_id, + &n_id) != KHM_ERROR_TOO_LONG || + n_id == 0) { + if (idents) + PFREE(idents); + return TRUE; + } + + if (idents) + PFREE(idents); + idents = PMALLOC(cb_id); + + if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG, + KCDB_IDENT_FLAG_CONFIG, + idents, + &cb_id, + &n_id) == KHM_ERROR_SUCCESS) + break; + } while(TRUE); + + for (t=idents; + ok_to_add && t && *t; + t = multi_string_next(t)) { + + khm_handle h_id = NULL; + khm_handle csp_ident = NULL; + khm_handle csp_afs = NULL; + khm_size cb; + wchar_t vbuf[1024]; + wchar_t * tbuf = NULL; + + kcdb_identity_create(t, 0, &h_id); + if (h_id == NULL) { +#ifdef DEBUG + assert(FALSE); +#endif + continue; + } + + if (kcdb_identity_is_equal(h_id, ident)) { + kcdb_identity_release(h_id); + continue; + } + + if (KHM_FAILED(kcdb_identity_get_config(h_id, 0, &csp_ident))) + goto _cleanup_loop; + + if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_AFSCRED, + 0, &csp_afs))) + goto _cleanup_loop; + + if (khc_read_multi_string(csp_afs, L"Cells", NULL, &cb) + != KHM_ERROR_TOO_LONG) + goto _cleanup_loop; + + if (cb < sizeof(vbuf)) + tbuf = vbuf; + else + tbuf = PMALLOC(cb); + + if (khc_read_multi_string(csp_afs, L"Cells", tbuf, &cb) + != KHM_ERROR_SUCCESS) + goto _cleanup_loop; + + if (multi_string_find(tbuf, cell, 0) == NULL) + goto _cleanup_loop; + + /* we found another identity which gets tokens for the + same cell */ + + ok_to_add = FALSE; + + if (ident_conflict) { + *ident_conflict = h_id; + kcdb_identity_hold(h_id); + } + + _cleanup_loop: + kcdb_identity_release(h_id); + if (csp_ident) + khc_close_space(csp_ident); + if (csp_afs) + khc_close_space(csp_afs); + if (tbuf && tbuf != vbuf) + PFREE(tbuf); + } + + if (idents) + PFREE(idents); + + return ok_to_add; +} + +void +afs_cred_get_identity_creds(afs_cred_list * l, + khm_handle ident, + khm_boolean * penabled) { + khm_handle h_id = NULL; + khm_handle h_afs = NULL; + khm_handle h_cells = NULL; /* per identity cells space */ + khm_handle h_gcells = NULL; /* global cells space */ + khm_boolean load_defs = TRUE; + khm_size cbi; + wchar_t * ms = NULL; + wchar_t * s = NULL; + afs_ident_token_set ts; + khm_int32 t; + + if (penabled) + *penabled = TRUE; + + afs_cred_flush_rows(l); + + kcdb_identity_get_config(ident, 0, &h_id); + if(!h_id) + goto _done_config; + + if(KHM_FAILED(khc_open_space(h_id, CSNAME_AFSCRED, + 0, &h_afs))) + goto _done_config; + + if (penabled) { + t = 1; + if (KHM_FAILED(khc_read_int32(h_afs, L"AFSEnabled", &t))) + khc_read_int32(csp_params, L"AFSEnabled", &t); + *penabled = !!t; + } + + if(KHM_FAILED(khc_open_space(h_afs, L"Cells", + 0, &h_cells))) + goto _done_config; + + if(khc_read_multi_string(h_afs, L"Cells", NULL, &cbi) != + KHM_ERROR_TOO_LONG) + goto _done_config; + + load_defs = FALSE; + + ms = PMALLOC(cbi); + ZeroMemory(ms, cbi); + + khc_read_multi_string(h_afs, L"Cells", ms, &cbi); + + s = ms; + for(s = ms; s && *s; s = multi_string_next(s)) { + afs_cred_row * r; + size_t cb; + khm_handle h_cell = NULL; + + /* is this a valid cell name? */ + if(FAILED(StringCbLength(s, MAXCELLCHARS, &cb))) + continue; + cb += sizeof(wchar_t); + + r = afs_cred_get_new_row(l); + + r->cell = PMALLOC(cb); + StringCbCopy(r->cell, cb, s); + + r->realm = NULL; + r->method = 0; + r->flags = 0; + + if(KHM_SUCCEEDED(khc_open_space(h_cells, s, + 0, &h_cell))) { + khm_int32 i; + wchar_t wname[KHUI_MAXCCH_NAME]; + khm_size cb; + + if(khc_read_string(h_cell, L"Realm", + NULL, &cbi) == + KHM_ERROR_TOO_LONG && + cbi > sizeof(wchar_t)) { + + r->realm = PMALLOC(cbi); + khc_read_string(h_cell, L"Realm", r->realm, &cbi); + } + + i = AFS_TOKEN_AUTO; + + cb = sizeof(wname); + if (KHM_SUCCEEDED(khc_read_string(h_cell, L"MethodName", + wname, &cb))) { + + r->method = afs_get_method_id(wname); + + /* remove the deprecated value if it is present. */ + khc_remove_value(h_cell, L"Method", 0); + + } else if (KHM_SUCCEEDED(khc_read_int32(h_cell, + L"Method", &i))) { + /* the Method property is deprecated. We detect and + correct this whenever possible. */ + + if (!afs_is_valid_method_id(i)) + i = AFS_TOKEN_AUTO; + + r->method = i; + + afs_get_method_name(i, wname, sizeof(wname)); + + khc_write_string(h_cell, L"MethodName", + wname); + + khc_remove_value(h_cell, L"Method", 0); + } + + khc_close_space(h_cell); + } + } + + if(ms) { + PFREE(ms); + ms = NULL; + } + + _done_config: + + if (load_defs) { + /* We want to load defaults */ + char buf[MAXCELLCHARS]; + wchar_t wbuf[MAXCELLCHARS]; + wchar_t wmethod[KHUI_MAXCCH_NAME]; + wchar_t * defcells; + khm_size cb_defcells; + afs_cred_row * r; + khm_size sz; + + khc_open_space(csp_params, L"Cells", 0, &h_gcells); + + if(!cm_GetRootCellName(buf)) { + AnsiStrToUnicode(wbuf, sizeof(wbuf), buf); + + if (afs_check_add_token_to_identity(wbuf, ident, NULL)) { + khm_handle h_cell = NULL; + + r = afs_cred_get_new_row(l); + + StringCbLength(wbuf, sizeof(wbuf), &sz); + sz += sizeof(wchar_t); + + r->cell = PMALLOC(sz); + StringCbCopy(r->cell, sz, wbuf); + + if (h_gcells && + KHM_SUCCEEDED(khc_open_space(h_gcells, wbuf, 0, &h_cell))) { + khm_size cb; + + cb = sizeof(wmethod); + if (KHM_SUCCEEDED(khc_read_string(h_cell, L"MethodName", wmethod, &cb))) { + r->method = afs_get_method_id(wmethod); + } else { + r->method = AFS_TOKEN_AUTO; + } + + cb = sizeof(wbuf); + if (KHM_SUCCEEDED(khc_read_string(h_cell, L"Realm", wbuf, &cb))) { + r->realm = PMALLOC(cb); + StringCbCopy(r->realm, cb, wbuf); + } else { + r->realm = NULL; + } + + khc_close_space(h_cell); + + } else { + r->realm = NULL; + r->method = AFS_TOKEN_AUTO; + } + + r->flags = 0; + } + } + + if (khc_read_multi_string(csp_params, L"DefaultCells", + NULL, &cb_defcells) == KHM_ERROR_TOO_LONG && + cb_defcells > sizeof(wchar_t) * 2) { + wchar_t * c_cell; + + defcells = PMALLOC(cb_defcells); + if (defcells == NULL) + goto _done_defaults; + + if (KHM_FAILED(khc_read_multi_string(csp_params, L"DefaultCells", + defcells, &cb_defcells))) { + PFREE(defcells); + goto _done_defaults; + } + + for (c_cell = defcells; + c_cell && *c_cell; + c_cell = multi_string_next(c_cell)) { + + khm_size cb; + int i; + khm_handle h_cell = NULL; + afs_cred_row * r; + + if (FAILED(StringCbLength(c_cell, (MAXCELLCHARS + 1) * sizeof(wchar_t), + &cb))) + continue; + cb += sizeof(wchar_t); + + for (i=0; i < l->n_rows; i++) { + if (!_wcsicmp(l->rows[i].cell, c_cell)) + break; + } + + if (i < l->n_rows) + continue; + + r = afs_cred_get_new_row(l); + + r->cell = PMALLOC(cb); + StringCbCopy(r->cell, cb, c_cell); + + if (h_gcells && + KHM_SUCCEEDED(khc_open_space(h_gcells, c_cell, 0, &h_cell))) { + + cb = sizeof(wmethod); + if (KHM_SUCCEEDED(khc_read_string(h_cell, L"MethodName", wmethod, &cb))) { + r->method = afs_get_method_id(wmethod); + } else { + r->method = AFS_TOKEN_AUTO; + } + + cb = sizeof(wbuf); + if (KHM_SUCCEEDED(khc_read_string(h_cell, L"Realm", wbuf, &cb))) { + r->realm = PMALLOC(cb); + StringCbCopy(r->realm, cb, wbuf); + } else { + r->realm = NULL; + } + + khc_close_space(h_cell); + } else { + r->realm = NULL; + r->method = AFS_TOKEN_AUTO; + } + + r->flags = 0; + } + + PFREE(defcells); + } + } + + _done_defaults: + + ts.ident = ident; + ts.l = l; + ts.add_new = TRUE; + ts.update_info = FALSE; + + kcdb_credset_apply(NULL, afs_get_id_creds_apply_proc, + &ts); + + if(h_id) + khc_close_space(h_id); + if(h_afs) + khc_close_space(h_afs); + if(h_cells) + khc_close_space(h_cells); + if(h_gcells) + khc_close_space(h_gcells); +} + +void +nc_dlg_enable(HWND hwnd, BOOL enable) { + if(enable) { + SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, BM_SETCHECK, + BST_CHECKED, 0); + } else { + SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, BM_SETCHECK, + BST_UNCHECKED, 0); + } + + EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_CELL), enable); + EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_REALM), enable); + EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_METHOD), enable); + EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_TOKENLIST), enable); + EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_ADD_TOKEN), enable); + EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_DELETE_TOKEN), enable); +} + +void +nc_dlg_show_tooltip(HWND hwnd, + UINT_PTR id, + LPWSTR msg, + LPWSTR title, + int type, + int x, + int y) +{ + afs_dlg_data * d; + TOOLINFO ti; + + d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.hwnd = hwnd; + ti.uId = id; + SendMessage(d->tooltip, TTM_GETTOOLINFO, 0, (LPARAM) &ti); + + ti.hinst = hResModule; + ti.lpszText = msg; + + SendMessage(d->tooltip, TTM_SETTOOLINFO, 0, (LPARAM) &ti); + + if(IS_INTRESOURCE(title)) { + wchar_t wbuf[1024]; + UINT resid; + + resid = (UINT)(UINT_PTR) title; + + LoadString(hResModule, resid, wbuf, ARRAYLENGTH(wbuf)); + SendMessage(d->tooltip, TTM_SETTITLE, type, (LPARAM) wbuf); + } else + SendMessage(d->tooltip, TTM_SETTITLE, type, (LPARAM) title); + + SendMessage(d->tooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &ti); + SendMessage(d->tooltip, TTM_TRACKPOSITION, 0, (LPARAM) MAKELONG(x,y)); + + d->tooltip_visible = TRUE; + + SetTimer(hwnd, DLG_TOOLTIP_TIMER_ID, DLG_TOOLTIP_TIMEOUT, NULL); +} + +void +nc_dlg_hide_tooltip(HWND hwnd, UINT_PTR id) +{ + TOOLINFO ti; + afs_dlg_data * d; + + d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + if(!d->tooltip_visible) + return; + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.hwnd = hwnd; + ti.uId = id; + + SendMessage(d->tooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti); + d->tooltip_visible = FALSE; +} + +void +afs_dlg_update_rows(HWND hwnd, afs_dlg_data * d) { + HWND hwlist; + LVITEM lvi; + wchar_t wauto[256]; + int i; + + CheckDlgButton(hwnd, IDC_NCAFS_OBTAIN, + (d->afs_enabled)? BST_CHECKED: BST_UNCHECKED); + + hwlist = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST); + + ListView_DeleteAllItems(hwlist); + + if(d->creds.n_rows == 0) + return; + + LoadString(hResModule, IDS_NC_AUTO, wauto, ARRAYLENGTH(wauto)); + + for(i=0; i < d->creds.n_rows; i++) { + wchar_t wbuf[256]; + int flags; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; + lvi.iItem = d->creds.n_rows + 1; + + lvi.stateMask = LVIS_STATEIMAGEMASK; + flags = d->creds.rows[i].flags; + if ((flags & DLGROW_FLAG_EXISTS) && + (flags & DLGROW_FLAG_NOTOWNED)) { + lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_bad_token); + } else if ((flags & DLGROW_FLAG_EXISTS)) { + lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_existing_token); + } else { + lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_new_token); + } + + lvi.lParam = (LPARAM) i; + + lvi.iSubItem = NCAFS_IDX_CELL; + lvi.pszText = d->creds.rows[i].cell; + + lvi.iItem = ListView_InsertItem(hwlist, &lvi); + + lvi.mask = LVIF_TEXT; /* subitems dislike lParam */ + lvi.iSubItem = NCAFS_IDX_REALM; + if(d->creds.rows[i].realm != NULL) + lvi.pszText = d->creds.rows[i].realm; + else + lvi.pszText = wauto; + ListView_SetItem(hwlist, &lvi); + + lvi.iSubItem = NCAFS_IDX_METHOD; + afs_method_describe(d->creds.rows[i].method, + KCDB_TS_SHORT, + wbuf, sizeof(wbuf)); + lvi.pszText = wbuf; + + ListView_SetItem(hwlist, &lvi); + } +} + +void +nc_dlg_del_token(HWND hwnd) { + afs_dlg_data * d; + khui_new_creds_by_type * nct; + + d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + if (d->nc) + khui_cw_find_type(d->nc, afs_credtype_id, &nct); + + if(ListView_GetSelectedCount(GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST)) == 0) { + wchar_t cell[KCDB_MAXCCH_NAME]; + int i; + + /* nothing is selected in the list view */ + /* we delete the row that matches the current contents of the + cell edit control */ + cell[0] = 0; + GetDlgItemText(hwnd, IDC_NCAFS_CELL, cell, ARRAYLENGTH(cell)); + for(i=0; icreds.n_rows; i++) { + if(!_wcsicmp(d->creds.rows[i].cell, cell)) { + /* found it */ + afs_cred_delete_row(&d->creds, i); + afs_dlg_update_rows(hwnd, d); + d->dirty = TRUE; + break; + } + } + } else { + /* something is selected in the token list view */ + /* we delete that */ + HWND hw; + LVITEM lvi; + int idx; + int row; + BOOL deleted = FALSE; + + hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST); + idx = -1; + do { + idx = ListView_GetNextItem(hw, idx, LVNI_SELECTED); + if(idx >= 0) { + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = idx; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + if(!ListView_GetItem(hw, &lvi)) + continue; + row = (int) lvi.lParam; + if(row >= 0 && row < d->creds.n_rows) { + d->creds.rows[row].flags |= DLGROW_FLAG_DELETED; + deleted = TRUE; + } + } + } while(idx != -1); + + if(deleted) { + for(idx = 0; idx < d->creds.n_rows; idx ++) { + if(d->creds.rows[idx].flags & DLGROW_FLAG_DELETED) { + afs_cred_delete_row(&d->creds, idx); + idx--; /* we have to look at the current item again */ + } + } + + d->dirty = TRUE; + afs_dlg_update_rows(hwnd, d); + } + } + + if (d->nc) + SendMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0); + else if (d->config_dlg && d->dirty) + khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); +} + +void +nc_dlg_add_token(HWND hwnd) { + afs_dlg_data * d; + afs_cred_row * prow; + afs_cred_row trow; + khui_new_creds_by_type * nct; + wchar_t buf[256]; + int idx; + size_t n; + size_t cb; + int i; + BOOL new_row = FALSE; + khm_handle ident = NULL; + + d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + if (d->nc) + khui_cw_find_type(d->nc, afs_credtype_id, &nct); + else + nct = NULL; + + if((n = SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, WM_GETTEXT, + (WPARAM) ARRAYLENGTH(buf), (LPARAM) buf)) + == 0) + { + /* probably should indicate that user should type something */ + RECT r; + GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_CELL), &r); + nc_dlg_show_tooltip(hwnd, + 0, + MAKEINTRESOURCE(IDS_NC_TT_NO_CELL), + MAKEINTRESOURCE(IDS_NC_TT_CANT_ADD), + 2, (r.left + r.right)/ 2, r.bottom); + return; + } + + if(n != wcsspn(buf, AFS_VALID_CELL_CHARS)) { + RECT r; + GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_CELL), &r); + nc_dlg_show_tooltip(hwnd, + 0, + MAKEINTRESOURCE(IDS_NC_TT_MALFORMED_CELL), + MAKEINTRESOURCE(IDS_NC_TT_CANT_ADD), + 2, (r.left + r.right)/2, r.bottom); + return; + } + + /* check if this is already listed */ + for(i=0;icreds.n_rows;i++) { + if(!_wcsicmp(buf, d->creds.rows[i].cell)) + break; + } + + if(i < d->creds.n_rows) { + new_row = FALSE; + + prow = &(d->creds.rows[i]); + } else { + new_row = TRUE; + prow = NULL; + } + + ZeroMemory(&trow, sizeof(trow)); + + cb = (n+1) * sizeof(wchar_t); + trow.cell = PMALLOC(cb); + StringCbCopy(trow.cell, cb, buf); + + /* now for the realm */ + do { + idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_GETCURSEL, 0, 0); + if(idx != CB_ERR) { + int lp; + lp = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_GETITEMDATA, idx, 0); + if(lp != CB_ERR && lp) /* this is the 'determine realm + automatically' item */ + { + trow.realm = NULL; + break; + } + } + + if((n = SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, WM_GETTEXT, + ARRAYLENGTH(buf), (LPARAM) buf)) == 0) { + RECT r; + GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_REALM), &r); + nc_dlg_show_tooltip(hwnd, + 0, + MAKEINTRESOURCE(IDS_NC_TT_NO_REALM), + MAKEINTRESOURCE((new_row)? + IDS_NC_TT_CANT_ADD: + IDS_NC_TT_CANT_UPDATE), + 2, (r.left + r.right)/2, r.bottom); + goto _error_exit; + } + + if(n != wcsspn(buf, AFS_VALID_REALM_CHARS)) { + RECT r; + GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_REALM), &r); + nc_dlg_show_tooltip(hwnd, + 0, + MAKEINTRESOURCE(IDS_NC_TT_MALFORMED_REALM), + MAKEINTRESOURCE((new_row)? + IDS_NC_TT_CANT_ADD: + IDS_NC_TT_CANT_UPDATE), + 2, (r.left + r.right)/2, r.bottom); + goto _error_exit; + } + + cb = (n+1) * sizeof(wchar_t); + trow.realm = PMALLOC(cb); + StringCbCopy(trow.realm, cb, buf); + + } while(FALSE); + + idx = (int)SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, + CB_GETCURSEL, 0, 0); + if (idx != CB_ERR) { + trow.method = (afs_tk_method) + SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_GETITEMDATA, + idx, 0); + } else { + trow.method = AFS_TOKEN_AUTO; + } + + if (d->nc && + d->nc->n_identities > 0 && + d->nc->identities[0]) { + + ident = d->nc->identities[0]; + + } else if (d->ident) { + + ident = d->ident; + + } + + if(new_row) { + khm_boolean ok_to_add = TRUE; + + if (ident) { + khm_handle id_conf = NULL; + + ok_to_add = + afs_check_add_token_to_identity(trow.cell, + ident, + &id_conf); + + if (!ok_to_add) { +#if KH_VERSION_API >= 5 + khui_alert * a; + wchar_t wbuf[512]; + wchar_t wfmt[128]; + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + +#ifdef DEBUG + assert(id_conf); +#endif + khui_alert_create_empty(&a); + + cb = sizeof(widname); + kcdb_identity_get_name(id_conf, widname, &cb); + + LoadString(hResModule, IDS_NC_TT_CONFLICT, + wfmt, ARRAYLENGTH(wfmt)); + StringCbPrintf(wbuf, sizeof(wbuf), + wfmt, trow.cell, widname); + khui_alert_set_message(a, wbuf); + + LoadString(hResModule, IDS_NC_TT_PROBLEM, + wbuf, ARRAYLENGTH(wbuf)); + khui_alert_set_title(a, wbuf); + + khui_alert_add_command(a, KHUI_PACTION_KEEP); + khui_alert_add_command(a, KHUI_PACTION_REMOVE); + khui_alert_add_command(a, KHUI_PACTION_CANCEL); + + khui_alert_set_severity(a, KHERR_INFO); + + khui_alert_show_modal(a); + + ok_to_add = TRUE; + + if (a->response == KHUI_PACTION_REMOVE) { + afs_remove_token_from_identities(trow.cell); + } else if (a->response == KHUI_PACTION_CANCEL) { + ok_to_add = FALSE; + } + + khui_alert_release(a); +#else + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wtitle[64]; + wchar_t wmsg[512]; + wchar_t wfmt[128]; + khm_size cb; + int r; + +#ifdef DEBUG + assert(id_conf); +#endif + + cb = sizeof(widname); + kcdb_identity_get_name(id_conf, widname, &cb); + LoadString(hResModule, IDS_NC_TT_PROBLEM, + wtitle, ARRAYLENGTH(wtitle)); + LoadString(hResModule, IDS_NC_TT_CONFLICTM, + wfmt, ARRAYLENGTH(wfmt)); + StringCbPrintf(wmsg, sizeof(wmsg), wfmt, + trow.cell, widname); + r = MessageBox(NULL, wmsg, wtitle, + MB_YESNOCANCEL | MB_ICONWARNING | + MB_APPLMODAL); + + ok_to_add = TRUE; + if (r == IDNO) { + afs_remove_token_from_identities(trow.cell); + } else if (r == IDCANCEL) { + ok_to_add = FALSE; + } +#endif + + kcdb_identity_release(id_conf); + } + + if (!ok_to_add) + goto _error_exit; + } + + prow = afs_cred_get_new_row(&d->creds); + } else { + if (prow->cell) + PFREE(prow->cell); + + if(prow->realm) + PFREE(prow->realm); + + ZeroMemory(prow, sizeof(*prow)); + } + + *prow = trow; + + if (ident) { + afs_ident_token_set ts; + + ts.ident = ident; + ts.l = &d->creds; + ts.add_new = FALSE; + ts.update_info = FALSE; + + kcdb_credset_apply(NULL, afs_get_id_creds_apply_proc, + &ts); + } + + afs_dlg_update_rows(hwnd, d); + + d->dirty = TRUE; + + if (d->nc) + SendMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0); + else if (d->config_dlg) { + khui_cfg_set_flags_inst(&d->cfg, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } + + return; + +_error_exit: + if(trow.realm) + PFREE(trow.realm); + if(trow.cell) + PFREE(trow.cell); +} + +/* this is shared between the new credentials window and the AFS per + identity configuration dialog. */ +INT_PTR CALLBACK +afs_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_INITDIALOG: + { + HWND hw; + HIMAGELIST hw_ilist; + afs_dlg_data * d; + khui_new_creds_by_type * nct = NULL; + RECT r; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + InitializeCriticalSection(&d->cs); + + /* lParam is a pointer to a khui_new_creds structure */ + d->nc = (khui_new_creds *) lParam; + + if (d->nc) + khui_cw_find_type(d->nc, afs_credtype_id, &nct); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d); +#pragma warning(pop) + + EnterCriticalSection(&d->cs); + + if (nct) + nct->aux = (LPARAM) d; + + /* create the tooltip window */ + d->tooltip = + CreateWindowEx(WS_EX_TOPMOST, + TOOLTIPS_CLASS, + NULL, + WS_POPUP | TTS_BALLOON | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hwnd, /* make this an owned window, so + we don't have to worry about + destroying it */ + NULL, + hInstance, + NULL); + + SetWindowPos(d->tooltip, + HWND_TOPMOST, + 0, + 0, + 0, + 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + { + TOOLINFO ti; + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.uFlags = TTF_TRACK; + ti.hwnd = hwnd; + ti.uId = 0; + ti.hinst = hResModule; + ti.lpszText = L""; + GetClientRect(hwnd, &(ti.rect)); + + SendMessage(d->tooltip, TTM_ADDTOOL, 0, (LPARAM) &ti); + } + + /* we only initialize the constant bits here. */ + hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST); + + GetClientRect(hw, &r); + + /* set the list view status icons */ + hw_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR8 | ILC_MASK, + 4, 4); +#ifdef DEBUG + assert(hw_ilist); +#endif + { + HICON hi; + + hi = LoadImage(hResModule, MAKEINTRESOURCE(IDI_NC_NEW), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + + d->idx_new_token = ImageList_AddIcon(hw_ilist, hi) + 1; + + DestroyIcon(hi); + + hi = LoadImage(hResModule, MAKEINTRESOURCE(IDI_NC_EXIST), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + d->idx_existing_token = ImageList_AddIcon(hw_ilist, hi) + 1; + + DestroyIcon(hi); + + hi = LoadImage(hResModule, + MAKEINTRESOURCE(IDI_NC_NOTOWNED), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR); + d->idx_bad_token = ImageList_AddIcon(hw_ilist, hi) + 1 ; + + DestroyIcon(hi); + } + + ListView_SetImageList(hw, hw_ilist, LVSIL_STATE); + + ListView_DeleteAllItems(hw); + + /* set the columns */ + { + LVCOLUMN lc; + wchar_t wbuf[256]; + + lc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; + lc.fmt = LVCFMT_LEFT; + lc.cx = ((r.right - r.left) * 2) / 5; + LoadString(hResModule, IDS_NCAFS_COL_CELL, + wbuf, ARRAYLENGTH(wbuf)); + lc.pszText = wbuf; + + ListView_InsertColumn(hw, 0, &lc); + + lc.mask |= LVCF_SUBITEM; + //lc.cx is the same as above + lc.iSubItem = NCAFS_IDX_REALM; + LoadString(hResModule, IDS_NCAFS_COL_REALM, + wbuf, ARRAYLENGTH(wbuf)); + + ListView_InsertColumn(hw, 1, &lc); + + lc.cx = ((r.right - r.left) * 1) / 5; + lc.iSubItem = NCAFS_IDX_METHOD; + LoadString(hResModule, IDS_NCAFS_COL_METHOD, + wbuf, ARRAYLENGTH(wbuf)); + + ListView_InsertColumn(hw, 2, &lc); + } + + /* Set the items for the 'method' combo box */ + hw = GetDlgItem(hwnd, IDC_NCAFS_METHOD); + + { + wchar_t wbuf[KHUI_MAXCB_SHORT_DESC]; + afs_tk_method method = -1; + int idx; + + SendMessage(hw, CB_RESETCONTENT, 0, 0); + + while((method = afs_get_next_method_id(method)) >= 0) { + afs_method_describe(method, KCDB_TS_SHORT, + wbuf, sizeof(wbuf)); + idx = (int)SendMessage(hw, CB_INSERTSTRING, + (WPARAM) -1, (LPARAM) wbuf); +#ifdef DEBUG + assert(idx != CB_ERR); +#endif + SendMessage(hw, CB_SETITEMDATA, (WPARAM) idx, + (LPARAM) method); + } + + /* finally, set the current selection to auto, which + is the first method returned by + afs_get_next_method_id() */ + SendMessage(hw, CB_SETCURSEL, 0, 0); + } + + d->afs_enabled = TRUE; + SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, + BM_SETCHECK, BST_CHECKED, 0); + + LeaveCriticalSection(&d->cs); + + /* the cells and realms combo boxes need to be filled + in the plugin thread since that requires making + potentially blocking and non-thread safe calls */ + } + return TRUE; + + case WM_DESTROY: + { + afs_dlg_data * d; + khui_new_creds_by_type * nct; + + d = (afs_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + EnterCriticalSection(&d->cs); + + if (d->nc) { + khui_cw_find_type(d->nc, afs_credtype_id, &nct); + + nct->aux = (LPARAM) NULL; + } + + afs_cred_free_rows(&d->creds); + + LeaveCriticalSection(&d->cs); + DeleteCriticalSection(&d->cs); + + PFREE(d); + } + return TRUE; + + case WM_COMMAND: + { + afs_dlg_data * d; + khui_new_creds_by_type * nct; + + d = (afs_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + EnterCriticalSection(&d->cs); + + if (d->nc) + khui_cw_find_type(d->nc, afs_credtype_id, &nct); + else + nct = NULL; + + nc_dlg_hide_tooltip(hwnd, 0); + + /* Handle WM_COMMAND */ + switch(wParam) { + case MAKEWPARAM(IDC_NCAFS_OBTAIN, BN_CLICKED): + { + BOOL c; + c = (SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, + BM_GETCHECK, 0, 0) + == BST_CHECKED); + d->afs_enabled = c; + d->dirty = TRUE; + if (d->nc) + khui_cw_enable_type(d->nc, afs_credtype_id, c); + else if (d->config_dlg) + khui_cfg_set_flags_inst(&d->cfg, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + nc_dlg_enable(hwnd, c); + } + break; + + case MAKEWPARAM(IDC_NCAFS_ADD_TOKEN, BN_CLICKED): + { + nc_dlg_add_token(hwnd); + } + break; + + case MAKEWPARAM(IDC_NCAFS_DELETE_TOKEN, BN_CLICKED): + { + nc_dlg_del_token(hwnd); + } + break; + } + + LeaveCriticalSection(&d->cs); + } + return TRUE; + + case KHUI_WM_NC_NOTIFY: + { + afs_dlg_data * d; + khui_new_creds_by_type * nct; + + d = (afs_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + EnterCriticalSection(&d->cs); + + if (d->nc) + khui_cw_find_type(d->nc, afs_credtype_id, &nct); + else + nct = NULL; + + switch(HIWORD(wParam)) { + case WMNC_DIALOG_SETUP: + { + SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, + CB_RESETCONTENT, 0, 0); + + /* load the LRU cells */ + { + wchar_t * buf; + wchar_t *s; + khm_size cbbuf; + + if(khc_read_multi_string(csp_params, L"LRUCells", + NULL, &cbbuf) == + KHM_ERROR_TOO_LONG) { + buf = PMALLOC(cbbuf); + khc_read_multi_string(csp_params, L"LRUCells", + buf, &cbbuf); + s = buf; + while(*s) { + SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, + CB_ADDSTRING, 0, (LPARAM) s); + s += wcslen(s) + 1; + } + PFREE(buf); + } + } + + /* now, if the root cell is not in the LRU, add it */ + { + char buf[256]; + wchar_t wbuf[256]; + + if(!cm_GetRootCellName(buf)) { + AnsiStrToUnicode(wbuf, sizeof(wbuf), buf); + if(SendDlgItemMessage(hwnd, + IDC_NCAFS_CELL, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) wbuf) == CB_ERR) { + SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, + CB_ADDSTRING, + 0, (LPARAM) wbuf); + } + SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, + CB_SELECTSTRING, + -1, (LPARAM) wbuf); + } + } + + SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_RESETCONTENT, 0, 0); + + /* as for the realms, we have a special one here */ + { + wchar_t wbuf[256]; + int idx; + + LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf, + (int) ARRAYLENGTH(wbuf)); + idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_ADDSTRING, 0, + (LPARAM) wbuf); + /* item data for the realm strings is the + answer to the question, "is this the + 'determine realm automatically' item?" */ + SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_SETITEMDATA, idx, TRUE); + SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_SELECTSTRING, + -1, (LPARAM) wbuf); + } + + /* load the LRU realms */ + { + wchar_t * buf; + wchar_t *s; + int idx; + khm_size cbbuf; + + if(khc_read_multi_string(csp_params, L"LRURealms", + NULL, &cbbuf) == + KHM_ERROR_TOO_LONG) { + buf = PMALLOC(cbbuf); + khc_read_multi_string(csp_params, L"LRURealms", + buf, &cbbuf); + s = buf; + while(*s) { + if(SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_FINDSTRINGEXACT, -1, + (LPARAM) s) == CB_ERR) { + idx = + (int) + SendDlgItemMessage(hwnd, + IDC_NCAFS_REALM, + CB_ADDSTRING, + 0, (LPARAM) s); + SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_SETITEMDATA, + idx, FALSE); + } + + s += wcslen(s) + 1; + } + PFREE(buf); + } + } + + if (d->nc) + khui_cw_enable_type(d->nc, afs_credtype_id, + d->afs_enabled); + + nc_dlg_enable(hwnd, d->afs_enabled); + + afs_dlg_update_rows(hwnd, d); + } + break; + + case WMNC_UPDATE_CREDTEXT: + { + wchar_t wformat[256]; + wchar_t wstr[2048]; + khm_int32 flags; + + if(nct->credtext) { + PFREE(nct->credtext); + nct->credtext = NULL; + } + +#ifdef DEBUG + assert(d->nc); +#endif + + if (d->nc->n_identities == 0 || + KHM_FAILED(kcdb_identity_get_flags(d->nc->identities[0], + &flags)) || + !(flags & KCDB_IDENT_FLAG_VALID)) + /* in this case, we don't show any credential text */ + break; + + wstr[0] = 0; + + if(!d->afs_enabled) { + LoadString(hResModule, IDS_AFS_CREDTEXT_DIS, + wstr, ARRAYLENGTH(wstr)); + } else { + if(d->creds.n_rows == 0) { + LoadString(hResModule, IDS_AFS_CREDTEXT_0, + wstr, ARRAYLENGTH(wstr)); + } else if(d->creds.n_rows == 1) { + LoadString(hResModule, IDS_AFS_CREDTEXT_1, + wformat, ARRAYLENGTH(wformat)); + StringCbPrintf(wstr, sizeof(wstr), wformat, + d->creds.rows[0].cell); + } else { + int i; + wchar_t wcells[1024]; + + LoadString(hResModule, IDS_AFS_CREDTEXT_N, + wformat, ARRAYLENGTH(wformat)); + wcells[0] = 0; + for(i=0; icreds.n_rows; i++) { + if(i > 0) + StringCbCat(wcells, sizeof(wcells), + L", "); + if(FAILED(StringCbCat(wcells, + sizeof(wcells), + d->creds.rows[i].cell))) { + size_t cch; + /* looks like we overflowed */ + /* add an ellipsis at the end */ + StringCchLength(wcells, ARRAYLENGTH(wcells), &cch); + cch = min(ARRAYLENGTH(wcells) - 4, cch); + StringCchCopy(wcells + cch, 4, L"..."); + + break; + } + } + + StringCbPrintf(wstr, sizeof(wstr), wformat, wcells); + } + } + + if(wstr[0] != 0) { + size_t cbs; + StringCbLength(wstr, sizeof(wstr), &cbs); + cbs += sizeof(wchar_t); + assert(nct->credtext == NULL); + nct->credtext = PMALLOC(cbs); + StringCbCopy(nct->credtext, cbs, wstr); + } else { + /* something went wrong */ + nct->credtext = NULL; + } + } + break; + + case WMNC_CREDTEXT_LINK: + { + khui_htwnd_link * l; + wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD]; + wchar_t * wids; + + l = (khui_htwnd_link *) lParam; + + StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len); + wids = wcschr(wid, L':'); + + if(!wids) + break; + else + wids++; + +#ifdef DEBUG + assert(d->nc); +#endif + + if(!wcscmp(wids, L"Enable")) { + SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, + BM_SETCHECK, BST_CHECKED, 0); + d->afs_enabled = TRUE; + khui_cw_enable_type(d->nc, afs_credtype_id, TRUE); + nc_dlg_enable(hwnd, TRUE); + } + } + break; + + case WMNC_IDENTITY_CHANGE: + kmq_post_sub_msg(afs_sub, KMSG_CRED, + KMSG_CRED_DIALOG_NEW_IDENTITY, 0, + (void *) d->nc); + break; + + case WMNC_AFS_UPDATE_ROWS: + afs_dlg_update_rows(hwnd, d); + +#ifdef DEBUG + assert(d->nc); +#endif + + PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0); + break; + } + + LeaveCriticalSection(&d->cs); + } + return TRUE; + + case WM_NOTIFY: + if(wParam == IDC_NCAFS_TOKENLIST) { + LPNMHDR lpnmh = (LPNMHDR) lParam; + + if(lpnmh->code == LVN_ITEMCHANGED) { + /* when an item in the list view is clicked, we + load the corresponding values into the edit and + combo boxes */ + NMLISTVIEW *lpnmlv = (NMLISTVIEW *) lpnmh; + LVITEM lvi; + HWND hw; + int idx; + int row; + afs_dlg_data * d; + + if (!(lpnmlv->uChanged & LVIF_STATE) || + !(lpnmlv->uNewState & LVIS_SELECTED) || + (lpnmlv->iItem == -1)) + + return TRUE; + + d = (afs_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + EnterCriticalSection(&d->cs); + + hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST); + + idx = lpnmlv->iItem; + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = idx; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + if(!ListView_GetItem(hw, &lvi)) + goto _done_notify_select; + + /* ok, now lvi.lParam should be the row of the token */ + row = (int) lvi.lParam; + if(row < 0 || row >= d->creds.n_rows) + goto _done_notify_select; + + SetDlgItemText(hwnd, IDC_NCAFS_CELL, + d->creds.rows[row].cell); + if(d->creds.rows[row].realm != NULL) { + SetDlgItemText(hwnd, IDC_NCAFS_REALM, + d->creds.rows[row].realm); + } else { + wchar_t wbuf[256]; + int idx; + + LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf, + ARRAYLENGTH(wbuf)); + idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, + CB_FINDSTRINGEXACT, -1, + (LPARAM) wbuf); + SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, CB_SETCURSEL, + idx, 0); + } + SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_SETCURSEL, + d->creds.rows[row].method, 0); + _done_notify_select: + LeaveCriticalSection(&d->cs); + + } else if (lpnmh->code == NM_DBLCLK) { + + LPNMITEMACTIVATE pnmi; + LVITEM lvi; + HWND hw; + afs_dlg_data * d; + int row; + int x,y; + RECT r; + + d = (afs_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + EnterCriticalSection(&d->cs); + + pnmi = (LPNMITEMACTIVATE) lpnmh; + + hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST); + + ZeroMemory(&lvi, sizeof(lvi)); + lvi.iItem = pnmi->iItem; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + + if (!ListView_GetItem(hw, &lvi)) + goto _done_notify_click; + + row = (int) lvi.lParam; + if(row < 0 || row >= d->creds.n_rows) + goto _done_notify_click; + + ListView_GetItemRect(hw, pnmi->iItem, &r, LVIR_SELECTBOUNDS); + x = (r.left + r.right) / 2; + y = (r.bottom); + + GetWindowRect(hw, &r); + y += r.top; + x += r.left; + + if (d->creds.rows[row].flags & DLGROW_FLAG_NOTOWNED) { + nc_dlg_show_tooltip(hwnd, 0, + MAKEINTRESOURCE(IDS_NC_TT_CONFLICTD), + MAKEINTRESOURCE(IDS_NC_TT_PROBLEM), + 2, + x,y); + } else if (d->creds.rows[row].flags & + DLGROW_FLAG_EXPIRED) { + nc_dlg_show_tooltip(hwnd, 0, + MAKEINTRESOURCE(IDS_NC_TT_EXPIRED), + MAKEINTRESOURCE(IDS_NC_TT_DETAILS), + 1, + x, y); + } else if (d->creds.rows[row].flags & + DLGROW_FLAG_EXISTS) { + nc_dlg_show_tooltip(hwnd, 0, + MAKEINTRESOURCE(IDS_NC_TT_EXISTS), + MAKEINTRESOURCE(IDS_NC_TT_DETAILS), + 1, x, y); + } else { + nc_dlg_show_tooltip(hwnd, 0, + MAKEINTRESOURCE(IDS_NC_TT_NEW), + MAKEINTRESOURCE(IDS_NC_TT_DETAILS), + 1, x, y); + } + + _done_notify_click: + LeaveCriticalSection(&d->cs); + } + } + return TRUE; + + case WM_TIMER: + { + if(wParam == DLG_TOOLTIP_TIMER_ID) { + KillTimer(hwnd, DLG_TOOLTIP_TIMER_ID); + nc_dlg_hide_tooltip(hwnd, 0); + } + } + return TRUE; + + case WM_HELP: + { + static const DWORD ctx_help[] = { + IDC_NCAFS_OBTAIN, IDH_OBTAIN, + IDC_NCAFS_CELL, IDH_CELL, + IDC_NCAFS_REALM, IDH_REALM, + IDC_NCAFS_METHOD, IDH_METHOD, + IDC_NCAFS_ADD_TOKEN, IDH_ADD, + IDC_NCAFS_DELETE_TOKEN, IDH_DELETE, + IDC_NCAFS_TOKENLIST, IDH_TOKENLIST, + 0 + }; + + LPHELPINFO hlp; + + hlp = (LPHELPINFO) lParam; + + if (hlp->iContextType != HELPINFO_WINDOW) + break; + + afs_html_help(hlp->hItemHandle, L"::/popups_newcred.txt", + HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help); + } + return TRUE; + } /* switch(uMsg) */ + + return FALSE; +} + + +/* passed in to kcdb_credset_apply along with the afs_credset to adjust + newly acquired credentials to include informatino derived from the + new creds operation */ +khm_int32 KHMAPI +afs_adjust_token_ident_proc(khm_handle cred, void * vd) +{ + wchar_t cell[MAXCELLCHARS]; + afs_ident_token_set * b = (afs_ident_token_set *) vd; + afs_cred_list * l; + khm_size cbbuf; + int i; + + l = b->l; + + /* ASSUMPTION: for each user, there can be tokens for only one + cell */ + + cbbuf = sizeof(cell); + + if(KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, NULL, cell, &cbbuf))) + return KHM_ERROR_SUCCESS; /* remember, kcdb doesn't care if + this run succeeded or not. all + it wants to know if whether or + not we want to continue the + search */ + + for(i=0; in_rows; i++) { + if((l->rows[i].flags & DLGROW_FLAG_DONE) && + !_wcsicmp(cell, l->rows[i].cell)) { + khm_int32 method; + + kcdb_cred_set_identity(cred, b->ident); + if(l->rows[i].realm) + kcdb_cred_set_attr(cred, afs_attr_realm, l->rows[i].realm, + KCDB_CBSIZE_AUTO); + else + kcdb_cred_set_attr(cred, afs_attr_realm, NULL, 0); + + method = l->rows[i].method; + kcdb_cred_set_attr(cred, afs_attr_method, &method, + KCDB_CBSIZE_AUTO); + + break; + } + } + + return KHM_ERROR_SUCCESS; +} + +void +afs_cred_write_ident_data(afs_dlg_data * d) { + wchar_t * lru_cell = NULL; + wchar_t * lru_realm = NULL; + wchar_t * id_cell = NULL; + khm_size cbidcell; + khm_size cbcell; + khm_size cbrealm; + khm_size cbt; + size_t cbz; + khm_handle h_idc = NULL; + khm_handle h_afs = NULL; + khm_handle h_acells = NULL; + khm_handle h_cellmap = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_handle ident = NULL; + afs_cred_list * l; + int i; + + l = &d->creds; + + if (d->nc && + d->nc->n_identities > 0 && + d->nc->identities[0]) + + ident = d->nc->identities[0]; + + else if (d->config_dlg) + + ident = d->ident; + + if (!ident) + return; + + cbt = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cbt); + + khc_open_space(csp_afscred, L"Cells", 0, &h_cellmap); + + if(ident) { + if(KHM_SUCCEEDED(kcdb_identity_get_config(ident, + KHM_FLAG_CREATE, + &h_idc))) { + khc_open_space(h_idc, CSNAME_AFSCRED, + KHM_FLAG_CREATE, &h_afs); + } + + if(h_afs) { + khc_open_space(h_afs, L"Cells", KHM_FLAG_CREATE, + &h_acells); + } + } + + if (h_afs && d) { + khc_write_int32(h_afs, L"AFSEnabled", + !!d->afs_enabled); + } + + if(khc_read_multi_string(csp_params, + L"LRUCells", + NULL, + &cbcell) == KHM_ERROR_TOO_LONG) { + cbcell += MAXCELLCHARS * sizeof(wchar_t) * + l->n_rows; + lru_cell = PMALLOC(cbcell); + ZeroMemory(lru_cell, cbcell); + cbt = cbcell; + + khc_read_multi_string(csp_params, + L"LRUCells", + lru_cell, + &cbt); + } else { + cbcell = MAXCELLCHARS * sizeof(wchar_t) * + l->n_rows; + if (cbcell > 0) { + lru_cell = PMALLOC(cbcell); + ZeroMemory(lru_cell, cbcell); + } else { + lru_cell = NULL; + } + } + + if(khc_read_multi_string(csp_params, + L"LRURealms", + NULL, + &cbrealm) == KHM_ERROR_TOO_LONG) { + cbrealm += MAXCELLCHARS * sizeof(wchar_t) * l->n_rows; + lru_realm = PMALLOC(cbrealm); + ZeroMemory(lru_realm, cbrealm); + cbt = cbrealm; + + khc_read_multi_string(csp_params, + L"LRURealms", + lru_realm, + &cbt); + } else { + cbrealm = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows; + if (cbrealm > 0) { + lru_realm = PMALLOC(cbrealm); + ZeroMemory(lru_realm, cbrealm); + } else { + lru_cell = NULL; + } + } + + cbidcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows; + if (cbidcell > 0) { + id_cell = PMALLOC(cbidcell); + ZeroMemory(id_cell, cbidcell); + } else { + id_cell = NULL; + } + + for(i=0; i < l->n_rows; i++) + if(!(l->rows[i].flags & DLGROW_FLAG_DELETED)) { + khm_handle h_acell = NULL; + + if(!multi_string_find(lru_cell, + l->rows[i].cell, 0)) { + cbz = cbcell; + multi_string_append(lru_cell, &cbz, + l->rows[i].cell); + } + + if(l->rows[i].realm && + !multi_string_find(lru_realm, + l->rows[i].realm, 0)) { + cbz = cbrealm; + multi_string_append(lru_realm, &cbz, + l->rows[i].realm); + } + + cbz = cbidcell; + multi_string_append(id_cell, &cbz, + l->rows[i].cell); + + if(h_acells && + KHM_SUCCEEDED(khc_open_space(h_acells, + l->rows[i].cell, + KHM_FLAG_CREATE, + &h_acell))) { + wchar_t methodname[KHUI_MAXCCH_NAME]; + + afs_get_method_name(l->rows[i].method, + methodname, + sizeof(methodname)); + + khc_write_string(h_acell, L"MethodName", + methodname); + + if(l->rows[i].realm) + khc_write_string(h_acell, L"Realm", + l->rows[i].realm); + else + khc_write_string(h_acell, L"Realm", L""); + khc_close_space(h_acell); + } + + if (h_cellmap) { + khc_write_string(h_cellmap, + l->rows[i].cell, + idname); + } + } + + if (lru_cell) + khc_write_multi_string(csp_params, + L"LRUCells", lru_cell); + if (lru_realm) + khc_write_multi_string(csp_params, + L"LRURealms", lru_realm); + if (id_cell) + khc_write_multi_string(h_afs, L"Cells", + id_cell); + + if (d->config_dlg) { + if (d->dirty) + khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | + KHUI_CNFLAG_MODIFIED); + else + khui_cfg_set_flags_inst(&d->cfg, 0, + KHUI_CNFLAG_MODIFIED); + } + + d->dirty = FALSE; + + if(h_cellmap) + khc_close_space(h_cellmap); + if(h_idc) + khc_close_space(h_idc); + if(h_afs) + khc_close_space(h_afs); + if(h_acells) + khc_close_space(h_acells); + if(id_cell) + PFREE(id_cell); + if(lru_cell) + PFREE(lru_cell); + if(lru_realm) + PFREE(lru_realm); +} + +khm_int32 +afs_msg_newcred(khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + switch(msg_subtype) { + case KMSG_CRED_NEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + wchar_t wbuf[256]; + size_t cbsize; + + nc = (khui_new_creds *) vparam; + + nct = PMALLOC(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = afs_credtype_id; + nct->ordinal = 3; + + LoadString(hResModule, IDS_AFS_NAME, wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(cbsize); + StringCbCopy(nct->name, cbsize, wbuf); + + nct->h_module = hResModule; + nct->dlg_proc = afs_dlg_proc; + nct->dlg_template = MAKEINTRESOURCE(IDD_NC_AFS); + nct->type_deps[nct->n_type_deps++] = krb5_credtype_id; + + if (krb4_credtype_id < 0) { + kcdb_credtype_get_id(KRB4_CREDTYPE_NAME, + &krb4_credtype_id); + } + if (krb4_credtype_id >= 0) { + nct->type_deps[nct->n_type_deps++] = + krb4_credtype_id; + } + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_RENEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + nc = (khui_new_creds *) vparam; + + nct = PMALLOC(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = afs_credtype_id; + nct->type_deps[nct->n_type_deps++] = krb5_credtype_id; + if (krb4_credtype_id < 0) { + kcdb_credtype_get_id(KRB4_CREDTYPE_NAME, + &krb4_credtype_id); + } + if (krb4_credtype_id >= 0) { + nct->type_deps[nct->n_type_deps++] = + krb4_credtype_id; + } + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_DIALOG_PRESTART: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + HWND hwnd; + + nc = (khui_new_creds *) vparam; + khui_cw_find_type(nc, afs_credtype_id, &nct); + + if(!nct) + break; + + hwnd = nct->hwnd_panel; + if (!hwnd) + break; + + PostMessage(hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0); + } + break; + + case KMSG_CRED_DIALOG_NEW_IDENTITY: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + afs_dlg_data * d; + + nc = (khui_new_creds *) vparam; + khui_cw_find_type(nc, afs_credtype_id, &nct); + + if(nct == NULL) + break; + + d = (afs_dlg_data *) nct->aux; + + if(d == NULL) + break; + + EnterCriticalSection(&d->cs); + + if (nct->aux == 0) { + LeaveCriticalSection(&d->cs); + break; + } + + /* we should load up the selected tokens for this + identity */ + if(nc->n_identities == 0) { + LeaveCriticalSection(&d->cs); + /* no identities selected. nothing to do */ + break; + } + + afs_cred_get_identity_creds(&d->creds, nc->identities[0], + &d->afs_enabled); + + LeaveCriticalSection(&d->cs); + + PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_AFS_UPDATE_ROWS), 0); + } + break; + + case KMSG_CRED_PROCESS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + afs_cred_list tlist; + afs_cred_list * l; + int i; + BOOL failed = FALSE; /* one or more cells failed */ + BOOL succeeded = FALSE; /* one or more cells succeeded */ + BOOL free_tlist = FALSE; + khm_handle ident = NULL; + afs_dlg_data * d = NULL; + BOOL get_tokens = TRUE; + BOOL ident_renew_triggered = TRUE; + khm_handle csp_afscred = NULL; + khm_handle csp_cells = NULL; + + nc = (khui_new_creds *) vparam; + khui_cw_find_type(nc, afs_credtype_id, &nct); + + if(!nct) + break; + + _begin_task(0); + _report_cs0(KHERR_INFO, + L"Getting AFS tokens..."); + _describe(); + + if(nc->result != KHUI_NC_RESULT_PROCESS && + nc->subtype != KMSG_CRED_RENEW_CREDS) { + /* nothing to do */ + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_SUCCESS); + + _report_cs0(KHERR_INFO, + L"Cancelling"); + _end_task(); + break; + } + + /* we can't proceed if Kerberos 5 has failed */ + if(!khui_cw_type_succeeded(nc, krb5_credtype_id)) { + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_FAILED); + + _report_cs0(KHERR_INFO, + L"Kerberos 5 plugin failed to process credentials request. Aborting"); + _end_task(); + break; + } + + if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + + if (nc->ctx.scope == KHUI_SCOPE_IDENT || + + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE && + nc->ctx.cred_type == afs_credtype_id) || + + (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred_type == afs_credtype_id)) { + + _report_cs1(KHERR_INFO, + L"AFS Renew Creds :: ident %1!p!", + _cptr(nc->ctx.identity)); + + } else { + + _report_cs0(KHERR_INFO, + L"Renew request not applicable to AFS"); + _end_task(); + break; + + } + + if (nc->ctx.identity != NULL) { + ident = nc->ctx.identity; + } else { + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_FAILED); + + _report_cs0(KHERR_INFO, + L"No identity specified. Aborting"); + _end_task(); + break; + } + + ZeroMemory(&tlist, sizeof(tlist)); + l = &tlist; + free_tlist = TRUE; + + afs_cred_get_identity_creds(l, ident, NULL); + + /* if the identity has any tokens associated with it + that aren't persistent, we should renew those as + well. */ + afs_cred_get_context_creds(l, &nc->ctx); + + if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || + nc->ctx.scope == KHUI_SCOPE_CRED) { + + ident_renew_triggered = FALSE; + + } + + } else { + _report_cs1(KHERR_INFO, + L"AFS New Creds :: ident %1!p!", + _cptr(nc->identities[0])); + + d = (afs_dlg_data *) nct->aux; + if(!d) { + _report_cs0(KHERR_INFO, + L"No dialog data found. Aborting"); + + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_FAILED); + _end_task(); + break; + } + + EnterCriticalSection(&d->cs); + + l = &d->creds; + + ident = nc->identities[0]; + if (!ident) { + LeaveCriticalSection(&d->cs); + + _report_cs0(KHERR_INFO, + L"No identity specified. Aborting"); + + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_FAILED); + + _end_task(); + break; + } + + get_tokens = d->afs_enabled; + } + + if (!get_tokens) + goto _skip_tokens; + + if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, 0, + &csp_afscred))) + khc_open_space(csp_afscred, L"Cells", 0, &csp_cells); + + /* looks like k5 worked. Now see about getting those + tokens */ + for(i=0; in_rows; i++) { + int code; + char cell[MAXCELLCHARS]; + char realm[MAXCELLCHARS]; + khm_handle ctoken; + FILETIME ft_old; + FILETIME ft_new; + time_t new_exp = 0; + khm_size cb; + khm_int32 method = AFS_TOKEN_AUTO; + khm_handle csp_cell = NULL; + + if (l->rows[i].flags & + (DLGROW_FLAG_DONE | DLGROW_FLAG_DELETED)) + + continue; + + ZeroMemory(cell, sizeof(cell)); + ZeroMemory(realm, sizeof(realm)); + + UnicodeStrToAnsi(cell, sizeof(cell), l->rows[i].cell); + if (l->rows[i].realm != NULL) + UnicodeStrToAnsi(realm, sizeof(realm), + l->rows[i].realm); + + ZeroMemory(&ft_old, sizeof(ft_old)); + + if (!ident_renew_triggered && + (ctoken = afs_find_token(NULL, l->rows[i].cell))) { + + cb = sizeof(ft_old); + kcdb_cred_get_attr(ctoken, KCDB_ATTR_EXPIRE, + NULL, &ft_old, &cb); + + kcdb_cred_release(ctoken); + } + + if (l->rows[i].method == AFS_TOKEN_AUTO && csp_cells && + KHM_SUCCEEDED(khc_open_space(csp_cells, + l->rows[i].cell, 0, + &csp_cell))) { + + if (KHM_FAILED(khc_read_int32(csp_cell, L"Method", &method))) { + method = l->rows[i].method; + } else { + _report_cs3(KHERR_INFO, + L"Overriding method %1!d! with global default %2!d! for cell %3!s!", + _int32(l->rows[i].method), + _int32(method), + _cstr(l->rows[i].cell)); + _resolve(); + } + + khc_close_space(csp_cell); + } else { + method = l->rows[i].method; + } + + _report_cs3(KHERR_INFO, + L"Getting tokens for cell %1!S! with realm %2!S! using method %3!d!", + _cstr(cell), + _cstr(realm), + _int32(method)); + _resolve(); + + /* make the call */ + code = afs_klog(ident, "", cell, realm, 0, + method, &new_exp); + + _report_cs1(KHERR_INFO, + L"klog returns code %1!d!", + _int32(code)); + + if(code) { + failed = TRUE; + l->rows[i].flags &= ~DLGROW_FLAG_DONE; + + if (!kherr_is_error()) { + /* failed to get tokens, but no error was reported */ + _report_sr1(KHERR_ERROR, IDS_ERR_GENERAL, + _cptr(cell)); + _resolve(); + } + + } else { + l->rows[i].flags |= DLGROW_FLAG_DONE; + succeeded = TRUE; + + if (new_exp && + !ident_renew_triggered) { + TimetToFileTime(new_exp, &ft_new); + + if (CompareFileTime(&ft_old, &ft_new) >= 0) { + /* getting a new token didn't improve the + situation much. We only get here if we + were trying to renew tokens. So we try + to trigger an identity renewal. Doing + so should get us new initial tickets + which will allow us to get a better + token. */ + + khui_action_context ctx; + + _reportf(L"Renewal of AFS tokens for cell %s failed to get a longer token. Triggering identity renewal", l->rows[i].cell); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->ctx.identity, + KCDB_CREDTYPE_INVALID, + NULL); + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + + ident_renew_triggered = TRUE; + } + } + } + } + + _skip_tokens: + + if(failed) { + /* we should indicate errors if anything went wrong */ + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_FAILED); + } else { + khui_cw_set_response(nc, afs_credtype_id, + KHUI_NC_RESPONSE_SUCCESS); + } + + if (succeeded && nc->subtype == KMSG_CRED_RENEW_CREDS) { + afs_ident_token_set b; + + afs_list_tokens_internal(); + + /* the tokens that we just acquired need adjusting to + include the realm, method and identity information + derived from the new creds operation. this is done + in afs_adjust_token_ident_proc */ + b.ident = ident; + b.l = l; + b.add_new = FALSE; + b.update_info = FALSE; + + kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc, + (void *) &b); + + kcdb_credset_collect(NULL, afs_credset, NULL, + afs_credtype_id, NULL); + + } else if (nc->subtype == KMSG_CRED_NEW_CREDS) { + afs_ident_token_set b; + + afs_list_tokens_internal(); + + /* the tokens that we just acquired need adjusting to + include the realm, method and identity information + derived from the new creds operation. this is done + in afs_adjust_token_ident_proc */ + b.ident = ident; + b.l = l; + b.add_new = FALSE; + b.update_info = FALSE; + + kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc, + (void *) &b); + + kcdb_credset_collect(NULL, afs_credset, NULL, + afs_credtype_id, NULL); + + afs_cred_write_ident_data(d); + } + + if (d) + LeaveCriticalSection(&d->cs); + + if (free_tlist) { + afs_cred_free_rows(&tlist); + } + + if (csp_afscred) + khc_close_space(csp_afscred); + + if (csp_cells) + khc_close_space(csp_cells); + + _end_task(); + } + break; + + case KMSG_CRED_END: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + nc = (khui_new_creds *) vparam; + khui_cw_find_type(nc, afs_credtype_id, &nct); + + if(!nct) + break; + + khui_cw_del_type(nc, afs_credtype_id); + + if (nct->name) + PFREE(nct->name); + if (nct->credtext) + PFREE(nct->credtext); + + PFREE(nct); + } + break; + } + + return KHM_ERROR_SUCCESS; +} diff --git a/src/WINNT/netidmgr_plugin/afsnewcreds.h b/src/WINNT/netidmgr_plugin/afsnewcreds.h new file mode 100644 index 0000000..cc760cd --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsnewcreds.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __AFS_NEWCREDS_H +#define __AFS_NEWCREDS_H + +typedef struct tag_afs_cred_row { + wchar_t * cell; + wchar_t * realm; + afs_tk_method method; + khm_int32 flags; +} afs_cred_row; + +/* we checked whether this cell exists */ +#define DLGROW_FLAG_CHECKED 0x00000001 + +/* cell was checked and was found to be valid */ +#define DLGROW_FLAG_VALID 0x00000002 + +/* cell was deleted */ +#define DLGROW_FLAG_DELETED 0x00000004 + +/* tokens obtained for cell */ +#define DLGROW_FLAG_DONE 0x00000008 + +/* tokens for this cell already exist */ +#define DLGROW_FLAG_EXISTS 0x00000010 + +/* tokens for this cell exist and is listed under a different + identity */ +#define DLGROW_FLAG_NOTOWNED 0x00000020 + +/* tokens for this cell exist and are expired */ +#define DLGROW_FLAG_EXPIRED 0x00000040 + +/* the subitem indexes for each data field */ +enum afs_ncwnd_subitems { + NCAFS_IDX_CELL=0, + NCAFS_IDX_REALM, + NCAFS_IDX_METHOD +}; + +#define DLG_TOOLTIP_TIMER_ID 1 +#define DLG_TOOLTIP_TIMEOUT 5000 + +typedef struct tag_afs_cred_list { + afs_cred_row * rows; + int n_rows; + int nc_rows; +} afs_cred_list; + +typedef struct tag_afs_dlg_data { + khui_new_creds * nc; + + afs_cred_list creds; + + khm_int32 afs_enabled; + + BOOL tooltip_visible; + BOOL dirty; + HWND tooltip; + + /* list view state image indices */ + int idx_new_token; + int idx_existing_token; + int idx_bad_token; + + CRITICAL_SECTION cs; + + /* used with configuration dialogs */ + khm_boolean config_dlg; + khui_config_init_data cfg; + khm_handle ident; +} afs_dlg_data; + +#define AFS_DLG_ROW_ALLOC 4 + +INT_PTR CALLBACK +afs_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +void +afs_dlg_update_rows(HWND hwnd, afs_dlg_data * d); + +void +afs_cred_flush_rows(afs_cred_list * l); + +void +afs_cred_free_rows(afs_cred_list * l); + +void +afs_cred_assert_rows(afs_cred_list * l, int n); + +void +afs_cred_delete_row(afs_cred_list * l, int i); + +afs_cred_row * +afs_cred_get_new_row(afs_cred_list * l); + +khm_int32 KHMAPI +afs_cred_add_cred_proc(khm_handle cred, void * rock); + +void +afs_cred_get_context_creds(afs_cred_list *l, + khui_action_context * ctx); + +void +afs_cred_get_identity_creds(afs_cred_list * l, + khm_handle ident, + khm_boolean * enabled); + +void +afs_cred_write_ident_data(afs_dlg_data * d); + +khm_int32 +afs_msg_newcred(khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam); + +#endif diff --git a/src/WINNT/netidmgr_plugin/afsp_version.h b/src/WINNT/netidmgr_plugin/afsp_version.h new file mode 100644 index 0000000..11974bf --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsp_version.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __AFSPLUGIN_VERSION_H +#define __AFSPLUGIN_VERSION_H + +#define AFSPLUGIN_VERSION_MAJOR 1 +#define AFSPLUGIN_VERSION_MINOR 5 +#define AFSPLUGIN_VERSION_PATCH 0002 +#define AFSPLUGIN_VERSION_AUX 0 + +#define AFSPLUGIN_VERSION 1.5.0002.0 +#define AFSPLUGIN_VERSION_STR "1.5.0002.0" +#define AFSPLUGIN_VERSION_LST 1,5,0002,0 + +#endif diff --git a/src/WINNT/netidmgr_plugin/afsp_version.h.in b/src/WINNT/netidmgr_plugin/afsp_version.h.in new file mode 100644 index 0000000..a15043e --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsp_version.h.in @@ -0,0 +1,40 @@ +afsp_version.h: NTMakefile afsp_version.h.in + $(COPY) << $@ +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __AFSPLUGIN_VERSION_H +#define __AFSPLUGIN_VERSION_H + +#define AFSPLUGIN_VERSION_MAJOR $(AFSPLUGIN_VERSION_MAJOR) +#define AFSPLUGIN_VERSION_MINOR $(AFSPLUGIN_VERSION_MINOR) +#define AFSPLUGIN_VERSION_PATCH $(AFSPLUGIN_VERSION_PATCH) +#define AFSPLUGIN_VERSION_AUX $(AFSPLUGIN_VERSION_AUX) + +#define AFSPLUGIN_VERSION $(AFSPLUGIN_VERSION) +#define AFSPLUGIN_VERSION_STR "$(AFSPLUGIN_VERSION)" +#define AFSPLUGIN_VERSION_LST $(AFSPLUGIN_VERLIST) + +#endif +<< diff --git a/src/WINNT/netidmgr_plugin/afspext.h b/src/WINNT/netidmgr_plugin/afspext.h new file mode 100644 index 0000000..cfe802b --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afspext.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __AFSPLUGIN_EXT_H +#define __AFSPLUGIN_EXT_H + +/*! \defgroup afs_ext OpenAFS Plugin extensions + + This section documents messages and data structures used by AFS + extension plugins. These are plugins which augment the behavior + of the AFS plugin. + + When performing specific tasks for NetIDMgr, the AFS plugin will + send out messages to the extension plugins either via broadcast or + unicast. The extension plugins provide functionality by + responding to these messages. + + @{*/ + +#define MAXCELLCHARS 64 +#define MAXHOSTCHARS 64 +#define MAXHOSTSPERCELL 8 + +#define TRANSARCAFSDAEMON "TransarcAFSDaemon" + +#define AFS_TOKENNAME_AUTO L"Auto" +#define AFS_TOKENNAME_KRB5 L"Kerberos5" +#define AFS_TOKENNAME_KRB524 L"Kerberos524" +#define AFS_TOKENNAME_KRB4 L"Kerberos4" + +/*! \brief An AFS token acquisition method identifier + + This takes on a value from ::afs_token_method or a token + acquisition method identifier assigned to an extension plugin. +*/ +typedef khm_int32 afs_tk_method; + +/*! \brief Predefined token acquisition methods */ +enum afs_token_method { + AFS_TOKEN_AUTO = 0, /*!< Automatic. This method iterates + through Krb5, Krb524, Krb4 and then + any extensions which provide token + acquisition methods until one of + them succeeds. */ + AFS_TOKEN_KRB5, /*!< Kerberos 5 */ + AFS_TOKEN_KRB524, /*!< Kerberos 5 with krb524 translation */ + AFS_TOKEN_KRB4, /*!< Kerberos 4 */ +}; + +/*! \brief Version of the OpenAFS Plugin + + This is an internal number that identifies the version of the + OpenAFS plugin API that this extension was built against. This + number is specified when sending the ::AFS_MSG_ANNOUNCE message. + */ +#define AFS_PLUGIN_VERSION 0x0000001 + +/*! \name Messages + + The AFS plugin registers the message type named ::AFS_MSG_TYPENAME + and sends messages of this type to notify any AFS extension + plugins to notify them of various events. + + @{*/ + +/*! \brief Name of the AFS plugin message + + This message type is registered when the AFS plugin starts and is + unregistered when the plugin stops. + + Use kmq_find_type() to find the type ID of this message type. + */ +#define AFS_MSG_TYPENAME L"AfsExtMessage" + +/*! \brief Announce an extension plugin + + Sent by an extension plugin to announce its existence to the AFS + plugin. This message should be sent by the extension plugin when + it has finished loading, and is the only message permitted to be + sent by an extension. All other messages are sent by the AFS + plugin. + + Since this message contains pointer parameters and there is no + cleanup performed on this, the message should be sent using + kmq_send_message(). + + + + + + +
Typetype ID of ::AFS_MSG_TYPENAME
Subtype::AFS_MSG_ANNOUNCE
uparam0
vparamPointer to a ::afs_msg_announce structure
+ + \note This message is only sent from extension plugins to the AFS plugin. + */ +#define AFS_MSG_ANNOUNCE 1 + +/*! \brief Parameter structure for announcing an extension plugin + + \see ::AFS_MSG_ANNOUNCE + */ +typedef struct tag_afs_msg_announce_v1 { + khm_size cbsize; /*!< Size of the strucutre. Set to \a + sizeof(::afs_msg_announce). If + there is a version skew between the + AFS plugin and the extension, then + this parameter will ensure that the + AFS plugin understands the correct + version of the structure. */ + + khm_ui_4 version; /*!< Version of the AFS plugin that + the extension is compiled for. Set + this to ::AFS_PLUGIN_VERSION. + Depending on this value, the AFS + plugin will either reject the + extension or determine which set of + messages and structures should be + used to communicate with the + extension. */ + + const wchar_t * name; /*!< Name of the extension. Should be + unique among all AFS extension + plugins. Size constrained by + ::KHUI_MAXCCH_NAME*/ + + khm_handle sub; /*!< A valid subscription for unicast + messages. This must have been + created through + kmq_create_subscription(). The + supplied handle will be + automatically released when the + plugin exits. However, if the + announcement message fails, then the + extension has to release the handle + itself. */ + + khm_boolean provide_token_acq; /*!< non-zero if the extension + provides a token acquisition + method. The \a token_acq + substructure should be filled if + this member is set to + non-zero. */ + + struct { + const wchar_t * short_desc; /*!< Short description of token + acquisition method. (localized, + required). Size is constrained by + ::KHUI_MAXCCH_SHORT_DESC */ + + const wchar_t * long_desc; /*!< Long description. (localized, + optional). Size is constrained by + ::KHUI_MAXCCH_LONG_DESC */ + + afs_tk_method method_id; /*!< Once the message is processed, + this will receive a new method + identifier. The value of this field + on entry is ignored. */ + + } token_acq; /*!< Registration information for + token acquisition method. Only + assumed to be valid if \a + provide_token_acq is TRUE. */ + +} afs_msg_announce; + +/*! \brief Sent to all extensions to resolve the identity of a token + + If the identity and credentials acquisition method of an AFS token + cannot be determined by the AFS plugin, this message is sent out + to extension plugins to allow them a chance to resolve it. + + If the extension plugin successfully resolves the identity and + token acquisition method of the specified token, it should return + ::KHM_ERROR_SUCCESS. Otherwise it should return a failure code. + The actual return code is not interpreted other than whether or + not it passes the ::KHM_SUCCEEDED() test. + + + + + + +
Typetype ID of ::AFS_MSG_TYPENAME
Subtype::AFS_MSG_RESOLVE_TOKEN
uparam0
vparamPointer to a ::afs_msg_resolve_token structure
+ + \note This message is only sent from the AFS plugin to extension plugins + + \note Only sent if the extension plugin has ::provide_token_acq set. + */ +#define AFS_MSG_RESOLVE_TOKEN 2 + +/*! \brief Message structure for AFS_MSG_RESOLVE_TOKEN + + Other than the fields marked as \a [OUT], all other fields should + be considered read-only and should not be modified. + + \see ::AFS_MSG_RESOLVE_TOKEN + */ +typedef struct tag_afs_msg_resolve_token_v1 { + khm_size cbsize; /*!< Size of the structure. This will + be set to \a + sizeof(::afs_msg_resolve_token). */ + + const wchar_t * cell; /*!< Specifies the cell that the token + belongs to. */ + + const struct ktc_token * token; /*!< The token */ + const struct ktc_principal * serverp; /*!< Server principal */ + const struct ktc_principal * clientp; /*!< Client principal */ + + khm_handle ident; /*!< [OUT] If the extension + successfully resolves the identity, + then it should assign a handle to + the identity to this field and + return ::KHM_ERROR_SUCCESS. The + handle will be automatically freed + by the AFS plugin. */ + + afs_tk_method method; /*!< [OUT] If the extension + successfully resolves the identity, + it should also assign the token + acquisition method identifier to + this field. The default method is + ::AFS_TOKEN_AUTO. This field + indicates the token acquisition + method that was used to obtain the + token and is used when the token + needs to be renewed. */ +} afs_msg_resolve_token; + +/*! \brief Sent to an extension plugin to obtain AFS tokens + + + + + + +
Typetype ID of ::AFS_MSG_TYPENAME
Subtype::AFS_MSG_KLOG
uparam0
vparamPointer to a ::afs_msg_klog
+ + \note Only sent from the AFS plugin to extension plugins + \note Only sent to extension plugins which have ::provide_token_acq set. +*/ +#define AFS_MSG_KLOG 3 + +/*! \brief Cell configuration information + + \see ::afs_msg_klog + + \note This structure uses ANSI char fields instead of unicode fields. + */ +typedef struct tag_afs_conf_cellA_v1 { + khm_size cbsize; /*!< set to \a sizeof(afs_conf_cell) */ + + char name[MAXCELLCHARS]; /*!< Name of the cell */ + short numServers; /*!< Number of servers for cell. + Upper bound of MAXHOSTSPERCELL */ + short flags; /*!< Not used. Set to zero. */ + struct sockaddr_in hostAddr[MAXHOSTSPERCELL]; + /*!< addresses for each server. There + are \a numServers entries.*/ + char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS]; + /*!< names of the servers. There are + \a numServers entries. */ + char * linkedCell; /*!< Not used. Set to zero. */ +} afs_conf_cell; + +/*! \brief Message parameters for AFS_MSG_KLOG message + + \see ::AFS_MSG_KLOG + + \note This structure uses ANSI char fields instead of unicode fields. + */ +typedef struct tag_afs_msg_klogA_v1 { + khm_size cbsize; /*!< Set to \a sizeof(afs_msg_klog) */ + + khm_handle identity; /*!< Handle to identity for which we + are obtaining tokens. */ + + const char * service; /*!< Service name to use when + obtaining token. This can be NULL + if the service name has not be + determined. */ + + const char * cell; /*!< Name of cell to obtain tokens + for. Can be NULL if the local cell + is to be used. */ + + const char * realm; /*!< Realm to use when obtaining + tokens. Can be NULL if the realm + has not been determined. */ + + const afs_conf_cell * cell_config; /*!< Cell configuration for the + cell specified in \a cell. */ + + khm_int32 lifetime; /*!< Advisory lifetime specifier, in + seconds. If set to zero, means + there is no specification for + lifetime. Extensions should feel + free to ignore this parameter. */ +} afs_msg_klog; + +/*!@}*/ + +/*!@}*/ + +#endif diff --git a/src/WINNT/netidmgr_plugin/afsplugin.c b/src/WINNT/netidmgr_plugin/afsplugin.c new file mode 100644 index 0000000..3dd47e1 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsplugin.c @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include +#include + +static BOOL initialized = FALSE; +khm_int32 afs_credtype_id = -1; +khm_int32 krb5_credtype_id = -1; +khm_int32 krb4_credtype_id = -1; +khm_int32 afs_msg_type_id = -1; +khm_int32 afs_type_principal = -1; +khm_int32 afs_type_method = -1; +khm_int32 afs_attr_client_princ = -1; +khm_int32 afs_attr_server_princ = -1; +khm_int32 afs_attr_cell = -1; +khm_int32 afs_attr_method = -1; +khm_int32 afs_attr_realm = -1; +khm_handle afs_credset = NULL; +khm_handle afs_sub = NULL; /* AFS message subscription */ + +/* forward dcls */ +khm_int32 KHMAPI +afs_msg_system(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); + +khm_int32 KHMAPI +afs_msg_kcdb(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); + +khm_int32 KHMAPI +afs_msg_cred(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); + +khm_int32 KHMAPI +afs_msg_ext(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam); + +/* AFS plugin callback */ +khm_int32 KHMAPI +afs_plugin_cb(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) +{ + if (msg_type == KMSG_SYSTEM) + return afs_msg_system(msg_subtype, uparam, vparam); + if (msg_type == KMSG_KCDB) + return afs_msg_kcdb(msg_subtype, uparam, vparam); + if (msg_type == KMSG_CRED) + return afs_msg_cred(msg_subtype, uparam, vparam); + if (msg_type == afs_msg_type_id) + return afs_msg_ext(msg_subtype, uparam, vparam); + + return KHM_ERROR_SUCCESS; +} + +/* ktc_principal attribute type */ +/* String */ + +khm_int32 KHMAPI +afs_type_principal_toString(const void * d, + khm_size cbd, + wchar_t * buffer, + khm_size * cb_buf, + khm_int32 flags) +{ + size_t cbsize; + struct ktc_principal * p; + wchar_t sprinc[512] = L""; + + if(!cb_buf) + return KHM_ERROR_INVALID_PARAM; + + p = (struct ktc_principal *) d; + + // assume this works. + afs_princ_to_string(p, sprinc, sizeof(sprinc)); + StringCbLength(sprinc, sizeof(sprinc), &cbsize); + cbsize += sizeof(wchar_t); + + if(!buffer || *cb_buf < cbsize) { + *cb_buf = cbsize; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buffer, *cb_buf, sprinc); + + *cb_buf = cbsize; + + return KHM_ERROR_SUCCESS; +} + +khm_boolean KHMAPI +afs_type_principal_isValid(const void * d, + khm_size cbd) +{ + /*TODO: check for more inconsistencies */ + if(cbd != sizeof(struct ktc_principal)) + return FALSE; + return TRUE; +} + +khm_int32 KHMAPI +afs_type_principal_comp(const void * d1, + khm_size cbd1, + const void * d2, + khm_size cbd2) +{ + struct ktc_principal * p1 = (struct ktc_principal *) d1; + struct ktc_principal * p2 = (struct ktc_principal *) d2; + int r; + + r = strcmp(p1->name, p2->name); + if(r != 0) + return r; + r = strcmp(p1->instance, p2->instance); + if(r != 0) + return r; + r = strcmp(p1->cell, p2->cell); + return r; +} + +khm_int32 KHMAPI +afs_type_principal_dup(const void * d_src, + khm_size cbd_src, + void * d_dst, + khm_size * cbd_dst) +{ + if(!d_dst || *cbd_dst < sizeof(struct ktc_principal)) { + *cbd_dst = sizeof(struct ktc_principal); + return KHM_ERROR_TOO_LONG; + } + + memcpy(d_dst, d_src, sizeof(struct ktc_principal)); + *cbd_dst = sizeof(struct ktc_principal); + + return KHM_ERROR_SUCCESS; +} + +khm_int32 KHMAPI +afs_type_method_toString(const void * data, + khm_size cb_data, + wchar_t * s_buf, + khm_size * pcb_s_buf, + khm_int32 flags) { + khm_int32 * pmethod = (khm_int32 *) data; + wchar_t wbuf[KHUI_MAXCCH_LONG_DESC]; + khm_size cb; + + if (!data || cb_data != sizeof(khm_int32)) + return KHM_ERROR_INVALID_PARAM; + + wbuf[0] = L'\0'; + if (!afs_method_describe(*pmethod, flags, wbuf, sizeof(wbuf))) { + LoadString(hResModule, + IDS_NC_METHOD_INVALID, + wbuf, + ARRAYLENGTH(wbuf)); + } + + StringCbLength(wbuf, sizeof(wbuf), &cb); + cb += sizeof(wchar_t); + + if (!s_buf || *pcb_s_buf < cb) { + *pcb_s_buf = cb; + return KHM_ERROR_TOO_LONG; + } else { + StringCbCopy(s_buf, *pcb_s_buf, wbuf); + *pcb_s_buf = cb; + return KHM_ERROR_SUCCESS; + } +} + +/* process KMSG_SYSTEM messages */ +khm_int32 KHMAPI +afs_msg_system(khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) +{ + khm_int32 rv = KHM_ERROR_UNKNOWN; + + switch(msg_subtype) { + case KMSG_SYSTEM_INIT: + /* Perform critical registrations and data structure + initalization */ + { + kcdb_credtype ct; + wchar_t buf[KCDB_MAXCCH_LONG_DESC]; + size_t cbsize; + kcdb_attrib att; + khm_handle csp_afscred = NULL; + khm_int32 disable_afscreds = FALSE; + + ZeroMemory(&ct, sizeof(ct)); + /* first of all, register the AFS token credential type */ + ct.id = KCDB_CREDTYPE_AUTO; + ct.name = AFS_CREDTYPE_NAME; + + if(LoadString(hResModule, + IDS_AFS_SHORT_DESC, + buf, + ARRAYLENGTH(buf)) != 0) { + StringCbLength(buf, sizeof(buf), &cbsize); + cbsize += sizeof(wchar_t); + ct.short_desc = PMALLOC(cbsize); + StringCbCopy(ct.short_desc, cbsize, buf); + } else + ct.short_desc = NULL; + + if(LoadString(hResModule, + IDS_AFS_LONG_DESC, + buf, + ARRAYLENGTH(buf)) != 0) { + StringCbLength(buf, sizeof(buf), &cbsize); + cbsize += sizeof(wchar_t); + ct.long_desc = PMALLOC(cbsize); + StringCbCopy(ct.long_desc, cbsize, buf); + } else + ct.long_desc = NULL; + + ct.icon = LoadImage(hResModule, + MAKEINTRESOURCE(IDI_AFSTOKEN), + IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE); + + kmq_create_subscription(afs_plugin_cb, &afs_sub); + ct.sub = afs_sub; + + kcdb_credtype_register(&ct, &afs_credtype_id); + + /* register the attribute types */ + { + kcdb_type type; + + ZeroMemory(&type, sizeof(type)); + type.comp = afs_type_principal_comp; + type.dup = afs_type_principal_dup; + type.isValid = afs_type_principal_isValid; + type.toString = afs_type_principal_toString; + type.name = AFS_TYPENAME_PRINCIPAL; + type.id = KCDB_TYPE_INVALID; + type.cb_max = sizeof(struct ktc_principal); + type.cb_min = sizeof(struct ktc_principal); + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + + if(KHM_FAILED(kcdb_type_register(&type, + &afs_type_principal))) + goto _exit_init; + } + + { + kcdb_type type; + kcdb_type *ti32 = NULL; + + kcdb_type_get_info(KCDB_TYPE_INT32, &ti32); + + ZeroMemory(&type, sizeof(type)); + type.comp = ti32->comp; + type.dup = ti32->dup; + type.isValid = ti32->isValid; + type.toString = afs_type_method_toString; + type.name = AFS_TYPENAME_METHOD; + type.id = KCDB_TYPE_INVALID; + type.cb_max = sizeof(khm_int32); + type.cb_min = sizeof(khm_int32); + type.flags = KCDB_TYPE_FLAG_CB_FIXED; + + if(KHM_FAILED(kcdb_type_register(&type, + &afs_type_method))) { + kcdb_type_release_info(ti32); + goto _exit_init; + } + + kcdb_type_release_info(ti32); + } + + /* now register the attributes */ + { + wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; + + ZeroMemory(&att, sizeof(att)); + + att.type = KCDB_TYPE_STRING; + att.name = AFS_ATTRNAME_CELL; + LoadString(hResModule, + IDS_ATTR_CELL_SHORT_DESC, + short_desc, + ARRAYLENGTH(short_desc)); + att.short_desc = short_desc; + att.long_desc = NULL; + att.id = KCDB_ATTR_INVALID; + att.flags = KCDB_ATTR_FLAG_TRANSIENT; + + if(KHM_FAILED(rv = kcdb_attrib_register(&att, + &afs_attr_cell))) + goto _exit_init; + } + + { + wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; + + ZeroMemory(&att, sizeof(att)); + + att.type = KCDB_TYPE_STRING; + att.name = AFS_ATTRNAME_REALM; + LoadString(hResModule, + IDS_ATTR_REALM_SHORT_DESC, + short_desc, + ARRAYLENGTH(short_desc)); + att.short_desc = short_desc; + att.long_desc = NULL; + att.id = KCDB_ATTR_INVALID; + att.flags = KCDB_ATTR_FLAG_TRANSIENT; + + if(KHM_FAILED(rv = kcdb_attrib_register(&att, + &afs_attr_realm))) + goto _exit_init; + } + + { + wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; + + ZeroMemory(&att, sizeof(att)); + + att.type = afs_type_method; + att.name = AFS_ATTRNAME_METHOD; + LoadString(hResModule, + IDS_ATTR_METHOD_SHORT_DESC, + short_desc, + ARRAYLENGTH(short_desc)); + att.short_desc = short_desc; + att.long_desc = NULL; + att.id = KCDB_ATTR_INVALID; + att.flags = KCDB_ATTR_FLAG_TRANSIENT; + + if(KHM_FAILED(rv = kcdb_attrib_register(&att, + &afs_attr_method))) + goto _exit_init; + } + + { + wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; + + ZeroMemory(&att, sizeof(att)); + + att.type = afs_type_principal; + att.name = AFS_ATTRNAME_CLIENT_PRINC; + LoadString(hResModule, + IDS_ATTR_CLIENT_PRINC_SHORT_DESC, + short_desc, + ARRAYLENGTH(short_desc)); + att.short_desc = short_desc; + att.long_desc = NULL; + att.id = KCDB_ATTR_INVALID; + att.flags = KCDB_ATTR_FLAG_TRANSIENT; + + if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_client_princ))) + goto _exit_init; + } + + { + wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; + + ZeroMemory(&att, sizeof(att)); + + att.type = afs_type_principal; + att.name = AFS_ATTRNAME_SERVER_PRINC; + LoadString(hResModule, + IDS_ATTR_SERVER_PRINC_SHORT_DESC, + short_desc, ARRAYLENGTH(short_desc)); + att.short_desc = short_desc; + att.long_desc = NULL; + att.id = KCDB_ATTR_INVALID; + att.flags = KCDB_ATTR_FLAG_TRANSIENT; + + if(KHM_FAILED(rv = kcdb_attrib_register(&att, &afs_attr_server_princ))) + goto _exit_init; + } + + /* afs_credset is our stock credentials set that we + use for all our credset needs (instead of creating + a new one every time) */ + + if(KHM_FAILED(rv = kcdb_credset_create(&afs_credset))) + goto _exit_init; + + if(KHM_FAILED(rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME, + &krb5_credtype_id))) + goto _exit_init; + + /* register the configuration nodes */ + { + khui_config_node node_ident; + khui_config_node_reg reg; + wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC]; + wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC]; + + if (KHM_FAILED(rv = khui_cfg_open(NULL, + L"KhmIdentities", + &node_ident))) + goto _exit_init; + + ZeroMemory(®, sizeof(reg)); + reg.name = AFS_CONFIG_NODE_MAIN; + reg.short_desc = wshort_desc; + reg.long_desc = wlong_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_AFS); + reg.dlg_proc = afs_cfg_main_proc; + reg.flags = 0; + LoadString(hResModule, IDS_CFG_MAIN_LONG, + wlong_desc, ARRAYLENGTH(wlong_desc)); + LoadString(hResModule, IDS_CFG_MAIN_SHORT, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(NULL, ®); + + ZeroMemory(®, sizeof(reg)); + reg.name = AFS_CONFIG_NODE_IDS; + reg.short_desc = wshort_desc; + reg.long_desc = wshort_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB); + reg.dlg_proc = afs_cfg_ids_proc; + reg.flags = KHUI_CNFLAG_SUBPANEL; + LoadString(hResModule, IDS_CFG_IDS_TAB, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(node_ident, ®); + + ZeroMemory(®, sizeof(reg)); + reg.name = AFS_CONFIG_NODE_ID; + reg.short_desc = wshort_desc; + reg.long_desc = wshort_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB); + reg.dlg_proc = afs_cfg_id_proc; + reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL; + LoadString(hResModule, IDS_CFG_ID_TAB, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(node_ident, ®); + } + + /* and register the AFS message type */ + rv = kmq_register_type(AFS_MSG_TYPENAME, &afs_msg_type_id); + + if (KHM_SUCCEEDED(rv)) + kmq_subscribe(afs_msg_type_id, afs_plugin_cb); + + /* if the configuration is set to disable afscreds.exe, + then we look for the shortcut and remove it if + found. */ + if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, + 0, + &csp_afscred))) { + wchar_t wpath[MAX_PATH]; + + khc_read_int32(csp_afscred, L"Disableafscreds", + &disable_afscreds); + + if (disable_afscreds && + afs_cfg_get_afscreds_shortcut(wpath)) { + + DeleteFile(wpath); + + } + + khc_close_space(csp_afscred); + } + + _exit_init: + if(ct.short_desc) + PFREE(ct.short_desc); + if(ct.long_desc) + PFREE(ct.long_desc); + } + /* now that the critical stuff is done, we move on to the + non-critical stuff */ + if(KHM_SUCCEEDED(rv)) { + initialized = TRUE; + + /* obtain existing tokens */ + afs_list_tokens(); + } + + /* define this so that if there are no TGT's, we don't + deadlock trying to open a new creds dialog from within the + new creds dialog. */ + SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1"); + + break; + /* end of KMSG_SYSTEM_INIT */ + + case KMSG_SYSTEM_EXIT: + if (afs_msg_type_id != -1) { + kmq_unsubscribe(afs_msg_type_id, afs_plugin_cb); + kmq_unregister_type(afs_msg_type_id); + } + if(afs_credtype_id >= 0) { + kcdb_credtype_unregister(afs_credtype_id); + } +#if 0 + if(afs_attr_client >= 0) { + kcdb_attrib_unregister(afs_attr_client); + } +#endif + if(afs_attr_cell >= 0) { + kcdb_attrib_unregister(afs_attr_cell); + } + if(afs_attr_realm >= 0) { + kcdb_attrib_unregister(afs_attr_realm); + } + if(afs_attr_method >= 0) { + kcdb_attrib_unregister(afs_attr_method); + } + if(afs_attr_client_princ >= 0) { + kcdb_attrib_unregister(afs_attr_client_princ); + } + if(afs_attr_server_princ >= 0) { + kcdb_attrib_unregister(afs_attr_server_princ); + } + if(afs_type_principal >= 0) { + kcdb_type_unregister(afs_type_principal); + } + if(afs_type_method >= 0) { + kcdb_type_unregister(afs_type_method); + } + initialized = FALSE; + if(afs_credset) + kcdb_credset_delete(afs_credset); + + /* afs_sub doesn't need to be deleted. That is taken care + of when unregistering the afs cred type */ + afs_sub = NULL; + + rv = KHM_ERROR_SUCCESS; + break; + /* end of KMSG_SYSTEM_EXIT */ + } + return rv; +} + +/* process KMSG_KCDB messages */ +khm_int32 KHMAPI +afs_msg_kcdb(khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + /* we don't really do anything with this yet */ +#if 0 + switch(msg_subtype) { + } +#endif + + return rv; +} + + + +static khm_int32 KHMAPI +afs_cred_destroy_proc(khm_handle cred, void * rock) { + khm_int32 t; + + if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) || + t != afs_credtype_id) + return KHM_ERROR_SUCCESS; + + afs_unlog_cred(cred); + + return KHM_ERROR_SUCCESS; +} + +/* process KMSG_CRED messages */ +khm_int32 KHMAPI +afs_msg_cred(khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_CRED_REFRESH: + afs_list_tokens(); + break; + + case KMSG_CRED_DESTROY_CREDS: + { + khui_action_context * ctx; + + ctx = (khui_action_context *) vparam; + + if (ctx->credset) { + _begin_task(0); + _report_cs0(KHERR_INFO, L"Destroying AFS Tokens"); + _describe(); + + kcdb_credset_apply(ctx->credset, + afs_cred_destroy_proc, + NULL); + + _end_task(); + } + } + break; + + default: + + if (IS_CRED_ACQ_MSG(msg_subtype)) + return afs_msg_newcred(msg_subtype, uparam, vparam); + } + + return rv; +} + diff --git a/src/WINNT/netidmgr_plugin/afsplugin_custom.c b/src/WINNT/netidmgr_plugin/afsplugin_custom.c new file mode 100644 index 0000000..d32b878 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/afsplugin_custom.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include +#include +#include + +static +const TCHAR * const dword_props[] = { + _TEXT("OPENAFSVERSIONMAJOR"), + _TEXT("OPENAFSVERSIONMINOR"), + _TEXT("KFWVERSIONMAJOR") +}; + +static void strip_decoration(TCHAR * str, int cchlen) { + int i; + + if (str[0] != _T('#') || cchlen < 1) + return; + + for (i=1; i < cchlen && str[i]; i++) { + str[i-1] = str[i]; + } + + str[i-1] = _T('\0'); +} + +UINT __stdcall StripRegDecoration(MSIHANDLE hInstall) { + TCHAR propbuffer[16]; /* we are looking for string + representations of DOWRDs. They + can't be longer than this. */ + DWORD cch_buffer; + UINT rv; + int i; + + for (i=0; i < sizeof(dword_props)/sizeof(dword_props[0]); i++) { + cch_buffer = sizeof(propbuffer)/sizeof(propbuffer[0]); + rv = MsiGetProperty(hInstall, dword_props[i], propbuffer, &cch_buffer); + if (rv == ERROR_SUCCESS) { + strip_decoration(propbuffer, cch_buffer); + MsiSetProperty(hInstall, dword_props[i], propbuffer); + } + } + + return ERROR_SUCCESS; +} diff --git a/src/WINNT/netidmgr_plugin/dynimport.c b/src/WINNT/netidmgr_plugin/dynimport.c new file mode 100644 index 0000000..bb4b8bd --- /dev/null +++ b/src/WINNT/netidmgr_plugin/dynimport.c @@ -0,0 +1,463 @@ +/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation +* files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, +* modify, merge, publish, distribute, sublicense, and/or sell copies +* of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +/* $Id$ */ + +#include +#include +#include +#include + +HINSTANCE hKrb4 = 0; +HINSTANCE hKrb5 = 0; +HINSTANCE hKrb524 = 0; +HINSTANCE hSecur32 = 0; +HINSTANCE hComErr = 0; +HINSTANCE hService = 0; +HINSTANCE hProfile = 0; +HINSTANCE hPsapi = 0; +HINSTANCE hToolHelp32 = 0; +HINSTANCE hCCAPI = 0; + +DWORD AfsAvailable = 0; + +// CCAPI +DECL_FUNC_PTR(cc_initialize); +DECL_FUNC_PTR(cc_shutdown); +DECL_FUNC_PTR(cc_get_NC_info); +DECL_FUNC_PTR(cc_free_NC_info); + +// krb4 functions +DECL_FUNC_PTR(get_krb_err_txt_entry); +DECL_FUNC_PTR(k_isinst); +DECL_FUNC_PTR(k_isname); +DECL_FUNC_PTR(k_isrealm); +DECL_FUNC_PTR(kadm_change_your_password); +DECL_FUNC_PTR(kname_parse); +DECL_FUNC_PTR(krb_get_cred); +DECL_FUNC_PTR(krb_get_krbhst); +DECL_FUNC_PTR(krb_get_lrealm); +DECL_FUNC_PTR(krb_get_pw_in_tkt); +DECL_FUNC_PTR(krb_get_tf_realm); +DECL_FUNC_PTR(krb_mk_req); +DECL_FUNC_PTR(krb_realmofhost); +DECL_FUNC_PTR(tf_init); +DECL_FUNC_PTR(tf_close); +DECL_FUNC_PTR(tf_get_cred); +DECL_FUNC_PTR(tf_get_pname); +DECL_FUNC_PTR(tf_get_pinst); +DECL_FUNC_PTR(LocalHostAddr); +DECL_FUNC_PTR(tkt_string); +DECL_FUNC_PTR(krb_set_tkt_string); +DECL_FUNC_PTR(initialize_krb_error_func); +DECL_FUNC_PTR(initialize_kadm_error_table); +DECL_FUNC_PTR(dest_tkt); +DECL_FUNC_PTR(krb_in_tkt); +DECL_FUNC_PTR(krb_save_credentials); +DECL_FUNC_PTR(krb_get_krbconf2); +DECL_FUNC_PTR(krb_get_krbrealm2); +DECL_FUNC_PTR(krb_life_to_time); + +// krb5 functions +DECL_FUNC_PTR(krb5_change_password); +DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_get_prompt_types); +DECL_FUNC_PTR(krb5_build_principal_ext); +DECL_FUNC_PTR(krb5_cc_get_name); +DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_cc_initialize); +DECL_FUNC_PTR(krb5_cc_destroy); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_store_cred); +DECL_FUNC_PTR(krb5_cc_copy_creds); +DECL_FUNC_PTR(krb5_cc_retrieve_cred); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_cc_start_seq_get); +DECL_FUNC_PTR(krb5_cc_next_cred); +DECL_FUNC_PTR(krb5_cc_end_seq_get); +DECL_FUNC_PTR(krb5_cc_remove_cred); +DECL_FUNC_PTR(krb5_cc_set_flags); +// DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_timeofday); +DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_get_credentials); +DECL_FUNC_PTR(krb5_mk_req); +DECL_FUNC_PTR(krb5_sname_to_principal); +DECL_FUNC_PTR(krb5_get_credentials_renew); +DECL_FUNC_PTR(krb5_free_data); +DECL_FUNC_PTR(krb5_free_data_contents); +// DECL_FUNC_PTR(krb5_get_realm_domain); +DECL_FUNC_PTR(krb5_free_unparsed_name); +DECL_FUNC_PTR(krb5_os_localaddr); +DECL_FUNC_PTR(krb5_copy_keyblock_contents); +DECL_FUNC_PTR(krb5_copy_data); +DECL_FUNC_PTR(krb5_free_creds); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_get_renewed_creds); +DECL_FUNC_PTR(krb5_get_default_config_files); +DECL_FUNC_PTR(krb5_free_config_files); +DECL_FUNC_PTR(krb5_get_default_realm); +DECL_FUNC_PTR(krb5_set_default_realm); +DECL_FUNC_PTR(krb5_free_ticket); +DECL_FUNC_PTR(krb5_decode_ticket); +DECL_FUNC_PTR(krb5_get_host_realm); +DECL_FUNC_PTR(krb5_free_host_realm); +DECL_FUNC_PTR(krb5_c_random_make_octets); +DECL_FUNC_PTR(krb5_free_addresses); +DECL_FUNC_PTR(krb5_free_default_realm); + +// Krb524 functions +DECL_FUNC_PTR(krb524_init_ets); +DECL_FUNC_PTR(krb524_convert_creds_kdc); + +// ComErr functions +DECL_FUNC_PTR(com_err); +DECL_FUNC_PTR(error_message); + +// Profile functions +DECL_FUNC_PTR(profile_init); +DECL_FUNC_PTR(profile_flush); +DECL_FUNC_PTR(profile_release); +DECL_FUNC_PTR(profile_get_subsection_names); +DECL_FUNC_PTR(profile_free_list); +DECL_FUNC_PTR(profile_get_string); +DECL_FUNC_PTR(profile_get_values); +DECL_FUNC_PTR(profile_get_relation_names); +DECL_FUNC_PTR(profile_clear_relation); +DECL_FUNC_PTR(profile_add_relation); +DECL_FUNC_PTR(profile_update_relation); +DECL_FUNC_PTR(profile_release_string); + +// Service functions +DECL_FUNC_PTR(OpenSCManagerA); +DECL_FUNC_PTR(OpenServiceA); +DECL_FUNC_PTR(QueryServiceStatus); +DECL_FUNC_PTR(CloseServiceHandle); +DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions +DECL_FUNC_PTR(LsaConnectUntrusted); +DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +DECL_FUNC_PTR(LsaCallAuthenticationPackage); +DECL_FUNC_PTR(LsaFreeReturnBuffer); +DECL_FUNC_PTR(LsaGetLogonSessionData); + +// CCAPI +FUNC_INFO ccapi_fi[] = { + MAKE_FUNC_INFO(cc_initialize), + MAKE_FUNC_INFO(cc_shutdown), + MAKE_FUNC_INFO(cc_get_NC_info), + MAKE_FUNC_INFO(cc_free_NC_info), + END_FUNC_INFO +}; + +FUNC_INFO k4_fi[] = { + MAKE_FUNC_INFO(get_krb_err_txt_entry), + MAKE_FUNC_INFO(k_isinst), + MAKE_FUNC_INFO(k_isname), + MAKE_FUNC_INFO(k_isrealm), + MAKE_FUNC_INFO(kadm_change_your_password), + MAKE_FUNC_INFO(kname_parse), + MAKE_FUNC_INFO(krb_get_cred), + MAKE_FUNC_INFO(krb_get_krbhst), + MAKE_FUNC_INFO(krb_get_lrealm), + MAKE_FUNC_INFO(krb_get_pw_in_tkt), + MAKE_FUNC_INFO(krb_get_tf_realm), + MAKE_FUNC_INFO(krb_mk_req), + MAKE_FUNC_INFO(krb_realmofhost), + MAKE_FUNC_INFO(tf_init), + MAKE_FUNC_INFO(tf_close), + MAKE_FUNC_INFO(tf_get_cred), + MAKE_FUNC_INFO(tf_get_pname), + MAKE_FUNC_INFO(tf_get_pinst), + MAKE_FUNC_INFO(LocalHostAddr), + MAKE_FUNC_INFO(tkt_string), + MAKE_FUNC_INFO(krb_set_tkt_string), + MAKE_FUNC_INFO(initialize_krb_error_func), + MAKE_FUNC_INFO(initialize_kadm_error_table), + MAKE_FUNC_INFO(dest_tkt), + /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX + MAKE_FUNC_INFO(krb_in_tkt), + MAKE_FUNC_INFO(krb_save_credentials), + MAKE_FUNC_INFO(krb_get_krbconf2), + MAKE_FUNC_INFO(krb_get_krbrealm2), + MAKE_FUNC_INFO(krb_life_to_time), + END_FUNC_INFO +}; + +FUNC_INFO k5_fi[] = { + MAKE_FUNC_INFO(krb5_change_password), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_init), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_get_prompt_types), + MAKE_FUNC_INFO(krb5_build_principal_ext), + MAKE_FUNC_INFO(krb5_cc_get_name), + MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_cc_initialize), + MAKE_FUNC_INFO(krb5_cc_destroy), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_copy_creds), + MAKE_FUNC_INFO(krb5_cc_store_cred), + MAKE_FUNC_INFO(krb5_cc_retrieve_cred), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_cc_start_seq_get), + MAKE_FUNC_INFO(krb5_cc_next_cred), + MAKE_FUNC_INFO(krb5_cc_end_seq_get), + MAKE_FUNC_INFO(krb5_cc_remove_cred), + MAKE_FUNC_INFO(krb5_cc_set_flags), + // MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_get_in_tkt_with_password), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_timeofday), + MAKE_FUNC_INFO(krb5_timestamp_to_sfstring), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_get_credentials), + MAKE_FUNC_INFO(krb5_mk_req), + MAKE_FUNC_INFO(krb5_sname_to_principal), + MAKE_FUNC_INFO(krb5_get_credentials_renew), + MAKE_FUNC_INFO(krb5_free_data), + MAKE_FUNC_INFO(krb5_free_data_contents), + // MAKE_FUNC_INFO(krb5_get_realm_domain), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + MAKE_FUNC_INFO(krb5_os_localaddr), + MAKE_FUNC_INFO(krb5_copy_keyblock_contents), + MAKE_FUNC_INFO(krb5_copy_data), + MAKE_FUNC_INFO(krb5_free_creds), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_get_renewed_creds), + MAKE_FUNC_INFO(krb5_free_addresses), + MAKE_FUNC_INFO(krb5_get_default_config_files), + MAKE_FUNC_INFO(krb5_free_config_files), + MAKE_FUNC_INFO(krb5_get_default_realm), + MAKE_FUNC_INFO(krb5_set_default_realm), + MAKE_FUNC_INFO(krb5_free_ticket), + MAKE_FUNC_INFO(krb5_decode_ticket), + MAKE_FUNC_INFO(krb5_get_host_realm), + MAKE_FUNC_INFO(krb5_free_host_realm), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + MAKE_FUNC_INFO(krb5_free_default_realm), + END_FUNC_INFO +}; + +FUNC_INFO k524_fi[] = { + MAKE_FUNC_INFO(krb524_init_ets), + MAKE_FUNC_INFO(krb524_convert_creds_kdc), + END_FUNC_INFO +}; + +FUNC_INFO profile_fi[] = { + MAKE_FUNC_INFO(profile_init), + MAKE_FUNC_INFO(profile_flush), + MAKE_FUNC_INFO(profile_release), + MAKE_FUNC_INFO(profile_get_subsection_names), + MAKE_FUNC_INFO(profile_free_list), + MAKE_FUNC_INFO(profile_get_string), + MAKE_FUNC_INFO(profile_get_values), + MAKE_FUNC_INFO(profile_get_relation_names), + MAKE_FUNC_INFO(profile_clear_relation), + MAKE_FUNC_INFO(profile_add_relation), + MAKE_FUNC_INFO(profile_update_relation), + MAKE_FUNC_INFO(profile_release_string), + END_FUNC_INFO +}; + +FUNC_INFO ce_fi[] = { + MAKE_FUNC_INFO(com_err), + MAKE_FUNC_INFO(error_message), + END_FUNC_INFO +}; + +FUNC_INFO service_fi[] = { + MAKE_FUNC_INFO(OpenSCManagerA), + MAKE_FUNC_INFO(OpenServiceA), + MAKE_FUNC_INFO(QueryServiceStatus), + MAKE_FUNC_INFO(CloseServiceHandle), + MAKE_FUNC_INFO(LsaNtStatusToWinError), + END_FUNC_INFO +}; + +FUNC_INFO lsa_fi[] = { + MAKE_FUNC_INFO(LsaConnectUntrusted), + MAKE_FUNC_INFO(LsaLookupAuthenticationPackage), + MAKE_FUNC_INFO(LsaCallAuthenticationPackage), + MAKE_FUNC_INFO(LsaFreeReturnBuffer), + MAKE_FUNC_INFO(LsaGetLogonSessionData), + 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 +}; + +khm_int32 init_imports(void) { + OSVERSIONINFO osvi; + int imp_rv = 1; + +#define CKRV if(!imp_rv) goto _err_ret + +#ifndef _WIN64 + imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0); + CKRV; +#endif + + imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0); + CKRV; + + imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0); + CKRV; + + imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0); + CKRV; + + imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1); + CKRV; + + imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1); + CKRV; + + imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0); + CKRV; + + imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0); + /* CCAPI_DLL is optional. No error check. */ + + 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 + imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0); + CKRV; + + hPsapi = 0; + } + else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Windows NT + imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0); + CKRV; + + hToolHelp32 = 0; + } + + AfsAvailable = TRUE; //afscompat_init(); + + return KHM_ERROR_SUCCESS; + + _err_ret: + return KHM_ERROR_NOT_FOUND; +} + +khm_int32 exit_imports(void) { + //afscompat_close(); + + if (hKrb4) + FreeLibrary(hKrb4); + if (hKrb5) + FreeLibrary(hKrb5); + if (hProfile) + FreeLibrary(hProfile); + if (hComErr) + FreeLibrary(hComErr); + if (hService) + FreeLibrary(hService); + if (hSecur32) + FreeLibrary(hSecur32); + if (hKrb524) + FreeLibrary(hKrb524); + if (hPsapi) + FreeLibrary(hPsapi); + if (hToolHelp32) + FreeLibrary(hToolHelp32); + + return KHM_ERROR_SUCCESS; +} + +int (*Lcom_err)(LPSTR,long,LPSTR,...); +LPSTR (*Lerror_message)(long); +LPSTR (*Lerror_table_name)(long); + +void Leash_load_com_err_callback(FARPROC ce, + FARPROC em, + FARPROC etn) +{ + (FARPROC)Lcom_err=ce; + (FARPROC)Lerror_message=em; + (FARPROC)Lerror_table_name=etn; +} diff --git a/src/WINNT/netidmgr_plugin/dynimport.h b/src/WINNT/netidmgr_plugin/dynimport.h new file mode 100644 index 0000000..46c72e0 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/dynimport.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_DYNIMPORT_H +#define __KHIMAIRA_DYNIMPORT_H + +/* Dynamic imports */ +#include +#include +#include + +#ifndef FAR +#define FAR +#endif + +extern HINSTANCE hKrb4; +extern HINSTANCE hKrb5; +extern HINSTANCE hProfile; + +/////////////////////////////////////////////////////////////////////////////// + +#define CCAPI_DLL "krbcc32.dll" +#define KRBCC32_DLL "krbcc32.dll" +#define SERVICE_DLL "advapi32.dll" +#define SECUR32_DLL "secur32.dll" +#define PROFILE_DLL "xpprof32.dll" + +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +//// CCAPI +/* In order to avoid including the private CCAPI headers */ +typedef int cc_int32; + +#define CC_API_VER_1 1 +#define CC_API_VER_2 2 + +#define CCACHE_API cc_int32 + +/* +** The Official Error Codes +*/ +#define CC_NOERROR 0 +#define CC_BADNAME 1 +#define CC_NOTFOUND 2 +#define CC_END 3 +#define CC_IO 4 +#define CC_WRITE 5 +#define CC_NOMEM 6 +#define CC_FORMAT 7 +#define CC_LOCKED 8 +#define CC_BAD_API_VERSION 9 +#define CC_NO_EXIST 10 +#define CC_NOT_SUPP 11 +#define CC_BAD_PARM 12 +#define CC_ERR_CACHE_ATTACH 13 +#define CC_ERR_CACHE_RELEASE 14 +#define CC_ERR_CACHE_FULL 15 +#define CC_ERR_CRED_VERSION 16 + +enum { + CC_CRED_VUNKNOWN = 0, // For validation + CC_CRED_V4 = 1, + CC_CRED_V5 = 2, + CC_CRED_VMAX = 3 // For validation +}; + +typedef struct opaque_dll_control_block_type* apiCB; +typedef struct _infoNC { + char* name; + char* principal; + cc_int32 vers; +} infoNC; + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_initialize, + ( + apiCB** cc_ctx, // < DLL's primary control structure. + // returned here, passed everywhere else + cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1) + cc_int32* api_supported, // < if ~NULL, max ver supported by DLL + const char** vendor // < if ~NULL, vendor name in read only C string + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_shutdown, + ( + apiCB** cc_ctx // <> DLL's primary control structure. NULL after + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_get_NC_info, + ( + apiCB* cc_ctx, // > DLL's primary control structure + struct _infoNC*** ppNCi // < (NULL before call) null terminated, + // list of a structs (free via cc_free_infoNC()) + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +CALLCONV_C, +cc_free_NC_info, + ( + apiCB* cc_ctx, + struct _infoNC*** ppNCi // < free list of structs returned by + // cc_get_cache_names(). set to NULL on return + ) +); +//// \CCAPI + +extern DWORD AfsAvailable; + +// service definitions +typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD); +typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD); +typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS); +typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE); + +////////////////////////////////////////////////////////////////////////////// + +// CCAPI +extern DECL_FUNC_PTR(cc_initialize); +extern DECL_FUNC_PTR(cc_shutdown); +extern DECL_FUNC_PTR(cc_get_NC_info); +extern DECL_FUNC_PTR(cc_free_NC_info); + +// krb4 functions +extern DECL_FUNC_PTR(get_krb_err_txt_entry); +extern DECL_FUNC_PTR(k_isinst); +extern DECL_FUNC_PTR(k_isname); +extern DECL_FUNC_PTR(k_isrealm); +extern DECL_FUNC_PTR(kadm_change_your_password); +extern DECL_FUNC_PTR(kname_parse); +extern DECL_FUNC_PTR(krb_get_cred); +extern DECL_FUNC_PTR(krb_get_krbhst); +extern DECL_FUNC_PTR(krb_get_lrealm); +extern DECL_FUNC_PTR(krb_get_pw_in_tkt); +extern DECL_FUNC_PTR(krb_get_tf_realm); +extern DECL_FUNC_PTR(krb_mk_req); +extern DECL_FUNC_PTR(krb_realmofhost); +extern DECL_FUNC_PTR(tf_init); +extern DECL_FUNC_PTR(tf_close); +extern DECL_FUNC_PTR(tf_get_cred); +extern DECL_FUNC_PTR(tf_get_pname); +extern DECL_FUNC_PTR(tf_get_pinst); +extern DECL_FUNC_PTR(LocalHostAddr); +extern DECL_FUNC_PTR(tkt_string); +extern DECL_FUNC_PTR(krb_set_tkt_string); +extern DECL_FUNC_PTR(initialize_krb_error_func); +extern DECL_FUNC_PTR(initialize_kadm_error_table); +extern DECL_FUNC_PTR(dest_tkt); +extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX +extern DECL_FUNC_PTR(krb_in_tkt); +extern DECL_FUNC_PTR(krb_save_credentials); +extern DECL_FUNC_PTR(krb_get_krbconf2); +extern DECL_FUNC_PTR(krb_get_krbrealm2); +extern DECL_FUNC_PTR(krb_life_to_time); + +// krb5 functions +extern DECL_FUNC_PTR(krb5_change_password); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +extern DECL_FUNC_PTR(krb5_get_init_creds_password); +extern DECL_FUNC_PTR(krb5_get_prompt_types); +extern DECL_FUNC_PTR(krb5_build_principal_ext); +extern DECL_FUNC_PTR(krb5_cc_get_name); +extern DECL_FUNC_PTR(krb5_cc_get_type); +extern DECL_FUNC_PTR(krb5_cc_resolve); +extern DECL_FUNC_PTR(krb5_cc_default); +extern DECL_FUNC_PTR(krb5_cc_default_name); +extern DECL_FUNC_PTR(krb5_cc_set_default_name); +extern DECL_FUNC_PTR(krb5_cc_initialize); +extern DECL_FUNC_PTR(krb5_cc_destroy); +extern DECL_FUNC_PTR(krb5_cc_close); +extern DECL_FUNC_PTR(krb5_cc_copy_creds); +extern DECL_FUNC_PTR(krb5_cc_store_cred); +extern DECL_FUNC_PTR(krb5_cc_retrieve_cred); +extern DECL_FUNC_PTR(krb5_cc_get_principal); +extern DECL_FUNC_PTR(krb5_cc_start_seq_get); +extern DECL_FUNC_PTR(krb5_cc_next_cred); +extern DECL_FUNC_PTR(krb5_cc_end_seq_get); +extern DECL_FUNC_PTR(krb5_cc_remove_cred); +extern DECL_FUNC_PTR(krb5_cc_set_flags); +// extern DECL_FUNC_PTR(krb5_cc_get_type); +extern DECL_FUNC_PTR(krb5_free_context); +extern DECL_FUNC_PTR(krb5_free_cred_contents); +extern DECL_FUNC_PTR(krb5_free_principal); +extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +extern DECL_FUNC_PTR(krb5_init_context); +extern DECL_FUNC_PTR(krb5_parse_name); +extern DECL_FUNC_PTR(krb5_timeofday); +extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +extern DECL_FUNC_PTR(krb5_unparse_name); +extern DECL_FUNC_PTR(krb5_get_credentials); +extern DECL_FUNC_PTR(krb5_mk_req); +extern DECL_FUNC_PTR(krb5_sname_to_principal); +extern DECL_FUNC_PTR(krb5_get_credentials_renew); +extern DECL_FUNC_PTR(krb5_free_data); +extern DECL_FUNC_PTR(krb5_free_data_contents); +// extern DECL_FUNC_PTR(krb5_get_realm_domain); +extern DECL_FUNC_PTR(krb5_free_unparsed_name); +extern DECL_FUNC_PTR(krb5_os_localaddr); +extern DECL_FUNC_PTR(krb5_copy_keyblock_contents); +extern DECL_FUNC_PTR(krb5_copy_data); +extern DECL_FUNC_PTR(krb5_free_creds); +extern DECL_FUNC_PTR(krb5_build_principal); +extern DECL_FUNC_PTR(krb5_get_renewed_creds); +extern DECL_FUNC_PTR(krb5_free_addresses); +extern DECL_FUNC_PTR(krb5_get_default_config_files); +extern DECL_FUNC_PTR(krb5_free_config_files); +extern DECL_FUNC_PTR(krb5_get_default_realm); +extern DECL_FUNC_PTR(krb5_set_default_realm); +extern DECL_FUNC_PTR(krb5_free_ticket); +extern DECL_FUNC_PTR(krb5_decode_ticket); +extern DECL_FUNC_PTR(krb5_get_host_realm); +extern DECL_FUNC_PTR(krb5_free_host_realm); +extern DECL_FUNC_PTR(krb5_c_random_make_octets); +extern DECL_FUNC_PTR(krb5_free_default_realm); + +// Krb524 functions +extern DECL_FUNC_PTR(krb524_init_ets); +extern DECL_FUNC_PTR(krb524_convert_creds_kdc); + +// ComErr functions +extern DECL_FUNC_PTR(com_err); +extern DECL_FUNC_PTR(error_message); + +// Profile functions +extern DECL_FUNC_PTR(profile_init); +extern DECL_FUNC_PTR(profile_flush); +extern DECL_FUNC_PTR(profile_release); +extern DECL_FUNC_PTR(profile_get_subsection_names); +extern DECL_FUNC_PTR(profile_free_list); +extern DECL_FUNC_PTR(profile_get_string); +extern DECL_FUNC_PTR(profile_get_values); +extern DECL_FUNC_PTR(profile_get_relation_names); +extern DECL_FUNC_PTR(profile_clear_relation); +extern DECL_FUNC_PTR(profile_add_relation); +extern DECL_FUNC_PTR(profile_update_relation); +extern DECL_FUNC_PTR(profile_release_string); + +// Service functions +extern DECL_FUNC_PTR(OpenSCManagerA); +extern DECL_FUNC_PTR(OpenServiceA); +extern DECL_FUNC_PTR(QueryServiceStatus); +extern DECL_FUNC_PTR(CloseServiceHandle); +extern DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions +extern DECL_FUNC_PTR(LsaConnectUntrusted); +extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +extern DECL_FUNC_PTR(LsaCallAuthenticationPackage); +extern DECL_FUNC_PTR(LsaFreeReturnBuffer); +extern DECL_FUNC_PTR(LsaGetLogonSessionData); + +// toolhelp functions +TYPEDEF_FUNC( + HANDLE, + WINAPI, + CreateToolhelp32Snapshot, + (DWORD, DWORD) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32First, + (HANDLE, LPMODULEENTRY32) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32Next, + (HANDLE, LPMODULEENTRY32) + ); + +// psapi functions +TYPEDEF_FUNC( + DWORD, + WINAPI, + GetModuleFileNameExA, + (HANDLE, HMODULE, LPSTR, DWORD) + ); + +TYPEDEF_FUNC( + BOOL, + WINAPI, + EnumProcessModules, + (HANDLE, HMODULE*, DWORD, LPDWORD) + ); + +#define pGetModuleFileNameEx pGetModuleFileNameExA +#define TOOLHELPDLL "kernel32.dll" +#define PSAPIDLL "psapi.dll" + +// psapi functions +extern DECL_FUNC_PTR(GetModuleFileNameExA); +extern DECL_FUNC_PTR(EnumProcessModules); + +// toolhelp functions +extern DECL_FUNC_PTR(CreateToolhelp32Snapshot); +extern DECL_FUNC_PTR(Module32First); +extern DECL_FUNC_PTR(Module32Next); + +khm_int32 init_imports(void); +khm_int32 exit_imports(void); + +#endif diff --git a/src/WINNT/netidmgr_plugin/help/Index.hhk b/src/WINNT/netidmgr_plugin/help/Index.hhk new file mode 100644 index 0000000..c0ba08a --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/Index.hhk @@ -0,0 +1,9 @@ + + + + + + +
    +
+ diff --git a/src/WINNT/netidmgr_plugin/help/NTMakefile b/src/WINNT/netidmgr_plugin/help/NTMakefile new file mode 100644 index 0000000..8d41e06 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/NTMakefile @@ -0,0 +1,37 @@ +# +# Copyright (c) 2005 Massachusetts Institute of Technology +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +RELDIR=WINNT\netidmgr_plugin +!INCLUDE ..\..\..\config\NTMakefile.$(SYS_NAME) +!INCLUDE ..\..\..\config\NTMakefile.version + +CHMFILE=$(DESTDIR)\root.client\usr\vice\etc\afsplhlp.chm + +install: $(CHMFILE) + +$(CHMFILE): afsplhlp.hhp + -hhc $** + $(COPY) afsplhlp.chm $(CHMFILE) + +clean:: + $(DEL) $(CHMFILE) \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/afsplhlp.h b/src/WINNT/netidmgr_plugin/help/afsplhlp.h new file mode 100644 index 0000000..51738d4 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/afsplhlp.h @@ -0,0 +1,14 @@ +#define IDH_OBTAIN 3000 +#define IDH_CELL 3001 +#define IDH_REALM 3002 +#define IDH_METHOD 3003 +#define IDH_ADD 3004 +#define IDH_DELETE 3005 +#define IDH_TOKENLIST 3006 +#define IDH_SVCSTATUS 3007 +#define IDH_SVCSTOP 3008 +#define IDH_SVCSTART 3009 +#define IDH_SVCVERSION 3010 +#define IDH_SVCCOMPANY 3011 +#define IDH_SVCCPL 3012 +#define IDH_STARTAFSCREDS 3013 diff --git a/src/WINNT/netidmgr_plugin/help/afsplhlp.hhp b/src/WINNT/netidmgr_plugin/help/afsplhlp.hhp new file mode 100644 index 0000000..5bc86f5 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/afsplhlp.hhp @@ -0,0 +1,29 @@ +[OPTIONS] +Auto Index=Yes +Compatibility=1.1 or later +Compiled file=afsplhlp.chm +Contents file=toc.hhc +Default Window=MainHelpWnd +Default topic=html/welcome.htm +Display compile progress=No +Index file=Index.hhk +Language=0x409 English (United States) +Title=OpenAFS Plugin for NetIDMgr + +[WINDOWS] +MainHelpWnd="OpenAFS/NetIDMgr Help","toc.hhc","Index.hhk","html/welcome.htm","html/welcome.htm",,,,,0x42120,,0x384e,[271,372,593,566],0x830000,,,,,,0 + + +[ALIAS] + +[MAP] +#include afsplhlp.h + +[TEXT POPUPS] +afsplhlp.h +popups_newcred.txt +popups_cfg.txt + +[INFOTYPES] +Category:Usage +CategoryDesc:Usage instructions for OpenAFS/NetIDMgr diff --git a/src/WINNT/netidmgr_plugin/help/html/afsplhlp.css b/src/WINNT/netidmgr_plugin/help/html/afsplhlp.css new file mode 100644 index 0000000..f59706c --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/afsplhlp.css @@ -0,0 +1,73 @@ +BODY { + font-family:helvetica,sans-serif; + font-size:8pt; + font-style:normal; + background-color:white; + margin-top: 0; + margin-left: 0; + margin-right: 0; + } + +H1 { + font-size: 10pt; + border-bottom:1px solid black; + padding:5px; + background-color:#eeeeee; + } + +H2 { + } + +H3 { + font-size: 9pt; + border-bottom: 1px solid lightgrey; + padding: 5px; + } + +H4 { + font-size: 9pt; + font-style: italic; + border-bottom: 1px dashed lightgrey; + margin-left: 10px; + } + +P { + margin-left: 5px; + margin-right: 5px; + } + +P.caption { + margin-left: 5px; + margin-right: 5px; + font-style: italic; +} + +DIV.inline { + float: left; +} + +DIV.sidebar { + float: right; + background-color:#ffffb9; + border: 1px solid #ffff00; +} + +A.external { +} + +A.mail { +} + +IMG { + border: 0; +} + +SPAN.pre { + font-family: courier; + font-weight: bold; +} + +SPAN.title { + font-weight: bold; +} + diff --git a/src/WINNT/netidmgr_plugin/help/html/bugs.htm b/src/WINNT/netidmgr_plugin/help/html/bugs.htm new file mode 100644 index 0000000..214215c --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/bugs.htm @@ -0,0 +1,24 @@ + + + Reporting Bugs and Requesting Features + + + + + + +

Reporting Bugs and Requesting Features

+ +

If you experience a bug in the program, please send email to bugs@secure-endpoints.com and report it. Please +include as much information as possible to enable us to reproduce the +problem. +

+ +

If there is a feature you would like to see in a future release, +please send email to the same address given above. +

+ + + \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/html/config_service.htm b/src/WINNT/netidmgr_plugin/help/html/config_service.htm new file mode 100644 index 0000000..93687d4 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/config_service.htm @@ -0,0 +1,39 @@ + + + Configuring the AFS Service + + + + + + +

Configuring the AFS Service

+ +

The OpenAFS plug-in allows you to start or stop the AFS +client service, determine the installed version, and invoke the AFS +Control Panel. This is provided via the AFS configuration panel in +the NetIDMgr configuration dialog, as seen below: +

+ +

+ +

Depending on the status of the service, either the Stop service or the Start +service buttons will be enabled. If the service is in a state +where it will not accept these control requests, then both buttons will +be disabled. +

+ +

The Version field and the Company fields are populated based on the resources +found in the afsd_service.exe binary. This +is the main binary that provides the AFS client service. Unless the +build of OpenAFS that you have installed is a private build, the +version should correspond to the release of OpenAFS that is installed +on your machine.

+ +

Clicking the Open AFS Control Panel... +will open the AFS configuration utility.

+ + + \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/html/copyright.htm b/src/WINNT/netidmgr_plugin/help/html/copyright.htm new file mode 100644 index 0000000..2d63278 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/copyright.htm @@ -0,0 +1,42 @@ + + + License + + + + + + +

OpenAFS Plug-in for Network Identification Manager License

+ +

This software is being provided to you, the LICENSEE, by Secure +Endpoints Inc. under the following license. By obtaining, using and/or +copying this software, you agree that you have read, understood, and +will comply with these terms and conditions:

+ +

Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee or royalty is hereby +granted, provided that you agree to comply with the following +copyright notice and statements, including the disclaimer, and that +the same appear on ALL copies of the software and documentation, +including modifications that you make for internal use or for +distribution:

+ +

Copyright 2005 by Secure Endpoints Inc.. All rights reserved.

+ +

THIS SOFTWARE IS PROVIDED "AS IS", AND SECURE ENDPOINTS INC. MAKES +NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. By way of +example, but not limitation, SECURE ENDPOINTS INC. MAKES NO +REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY +PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE OR +DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, +TRADEMARKS OR OTHER RIGHTS.

+ +

The name of Secure Endpoints Inc. may NOT be used in advertising or +publicity pertaining to distribution of the software. Title to +copyright in this software and any associated documentation shall at +all times remain with Secure Endpoints Inc., and USER agrees to +preserve same.

+ + + diff --git a/src/WINNT/netidmgr_plugin/help/html/images/openafs-logo.jpg b/src/WINNT/netidmgr_plugin/help/html/images/openafs-logo.jpg new file mode 100644 index 0000000..cbddc47 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/openafs-logo.jpg differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_cfg_afs_0.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_cfg_afs_0.bmp new file mode 100644 index 0000000..2856ffa Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_cfg_afs_0.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_cfg_afs_main.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_cfg_afs_main.bmp new file mode 100644 index 0000000..69101c5 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_cfg_afs_main.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_0.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_0.bmp new file mode 100644 index 0000000..67e843f Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_0.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_1.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_1.bmp new file mode 100644 index 0000000..0d388ca Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_1.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_2.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_2.bmp new file mode 100644 index 0000000..ce0f628 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_afs_2.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_nc_main.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_main.bmp new file mode 100644 index 0000000..b3b0263 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_main.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/images/window_nc_prob.bmp b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_prob.bmp new file mode 100644 index 0000000..51c16d6 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/help/html/images/window_nc_prob.bmp differ diff --git a/src/WINNT/netidmgr_plugin/help/html/template.htm b/src/WINNT/netidmgr_plugin/help/html/template.htm new file mode 100644 index 0000000..cbdf541 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/template.htm @@ -0,0 +1,11 @@ + + + title + + + + + + + + \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/html/token_methods.htm b/src/WINNT/netidmgr_plugin/help/html/token_methods.htm new file mode 100644 index 0000000..7d163d6 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/token_methods.htm @@ -0,0 +1,70 @@ + + + Token Acquisition Methods + + + + + + +

Token Acquisition Methods

+ +

AFS tokens can be obtained via several different methods. Each of +the methods that are natively supported by the OpenAFS plug-in is +described below. Note that, additional plug-ins may define other +acquisition methods that are not listed here. +

+ +

Contents

+ + + + +

Kerberos 5

+ +

A Kerberos 5 service ticket is obtained for the cell and used directly to +construct the AFS token. +

+ +
+

Kerberos 5 to 4 conversion (Kerberos 524)

+ +

A Kerberos 5 service ticket is obtained for the cell and then +converted to a Kerberos 4 service ticket using the krb524 daemon. The +resulting Kerberos 4 ticket is used to construct the AFS token. +

+ +
+

Kerberos 4

+ +

A Kerberos 4 service ticket is obtained for the cell and then used +to construct the AFS token. In order to use this method, the identity +must be be configured to obtain Kerberos 4 tickets when obtaining and +renewing credentials. Otherwise a Kerberos 4 TGT (ticket granting +ticket) will not be available to obtain the service ticket with. +

+ +
+

Automatic method selection

+ +

When the OpenAFS plug-in is configured to use automatic method +selection for obtaining an AFS token, it iterates through the Kerberos +5, Kerberos 524 and Kerberos 4 methods until one of them succeeds. If +a realm for the service ticket is specified, then the realm will be +used for all methods. +

+ +

The correct method to use for your AFS cell will depend on the +configuration of the AFS cell and the associated Kerberos realm. In +most cases, automatic method selection will determine the correct +realm. However, other cases, the method will have to be specified +explicitly. +

+ + + \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/html/tokens_per_id.htm b/src/WINNT/netidmgr_plugin/help/html/tokens_per_id.htm new file mode 100644 index 0000000..ec14f2f --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/tokens_per_id.htm @@ -0,0 +1,189 @@ + + + Configuring identifications to obtain tokens for AFS cells + + + + + + +

Configuring identifications to obtain tokens for AFS cells

+ +

+The OpenAFS plug-in maintains a list of AFS cells for each identification. +A list is created the first time AFS tokens are obtained for an +identification or when the list of cells is +specified in the identification configuration panels. Each AFS cell that +is listed is associated with a method by which a token should +be obtained and the name of the Kerberos realm that is used to +obtain the service ticket (more details are provided in the Token Aquisition Methods topic). +

+ +

The following sections detail the process by which AFS cells can be +specified when obtaining new credentials or configuring identifications. +

+ + +

Specifying AFS cells when obtaining new credentials

+ +

+When the OpenAFS plug-in is installed, it enhances the NetIDMgr new credentials +dialog with an AFS tokens options panel. A typical new +credentials dialog is shown below demonstrating AFS cells listed in the +credentials summary window. +

+ +

New credentials window showing AFS cells in the credentials summary window

+ +

Clicking on the AFS link in the +credentials summary window will take you to the AFS options page. +Alternatively, you can select the Options +>> button which expands the dialog to show the +credentials type buttons, and then click the AFS button at the bottom of the expanded dialog. +

+ +

The AFS identification options page is shown below

+ +

AFS identification options page

+ +

This page allows you to specify if AFS tokens are obtained for this +identification and if so, for which tokens and by which method will they be +obtained. By unchecking the Obtain AFS +tokens checkbox, you can prevent AFS tokens from being obtained +for this idenfication. +

+ +

Once the new credentials dialog successfully completes, the list of +cells will be saved with the identification. The next +time you obtain new credentials for the identification, the list of cells +will be loaded automatically. This list can be edited either by using +the new credentials dialog or the identity configuration +panels. (See Changing persistent tokent lists). +

+ +

To add a cell:

+

+

    + +
  • Specify the name of the cell in the Cell +text box.
  • + +
  • Specify the Kerberos realm for the service ticket in the Realm text box. Note that you can select (Automatic) as the realm to allow the OpenAFS +plug-in to select the realm. For most cases, you don't need to specify +the realm manually and can safely leave the Realm as (Automatic)
  • + +
  • Specify the token acquisition method in the Method. You can select (Automatic) as the method to allow the OpenAFS +plug-in to select the method automatically. Similar to the automatic +realm selection, for most cases the plug-in will be able to correctly +select the token aquisition method. More details about credentials +acquisition methods are provided in the Token Acquisition Methods topic.
  • + +
  • Select the Add/Update button to add the +cell.
  • + +
+

+ +

Note that only one token can exist per cell per login session. +Which means that if you already have a token for cell X while +you are logged in as user A, then you can't have another +token for cell X. This means that only one identification can +obtain a token for a given cell.

+ +

Therefore, if you try to add a cell to an identification which is +already listed in the persistent cell list for another identification or +which currently exists under a different identification, you will receive a +warning such as the following: +

+ +

+Message displaying warning about a duplicate cell +

+ +

From here, you can decide to keep the cell listed for both +identifications (although only one of them can be active at any given +time), or remove the cell from all the other identifications and add it to +the current one. Also, you can cancel the add cell request. +

+ +

To modify a cell

+

+

    + +
  • Select the cell from the list of cells. The cell name, realm and +method in the text boxes will be updated to display the information +from the cell just selected.
  • + +
  • Make changes to the realm and method fields as appropriate
  • + +
  • Select Add / Update to update the +information in the cell list
  • + +
+

+ +

Note that if you don't click the Add / +Update, the cell entry will not be updated. +

+ +

To delete cells

+ +

+

    + +
  • Select the cells you want to delete from the cell list. You can +select multiple cells by clicking while holding the Ctrl key.
  • + +
  • Select the Delete button.
  • + +
+

+ +

Cell states

+ +

When you add cells or when you view the cell list, you will see +an icon next to each cell name. This icon represents the current state of +the cell's token. You can double-click on the cell to get details about the +state. +

+ +

+ +

+

+Token for cell foo.bar is a new token while +the token for net.mit.edu is in a problem +state. Double clicking the problem token will display a balloon +prompt indicating what the problem is. +

+ + +

Changing persistent cell lists for existing identifications

+ +

+The configuration panel for a persistent identification contains a panel for +specifying the AFS cells. This panel is identical to the panel used +by the new credentials dialog. You can easily modify the cell lists +as described above and click Apply and you +are done. +

+ +

The AFS configuration panel for an identification is shown below.

+ +

+ +

You can reach this configuration panel by opening the configuration +dialog (Options menu), and then clicking the +persistent identification you need to modify options for.

+ + + \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/html/welcome.htm b/src/WINNT/netidmgr_plugin/help/html/welcome.htm new file mode 100644 index 0000000..592b13a --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/html/welcome.htm @@ -0,0 +1,61 @@ + + + Welcome to the OpenAFS plug-in for NetIDMgr + + + + + +

Welcome to the OpenAFS plug-in for NetIDMgr

+ + + +

+The OpenAFS plug-in extends the Network Identity Manager (or +NetIDMgr for short) to support AFS credential management. This plug-in +obtains AFS tokens for the cells associated with each identification +and provides the tools necessary to maintain them. +

+ +

+This version of the plug-in is provided by Secure Endpoints Inc. +Visit http://www.secure-endpoints.com +for updates. +

+ + + +

Using the OpenAFS plug-in

+ + + + +

External links

+ + + + \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/help/popups_cfg.txt b/src/WINNT/netidmgr_plugin/help/popups_cfg.txt new file mode 100644 index 0000000..4dc07f6 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/popups_cfg.txt @@ -0,0 +1,30 @@ +.topic IDH_SVCSTATUS +Current status of the OpenAFS Client Service. + +.topic IDH_SVCSTOP +Stops the OpenAFS Client service. Access to resources in AFS will not +be available until the service is started again. All exising AFS +tokens will also be lost. + +.topic IDH_SVCSTART +Start the service. Once the service starts, it will not have any AFS +tokens for any of the users. Therefore new tokens will be +automatically be obtained once the service starts. + +.topic IDH_SVCVERSION +Version of the OpenAFS Client that is installed on this machine. The +version is derived from the executable that provides the OpenAFS +Client service on this machine. + +.topic IDH_SVCCOMPANY +The company that provided the OpenAFS client. + +.topic IDH_SVCCPL +Open the OpenAFS Client Configuration utility. + +.topic IDH_STARTAFSCREDS +Once the OpenAFS plugin for NetIDMgr is installed, it is no longer +necessary to start AFSCreds.exe everytime a user logs in. The allows +you to disable AFSCreds.exe. Note that this is a per machine setting +and requires Administrator privileges on the machine to have an +effect. diff --git a/src/WINNT/netidmgr_plugin/help/popups_newcred.txt b/src/WINNT/netidmgr_plugin/help/popups_newcred.txt new file mode 100644 index 0000000..09e4db3 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/popups_newcred.txt @@ -0,0 +1,31 @@ +.topic IDH_OBTAIN +If checked, obtains AFS tokens for this identity as specified below. +Otherwise, doesn't obtain AFS tokens at all. + +.topic IDH_CELL +The name of the cell for which this token will be obtained for. + +.topic IDH_REALM +The Kerberos realm used to obtain the service ticket for the cell. +Select 'Automatic' to let the AFS plug-in determine the realm +automatically. + +.topic IDH_METHOD +The method used to construct the AFS token. Select 'Automatic' to let +the AFS plugin determine the method automatically. + +.topic IDH_ADD +Add or update the token in the token list. If the token already +exists in the list, then the information will be updated. Otherwise +it will be added. + +.topic IDH_DELETE +Delete the selected tokens from the token list. Tokens that are +currently selected in the tokens list will be deleted. If no tokens +are selected in the list, then the token corresponding to the cell +listed in the 'Cell' input box will be deleted. + +.topic IDH_TOKENLIST +The list of tokens that will be obtained for this identity. +Double-click on any of the tokens here to get details about the state +of each token. diff --git a/src/WINNT/netidmgr_plugin/help/toc.hhc b/src/WINNT/netidmgr_plugin/help/toc.hhc new file mode 100644 index 0000000..3e153fa --- /dev/null +++ b/src/WINNT/netidmgr_plugin/help/toc.hhc @@ -0,0 +1,56 @@ + + + + + + + + + + + +
    +
  • + + + +
      +
    • + + + +
    • + + + +
    +
  • + + +
      +
    • + + + + +
    • + + + + +
    • + + + +
    +
  • + + +
      +
    • + + + +
    +
+ diff --git a/src/WINNT/netidmgr_plugin/images/OpenAFS.ico b/src/WINNT/netidmgr_plugin/images/OpenAFS.ico new file mode 100644 index 0000000..f8fe9ca Binary files /dev/null and b/src/WINNT/netidmgr_plugin/images/OpenAFS.ico differ diff --git a/src/WINNT/netidmgr_plugin/images/afstoken.ico b/src/WINNT/netidmgr_plugin/images/afstoken.ico new file mode 100644 index 0000000..61534df Binary files /dev/null and b/src/WINNT/netidmgr_plugin/images/afstoken.ico differ diff --git a/src/WINNT/netidmgr_plugin/images/nc_exist.ico b/src/WINNT/netidmgr_plugin/images/nc_exist.ico new file mode 100644 index 0000000..1491e3d Binary files /dev/null and b/src/WINNT/netidmgr_plugin/images/nc_exist.ico differ diff --git a/src/WINNT/netidmgr_plugin/images/nc_new.ico b/src/WINNT/netidmgr_plugin/images/nc_new.ico new file mode 100644 index 0000000..cb6c750 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/images/nc_new.ico differ diff --git a/src/WINNT/netidmgr_plugin/images/nc_notowned.ico b/src/WINNT/netidmgr_plugin/images/nc_notowned.ico new file mode 100644 index 0000000..84bf9b6 Binary files /dev/null and b/src/WINNT/netidmgr_plugin/images/nc_notowned.ico differ diff --git a/src/WINNT/netidmgr_plugin/krb5common.c b/src/WINNT/netidmgr_plugin/krb5common.c new file mode 100644 index 0000000..5475036 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/krb5common.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif +#include + +/**************************************/ +/* khm_krb5_error(): */ +/**************************************/ +int +khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, + int FreeContextFlag, krb5_context * ctx, + krb5_ccache * cache) +{ +#ifdef NO_KRB5 + return 0; +#else + +#ifdef SHOW_MESSAGE_IN_AN_ANNOYING_WAY + char message[256]; + const char *errText; + int krb5Error = ((int)(rc & 255)); + + errText = perror_message(rc); + _snprintf(message, sizeof(message), + "%s\n(Kerberos error %ld)\n\n%s failed", + errText, + krb5Error, + FailedFunctionName); + + MessageBoxA(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR | + MB_TASKMODAL | + MB_SETFOREGROUND); +#endif + + if (FreeContextFlag == 1) + { + if (*ctx != NULL) + { + if (*cache != NULL) { + pkrb5_cc_close(*ctx, *cache); + *cache = NULL; + } + + pkrb5_free_context(*ctx); + *ctx = NULL; + } + } + + return rc; + +#endif //!NO_KRB5 +} + +int +khm_krb5_initialize(khm_handle ident, + krb5_context *ctx, + krb5_ccache *cache) +{ +#ifdef NO_KRB5 + return(0); +#else + + LPCSTR functionName; + int freeContextFlag; + krb5_error_code rc = 0; + krb5_flags flags = 0; + + if (pkrb5_init_context == NULL) + return 1; + + if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx))) { + functionName = "krb5_init_context()"; + freeContextFlag = 0; + goto on_error; + } + + if(*cache == 0) { + wchar_t wccname[MAX_PATH]; + khm_size cbwccname; + + if(ident != NULL) { + cbwccname = sizeof(wccname); + do { + char ccname[256]; + + if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName", + NULL, wccname, + &cbwccname))) { + cbwccname = sizeof(wccname); + if (KHM_FAILED + (khm_krb5_find_ccache_for_identity(ident, + ctx, + wccname, + &cbwccname))) { +#ifdef DEBUG_LIKE_A_MADMAN + assert(FALSE); +#endif + break; + } + } + + if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0) + break; + + if((*pkrb5_cc_resolve)(*ctx, ccname, cache)) { + functionName = "krb5_cc_resolve()"; + freeContextFlag = 1; + goto on_error; + } + } while(FALSE); + } + +#ifndef FAILOVER_TO_DEFAULT_CCACHE + rc = 1; +#endif + if (*cache == 0 +#ifdef FAILOVER_TO_DEFAULT_CCACHE + && (rc = (*pkrb5_cc_default)(*ctx, cache)) +#endif + ) { + functionName = "krb5_cc_default()"; + freeContextFlag = 1; + goto on_error; + } + } + +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; +#endif + + if ((rc = (*pkrb5_cc_set_flags)(*ctx, *cache, flags))) + { + if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND) + khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx, + cache); + else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) { + if (*cache != NULL) + (*pkrb5_cc_close)(*ctx, *cache); + } + return rc; + } + return 0; + +on_error: + return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache); +#endif //!NO_KRB5 +} + +#define TIMET_TOLERANCE (60*5) + +khm_int32 KHMAPI +khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, + khm_handle ident, + krb5_timestamp * pexpiration) +{ + krb5_principal principal = 0; + char * princ_name = NULL; + krb5_creds creds; + krb5_error_code code; + krb5_error_code cc_code; + krb5_cc_cursor cur; + krb5_timestamp now, expiration = 0; + + wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME]; + char ident_name[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + khm_int32 rv = KHM_ERROR_NOT_FOUND; + + if (!ctx || !cc || !ident || !pexpiration) + return KHM_ERROR_GENERAL; + + code = pkrb5_cc_get_principal(ctx, cc, &principal); + + if ( code ) + return KHM_ERROR_INVALID_PARAM; + + cb = sizeof(w_ident_name); + kcdb_identity_get_name(ident, w_ident_name, &cb); + UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name); + + code = pkrb5_unparse_name(ctx, principal, &princ_name); + + /* compare principal to ident. */ + + if ( code || !princ_name || + strcmp(princ_name, ident_name) ) { + if (princ_name) + pkrb5_free_unparsed_name(ctx, princ_name); + pkrb5_free_principal(ctx, principal); + return KHM_ERROR_UNKNOWN; + } + + pkrb5_free_unparsed_name(ctx, princ_name); + pkrb5_free_principal(ctx, principal); + + code = pkrb5_timeofday(ctx, &now); + + if (code) + return KHM_ERROR_UNKNOWN; + + cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur); + + while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) { + krb5_data * c0 = krb5_princ_name(ctx, creds.server); + krb5_data * c1 = krb5_princ_component(ctx, creds.server, 1); + krb5_data * r = krb5_princ_realm(ctx, creds.server); + + if ( c0 && c1 && r && c1->length == r->length && + !strncmp(c1->data,r->data,r->length) && + !strncmp("krbtgt",c0->data,c0->length) ) { + + /* we have a TGT, check for the expiration time. + * if it is valid and renewable, use the renew time + */ + + if (!(creds.ticket_flags & TKT_FLG_INVALID) && + creds.times.starttime < (now + TIMET_TOLERANCE) && + (creds.times.endtime + TIMET_TOLERANCE) > now) { + expiration = creds.times.endtime; + + if ((creds.ticket_flags & TKT_FLG_RENEWABLE) && + (creds.times.renew_till > creds.times.endtime)) { + expiration = creds.times.renew_till; + } + } + } + } + + if (cc_code == KRB5_CC_END) { + cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur); + rv = KHM_ERROR_SUCCESS; + *pexpiration = expiration; + } + + return rv; +} + +khm_int32 KHMAPI +khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, + void * buffer, khm_size * pcbbuf) +{ + krb5_context ctx = 0; + krb5_ccache cache = 0; + krb5_error_code code; + apiCB * cc_ctx = 0; + struct _infoNC ** pNCi = NULL; + int i; + khm_int32 t; + wchar_t * ms = NULL; + khm_size cb; + krb5_timestamp expiration = 0; + krb5_timestamp best_match_expiration = 0; + char best_match_ccname[256] = ""; + khm_handle csp_params = NULL; + khm_handle csp_plugins = NULL; + + if (!buffer || !pcbbuf) + return KHM_ERROR_GENERAL; + + ctx = *pctx; + + if (!pcc_initialize || + !pcc_get_NC_info || + !pcc_free_NC_info || + !pcc_shutdown) + goto _skip_cc_iter; + + code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL); + if (code) + goto _exit; + + code = pcc_get_NC_info(cc_ctx, &pNCi); + + if (code) + goto _exit; + + for(i=0; pNCi[i]; i++) { + if (pNCi[i]->vers != CC_CRED_V5) + continue; + + code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache); + if (code) + continue; + + /* need a function to check the cache for the identity + * and determine if it has valid tickets. If it has + * the right identity and valid tickets, store the + * expiration time and the cache name. If it has the + * right identity but no valid tickets, store the ccache + * name and an expiration time of zero. if it does not + * have the right identity don't save the name. + * + * Keep searching to find the best cache available. + */ + + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, + sizeof(best_match_ccname), + "API:"); + StringCbCatA(best_match_ccname, + sizeof(best_match_ccname), + pNCi[i]->name); + expiration = 0; + } + } + + if(ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + _skip_cc_iter: + + if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) { + khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params); + khc_close_space(csp_plugins); + csp_plugins = NULL; + } + +#ifdef DEBUG + if (csp_params == NULL) { + assert(FALSE); + } +#endif + + if (csp_params && + KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) { + code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache); + if (code == 0 && cache) { + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, sizeof(best_match_ccname), + "MSLSA:"); + expiration = 0; + } + } + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + + cache = 0; + } + + if (csp_params && + khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + == KHM_ERROR_TOO_LONG && + cb > sizeof(wchar_t) * 2) { + + wchar_t * t; + char ccname[MAX_PATH + 6]; + + ms = PMALLOC(cb); + +#ifdef DEBUG + assert(ms); +#endif + + khc_read_multi_string(csp_params, L"FileCCList", ms, &cb); + for(t = ms; t && *t; t = multi_string_next(t)) { + StringCchPrintfA(ccname, ARRAYLENGTH(ccname), + "FILE:%S", t); + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + if (code) + continue; + + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, + sizeof(best_match_ccname), + ccname); + expiration = 0; + } + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + PFREE(ms); + } + _exit: + if (csp_params) + khc_close_space(csp_params); + + if (pNCi) + (*pcc_free_NC_info)(cc_ctx, &pNCi); + + if (cc_ctx) + (*pcc_shutdown)(&cc_ctx); + + if (best_match_ccname[0]) { + + if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer, + *pcbbuf, + best_match_ccname)) { + + *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t); + + return KHM_ERROR_SUCCESS; + } + + } + + return KHM_ERROR_GENERAL; +} diff --git a/src/WINNT/netidmgr_plugin/krb5common.h b/src/WINNT/netidmgr_plugin/krb5common.h new file mode 100644 index 0000000..29cae71 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/krb5common.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Adapted from multiple Leash header files */ + +#ifndef __KHIMAIRA_KRB5COMMON_H +#define __KHIMAIRA_KRB5COMMON_H + +#include + +#ifndef NO_KRB5 +int khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, + int FreeContextFlag, krb5_context *ctx, + krb5_ccache *cache); + +int +khm_krb5_get_error_string(krb5_error_code rc, + wchar_t * buffer, + khm_size cb_buffer); + +int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *); + +khm_int32 KHMAPI +khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, + void * buffer, khm_size * pcbbuf); + +khm_int32 KHMAPI +khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, + khm_handle ident, + krb5_timestamp * pexpiration); +#endif /* NO_KRB5 */ + +#endif diff --git a/src/WINNT/netidmgr_plugin/lang/en_us/langres.rc b/src/WINNT/netidmgr_plugin/lang/en_us/langres.rc new file mode 100644 index 0000000..fb185b6 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/lang/en_us/langres.rc @@ -0,0 +1,273 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\langres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\..\\langres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NC_AFS DIALOGEX 0, 0, 300, 166 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "AFS Token Options",IDC_STATIC,7,7,286,11,SS_SUNKEN | NOT WS_GROUP + CONTROL "Obtain &AFS tokens",IDC_NCAFS_OBTAIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,19,74,12 + GROUPBOX "Token for",IDC_STATIC,7,32,286,54 + LTEXT "&Cell",IDC_STATIC,12,41,42,10 + COMBOBOX IDC_NCAFS_CELL,57,38,152,12,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "&Realm",IDC_STATIC,12,57,42,10 + COMBOBOX IDC_NCAFS_REALM,57,54,152,12,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "&Method",IDC_STATIC,12,73,42,10 + COMBOBOX IDC_NCAFS_METHOD,57,70,152,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Add/Update",IDC_NCAFS_ADD_TOKEN,213,38,77,13,BS_NOTIFY + PUSHBUTTON "&Delete",IDC_NCAFS_DELETE_TOKEN,213,70,77,13,BS_NOTIFY + CONTROL "",IDC_NCAFS_TOKENLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,88,286,71 +END + +IDD_CFG_IDS_TAB DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Obtain AFS tokens for new identities",IDC_CFG_OBTAIN, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,133,10 +END + +IDD_CFG_ID_TAB DIALOGEX 0, 0, 235, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Obtain &AFS tokens",IDC_NCAFS_OBTAIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,74,12 + GROUPBOX "Token for",IDC_STATIC,7,18,221,56 + LTEXT "&Cell",IDC_STATIC,13,28,42,10 + COMBOBOX IDC_NCAFS_CELL,57,25,109,12,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "&Realm",IDC_STATIC,13,44,42,10 + COMBOBOX IDC_NCAFS_REALM,57,41,109,12,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "&Method",IDC_STATIC,13,60,42,10 + COMBOBOX IDC_NCAFS_METHOD,57,57,109,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Add/Update",IDC_NCAFS_ADD_TOKEN,174,26,50,13,BS_NOTIFY + PUSHBUTTON "&Delete",IDC_NCAFS_DELETE_TOKEN,174,56,50,13,BS_NOTIFY + CONTROL "",IDC_NCAFS_TOKENLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,75,221,69 +END + +IDD_CFG_AFS DIALOGEX 0, 0, 255, 182 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "AFS Service",IDC_CFG_SVCGRP,7,7,241,86 + LTEXT "Service status",IDC_CFG_LBL_STATUS,14,18,46,8 + EDITTEXT IDC_CFG_STATUS,68,16,172,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Stop service",IDC_CFG_STOP,68,34,50,14 + PUSHBUTTON "Start service",IDC_CFG_START,127,34,50,14 + CONTROL "",IDC_CFG_PROGRESS,"msctls_progress32",NOT WS_VISIBLE | WS_BORDER,184,38,56,8 + LTEXT "Version",IDC_CFG_LBL_VERSION,14,57,24,8 + EDITTEXT IDC_CFG_VERSION,68,54,172,14,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Company",IDC_CFG_LBL_COMPANY,14,75,31,8 + EDITTEXT IDC_CFG_COMPANY,68,72,172,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Open AFS Control Panel ...",IDC_CFG_CPL,128,161,112,14 + GROUPBOX "Startup options",IDC_CFG_STARTGRP,7,99,241,48 + CONTROL "Prevent AFSCreds.exe from starting automatically everytime you log in to Windows.",IDC_CFG_STARTAFSCREDS, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,14,108,226,22 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NC_AFS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 293 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_CFG_IDS_TAB, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_CFG_ID_TAB, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_CFG_AFS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + VERTGUIDE, 14 + VERTGUIDE, 68 + VERTGUIDE, 240 + TOPMARGIN, 7 + BOTTOMMARGIN, 175 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_AFSTOKEN ICON "..\\..\\images\\afstoken.ico" +IDI_AFSPLUGIN ICON "..\\..\\images\\OpenAFS.ico" +IDI_NC_NEW ICON "..\\..\\images\\nc_new.ico" +IDI_NC_EXIST ICON "..\\..\\images\\nc_exist.ico" +IDI_NC_NOTOWNED ICON "..\\..\\images\\nc_notowned.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_AFS_SHORT_DESC "AFS tokens" + IDS_AFS_LONG_DESC "AFS tokens" + IDS_AFS_NAME "AFS" + IDS_NCAFS_COL_CELL "Cell" + IDS_NCAFS_COL_REALM "Realm" + IDS_NCAFS_COL_METHOD "Method" + IDS_NC_METHOD_AUTO "(Automatic)" + IDS_NC_METHOD_KRB5 "Kerberos 5" + IDS_NC_METHOD_KRB4 "Kerberos 4" + IDS_NC_METHOD_KRB524 "Krb524" + IDS_NC_REALM_AUTO "(Automatic)" +END + +STRINGTABLE +BEGIN + IDS_NC_TT_NO_CELL "You have not specified an AFS cell to authenticate to." + IDS_NC_TT_CANT_ADD "Can't add a new token" + IDS_NC_TT_MALFORMED_CELL + "The cell name you specified contains invalid characters." + IDS_NC_TT_NO_REALM "You have not specified a Kerberos realm to use to obtain tokesn for the cell." + IDS_NC_AUTO "(Auto)" + IDS_NC_TT_MALFORMED_REALM + "The realm name you entered contains invalid characters." + IDS_NC_TT_CANT_UPDATE "Can't update token" + IDS_AFS_CREDTEXT_DIS "

AFS: AFS is disabled. (click here to enable)

" + IDS_AFS_CREDTEXT_0 "

AFS: No tokens selected

" + IDS_AFS_CREDTEXT_1 "

AFS: Token for cell %s

" + IDS_AFS_CREDTEXT_N "

AFS: Tokens for cells %s

" + IDS_ATTR_CELL_SHORT_DESC "Cell" + IDS_ATTR_REALM_SHORT_DESC "Realm" + IDS_ATTR_METHOD_SHORT_DESC "Method" + IDS_ATTR_CLIENT_SHORT_DESC "Client Principal" + IDS_ATTR_CLIENT_PRINC_SHORT_DESC "Client Principal" +END + +STRINGTABLE +BEGIN + IDS_ATTR_SERVER_PRINC_SHORT_DESC "Server Principal" + IDS_DEF_LOCATION "AFS Cache Manager" + IDS_PLUGIN_DESC "AFS Credentials Provider" + IDS_CFG_IDS_TAB "AFS" + IDS_CFG_ID_TAB "AFS" + IDS_CFG_MAIN_LONG "AFS Configuration" + IDS_CFG_MAIN_SHORT "AFS" + IDS_CFG_SVCSTATUS "Status is unknown,Stopped,Starting ...,Stopping ...,Running,Continuing ...,Pausing ...,Paused,Status is unknown" + IDS_NC_METHODL_AUTO "(Automatically determine method)" + IDS_NC_METHODL_KRB5 "Kerberos 5" + IDS_NC_METHODL_KRB4 "Kerberos 4" + IDS_NC_METHODL_KRB524 "Krb524" + IDS_NC_METHOD_INVALID "(Invalid method identifier)" + IDS_NC_TT_CONFLICT "Tokens for cell %s are already listed for identity %s.\nDo you want to keep the token for this cell for other identities?" + IDS_NC_TT_PROBLEM "Problem with new token" + IDS_NC_TT_CONFLICTM "Tokens for cell %s are already listed for identity %s.\nDo you want to keep the token for other identities as well as this one?" +END + +STRINGTABLE +BEGIN + IDS_NC_TT_DETAILS "Details about token" + IDS_NC_TT_CONFLICTD "This token already exists under a different identity." + IDS_NC_TT_EXPIRED "Currently existing token has expired." + IDS_NC_TT_EXISTS "This token already exists for this identity." + IDS_NC_TT_NEW "This is a new token for this identity." + IDS_CFG_CANTSTART "The AFS service could not be started.\n\n" + IDS_CFG_CANTSTOP "The AFS service could not be stopped.\n\n" + IDS_ERR_CELLCONFIG "Could not locate configuration information for cell %1!S!." + IDS_ERR_NOSERVICE "The AFS service is not running. If OpenAFS is installed, you can start the service using the AFS configuration panel." + IDS_ERR_CELLCONFIG_S "The error code returned was %2!d!." + IDS_ERR_GENERAL "Tokens could not be obtained for cell %1!S!." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/WINNT/netidmgr_plugin/lang/en_us/license.rtf b/src/WINNT/netidmgr_plugin/lang/en_us/license.rtf new file mode 100644 index 0000000..9202b4f Binary files /dev/null and b/src/WINNT/netidmgr_plugin/lang/en_us/license.rtf differ diff --git a/src/WINNT/netidmgr_plugin/lang/en_us/resource.h b/src/WINNT/netidmgr_plugin/lang/en_us/resource.h new file mode 100644 index 0000000..b714539 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/lang/en_us/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by langres.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/WINNT/netidmgr_plugin/langres.h b/src/WINNT/netidmgr_plugin/langres.h new file mode 100644 index 0000000..f651825 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/langres.h @@ -0,0 +1,101 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\afs\lang\en_us\langres.rc +// +#define IDS_AFS_SHORT_DESC 101 +#define IDS_AFS_LONG_DESC 102 +#define IDI_ICON1 102 +#define IDD_NC_AFS 103 +#define IDS_AFS_NAME 103 +#define IDS_NCAFS_COL_CELL 104 +#define IDD_CFG_IDS_TAB 104 +#define IDS_NCAFS_COL_REALM 105 +#define IDD_CFG_ID_TAB 105 +#define IDS_NCAFS_COL_METHOD 106 +#define IDD_CFG_AFS 106 +#define IDS_NC_METHOD_AUTO 107 +#define IDI_AFSTOKEN 107 +#define IDS_NC_METHOD_KRB5 108 +#define IDI_AFSPLUGIN 108 +#define IDS_NC_METHOD_KRB4 109 +#define IDI_NC_NEW 109 +#define IDS_NC_METHOD_KRB524 110 +#define IDI_NC_EXIST 110 +#define IDS_NC_REALM_AUTO 111 +#define IDI_NC_NOTOWNED 111 +#define IDS_NC_TT_NO_CELL 112 +#define IDS_NC_TT_CANT_ADD 113 +#define IDS_NC_TT_MALFORMED_CELL 114 +#define IDS_NC_TT_NO_REALM 115 +#define IDS_NC_AUTO 116 +#define IDS_NC_TT_MALFORMED_REALM 117 +#define IDS_NC_TT_CANT_UPDATE 118 +#define IDS_AFS_CREDTEXT_DIS 119 +#define IDS_AFS_CREDTEXT_0 120 +#define IDS_AFS_CREDTEXT_1 121 +#define IDS_AFS_CREDTEXT_N 122 +#define IDS_ATTR_CELL_SHORT_DESC 123 +#define IDS_ATTR_REALM_SHORT_DESC 124 +#define IDS_ATTR_METHOD_SHORT_DESC 125 +#define IDS_ATTR_CLIENT_SHORT_DESC 126 +#define IDS_ATTR_CLIENT_PRINC_SHORT_DESC 127 +#define IDS_ATTR_SERVER_PRINC_SHORT_DESC 128 +#define IDS_DEF_LOCATION 129 +#define IDS_PLUGIN_DESC 130 +#define IDS_CFG_IDS_TAB 131 +#define IDS_CFG_ID_TAB 132 +#define IDS_CFG_MAIN_LONG 133 +#define IDS_CFG_MAIN_SHORT 134 +#define IDS_CFG_SVCSTATUS 135 +#define IDS_NC_METHODL_AUTO 136 +#define IDS_NC_METHODL_KRB5 137 +#define IDS_NC_METHODL_KRB4 138 +#define IDS_NC_METHODL_KRB524 139 +#define IDS_NC_METHOD_INVALID 140 +#define IDS_NC_TT_CONFLICT 141 +#define IDS_NC_TT_PROBLEM 142 +#define IDS_NC_TT_CONFLICTM 143 +#define IDS_NC_TT_DETAILS 144 +#define IDS_NC_TT_CONFLICTD 145 +#define IDS_NC_TT_EXPIRED 146 +#define IDS_NC_TT_EXISTS 147 +#define IDS_NC_TT_NEW 148 +#define IDS_CFG_CANTSTART 149 +#define IDS_CFG_CANTSTOP 150 +#define IDS_ERR_CELLCONFIG 151 +#define IDS_ERR_NOSERVICE 152 +#define IDS_ERR_CELLCONFIG_S 153 +#define IDS_ERR_GENERAL 154 +#define IDC_NCAFS_OBTAIN 1001 +#define IDC_NCAFS_TOKENLIST 1002 +#define IDC_NCAFS_CELL 1004 +#define IDC_NCAFS_REALM 1005 +#define IDC_NCAFS_METHOD 1006 +#define IDC_NCAFS_ADD_TOKEN 1007 +#define IDC_NCAFS_DELETE_TOKEN 1008 +#define IDC_CFG_SVCGRP 1009 +#define IDC_CFG_LBL_STATUS 1010 +#define IDC_CFG_STATUS 1011 +#define IDC_CFG_LBL_VERSION 1012 +#define IDC_CFG_VERSION 1013 +#define IDC_CFG_STOP 1014 +#define IDC_CFG_START 1015 +#define IDC_CFG_CPL 1016 +#define IDC_CFG_OBTAIN 1017 +#define IDC_CFG_PROGRESS 1019 +#define IDC_CFG_LBL_COMPANY 1020 +#define IDC_CFG_COMPANY 1021 +#define IDC_CFG_STARTGRP 1022 +#define IDC_CHECK1 1023 +#define IDC_CFG_STARTAFSCREDS 1023 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1024 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/WINNT/netidmgr_plugin/main.c b/src/WINNT/netidmgr_plugin/main.c new file mode 100644 index 0000000..e3569e5 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/main.c @@ -0,0 +1,148 @@ +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +/* Disable the 'macro redefinition' warning which is getting + triggerred by a redefinition of the ENCRYPT and DECRYPT macros. */ +#pragma warning (push) +#pragma warning (disable: 4005) + +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#pragma warning (pop) + +kmm_module h_khModule; /* KMM's handle to this module */ +HINSTANCE hInstance; +HMODULE hResModule; /* HMODULE to the resource library */ + +khm_handle csp_plugins = NULL; +khm_handle csp_afscred = NULL; +khm_handle csp_params = NULL; + +kmm_module_locale locales[] = { + LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"afscred_en_us.dll", KMM_MLOC_FLAG_DEFAULT) +}; +int n_locales = ARRAYLENGTH(locales); + +/* These two probably should not do anything */ +void init_afs() { +} + +void exit_afs() { +} + +/* called by the NetIDMgr module manager */ +KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) { + khm_int32 rv = KHM_ERROR_SUCCESS; + kmm_plugin_reg pi; + wchar_t buf[256]; + + h_khModule = h_module; + + rv = kmm_set_locale_info(h_module, locales, n_locales); + if(KHM_SUCCEEDED(rv)) { + hResModule = kmm_get_resource_hmodule(h_module); + } else { + goto _exit; + } + + ZeroMemory(&pi,sizeof(pi)); + + pi.msg_proc = afs_plugin_cb; + pi.name = AFS_PLUGIN_NAME; + pi.type = KHM_PITYPE_CRED; + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_AFSPLUGIN), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + pi.dependencies = AFS_PLUGIN_DEPS; + pi.description = buf; + + LoadString(hResModule, IDS_PLUGIN_DESC, + buf, ARRAYLENGTH(buf)); + + kmm_provide_plugin(h_module, &pi); + + if(KHM_FAILED(rv = init_imports())) + goto _exit; + + rv = kmm_get_plugins_config(0, &csp_plugins); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_load_schema(csp_plugins, schema_afsconfig); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_open_space(csp_plugins, CSNAME_AFSCRED, 0, &csp_afscred); + if(KHM_FAILED(rv)) goto _exit; + + rv = khc_open_space(csp_afscred, CSNAME_PARAMS, 0, &csp_params); + if(KHM_FAILED(rv)) goto _exit; + +_exit: + return rv; +} + +/* called by the NetIDMgr module manager */ +KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) { + exit_imports(); + + if(csp_params) { + khc_close_space(csp_params); + csp_params = NULL; + } + if(csp_afscred) { + khc_close_space(csp_afscred); + csp_afscred = NULL; + } + if(csp_plugins) { + khc_unload_schema(csp_plugins, schema_afsconfig); + khc_close_space(csp_plugins); + csp_plugins = NULL; + } + + return KHM_ERROR_SUCCESS; /* the return code is ignored */ +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + hInstance = hinstDLL; + init_afs(); + break; + case DLL_PROCESS_DETACH: + exit_afs(); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + + return TRUE; +} diff --git a/src/WINNT/netidmgr_plugin/params.h b/src/WINNT/netidmgr_plugin/params.h new file mode 100644 index 0000000..f0a5609 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/params.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* $Id$ */ + +#ifndef __KHIMAIRA_KRBAFSCRED_PARAMS_H +#define __KHIMAIRA_KRBAFSCRED_PARAMS_H + + +#endif \ No newline at end of file diff --git a/src/WINNT/netidmgr_plugin/version.rc b/src/WINNT/netidmgr_plugin/version.rc new file mode 100644 index 0000000..cc43459 --- /dev/null +++ b/src/WINNT/netidmgr_plugin/version.rc @@ -0,0 +1,87 @@ +/* Copyright (c) 2004 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* $Id$ */ + +#include +#include + +#ifndef LANGVER + +#define STR_FILEDESC "OpenAFS Plugin for NetIDMgr" +#define STR_INTNAME "afscred" +#define STR_ORIGNAME "afscred.dll" + +#else + +#ifdef LANG_en_us + +#define STR_FILEDESC "English(US) language resources for OpenAFS plugin" +#define STR_INTNAME "afscred_en_us" +#define STR_ORIGNAME "afscred_en_us.dll" + +#else + +#error Unknown langugae + +#endif + +#endif + +1 VERSIONINFO + FILEVERSION AFSPLUGIN_VERSION_LST + PRODUCTVERSION KH_VERSION_LIST + FILEFLAGSMASK KH_VER_FILEFLAGMASK + FILEFLAGS KH_VER_FILEFLAGS + FILEOS KH_VER_FILEOS + FILETYPE KH_VER_FILETYPEDLL + FILESUBTYPE 0 + { + + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", "Secure Endpoints Inc." + VALUE "FileDescription", STR_FILEDESC + VALUE "FileVersion", AFSPLUGIN_VERSION_STR + VALUE "InternalName", STR_INTNAME + VALUE "LegalCopyright", "(C) 2005 Secure Endpoints Inc." + VALUE "OriginalFilename", STR_ORIGNAME + VALUE "ProductName", "OpenAFS Plugin for NetIDMgr" + VALUE "ProductVersion", KH_VERSION_STRING +#ifndef LANGVER + VALUE NIMV_MODULE, "OpenAFS" + VALUE NIMV_PLUGINS, "AfsCred" + VALUE NIMV_APIVER, KH_VERSION_STRINGAPI + VALUE NIMV_SUPPORT, "http://www.secure-endpoints.com" +#endif + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1200 + } + } diff --git a/src/config/NTMakefile b/src/config/NTMakefile index 2c1879a..7bb7d6e 100644 --- a/src/config/NTMakefile +++ b/src/config/NTMakefile @@ -374,6 +374,9 @@ idirs: doclink ! IF (!EXIST($(OJT)\WINNT\license\lang)) $(MKDIR) $(OJT)\WINNT\license\lang ! ENDIF +! IF (!EXIST($(OJT)\WINNT\netidmgr_plugin)) + $(MKDIR) $(OJT)\WINNT\netidmgr_plugin +! ENDIF ! IF (!EXIST($(OJT)\WINNT\pthread)) $(MKDIR) $(OJT)\WINNT\pthread ! ENDIF