diff --git a/src/NTMakefile b/src/NTMakefile
index 42a6306c5f..f6b59fbc9c 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 a8823ec4b5..2126146fa7 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 bb36097e6f..684b68e349 100644
--- a/src/WINNT/install/wix/feature.wxi
+++ b/src/WINNT/install/wix/feature.wxi
@@ -24,33 +24,48 @@
-
-
- VersionNT = 500 And ServicePackLevel < 3
-
-
-
-
- CREDSSTARTUP = 0
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+ VersionNT = 500 And ServicePackLevel < 3
+
+
+
+
+ CREDSSTARTUP = 0
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -263,16 +278,31 @@
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WINNT/install/wix/files.wxi b/src/WINNT/install/wix/files.wxi
index 3d34d2a05b..9959d17c19 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 72a2843a4e..5737a82270 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 ExtensionAuthentication for AFS
diff --git a/src/WINNT/install/wix/openafs.wxs b/src/WINNT/install/wix/openafs.wxs
index 933f2be104..3fde40ae81 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_UPGRADENSISUNINSTALL <> "" AND UILevel >= 4NSISUNINSTALL <> "" AND UILevel < 4
@@ -243,6 +243,13 @@
+
+
+
+
+
+
+
diff --git a/src/WINNT/install/wix/platform.wxi b/src/WINNT/install/wix/platform.wxi
index e8b1d8fa3c..53ccc92cc0 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 0000000000..ba846733ff
--- /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 0000000000..512e2a0bbf
--- /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 0000000000..1fbf84b8db
--- /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 0000000000..3dad7ab405
--- /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 0000000000..5a3e5d3b2d
--- /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 0000000000..f27f323d2a
--- /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 0000000000..6a163cd707
--- /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 0000000000..e143c067ca
--- /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 0000000000..e35c347752
--- /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 0000000000..cc760cd274
--- /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 0000000000..11974bfe85
--- /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 0000000000..a15043ea5d
--- /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 0000000000..cfe802b2b9
--- /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().
+
+
+
Type
type ID of ::AFS_MSG_TYPENAME
+
Subtype
::AFS_MSG_ANNOUNCE
+
uparam
0
+
vparam
Pointer 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.
+
+
+
Type
type ID of ::AFS_MSG_TYPENAME
+
Subtype
::AFS_MSG_RESOLVE_TOKEN
+
uparam
0
+
vparam
Pointer 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
+
+
+
Type
type ID of ::AFS_MSG_TYPENAME
+
Subtype
::AFS_MSG_KLOG
+
uparam
0
+
vparam
Pointer 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 0000000000..3dd47e1ff5
--- /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 0000000000..d32b8784bc
--- /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 0000000000..bb4b8bdb62
--- /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 0000000000..46c72e029b
--- /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 0000000000..c0ba08a9ac
--- /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 0000000000..8d41e0635b
--- /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 0000000000..51738d484b
--- /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 0000000000..5bc86f5e0c
--- /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 0000000000..f59706cc68
--- /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 0000000000..214215c1cd
--- /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 0000000000..93687d4ec2
--- /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 0000000000..2d63278d02
--- /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 0000000000..cbddc47c4a
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 0000000000..2856ffa5ea
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 0000000000..69101c5e76
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 0000000000..67e843f8cb
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 0000000000..0d388cacfa
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 0000000000..ce0f628792
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 0000000000..b3b02634de
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 0000000000..51c16d683b
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 0000000000..cbdf541b31
--- /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 0000000000..7d163d6194
--- /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.
+
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 0000000000..ec14f2fa08
--- /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.
+
+
+
+
+
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
+
+
+
+
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:
+
+
+
+
+
+
+
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 0000000000..592b13ad63
--- /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.
+
+
+
\ 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 0000000000..4dc07f64e6
--- /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 0000000000..09e4db31ae
--- /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 0000000000..3e153fad74
--- /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 0000000000..f8fe9ca2ac
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 0000000000..61534df746
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 0000000000..1491e3d06c
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 0000000000..cb6c7504e0
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 0000000000..84bf9b64ba
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 0000000000..5475036fc7
--- /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 0000000000..29cae71ee9
--- /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 0000000000..fb185b6082
--- /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 "
"
+ 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 0000000000..9202b4f2f4
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 0000000000..b71453945c
--- /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 0000000000..f651825ec6
--- /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 0000000000..e3569e5aa3
--- /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 0000000000..f0a5609195
--- /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 0000000000..cc434595a8
--- /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 2c1879a14e..7bb7d6e6bf 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