summaryrefslogtreecommitdiffstats
path: root/src/windows/kfwlogon
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/kfwlogon')
-rw-r--r--src/windows/kfwlogon/Makefile.in36
-rw-r--r--src/windows/kfwlogon/kfwcommon.c936
-rw-r--r--src/windows/kfwlogon/kfwcpcc.c39
-rw-r--r--src/windows/kfwlogon/kfwcpcc.rc10
-rw-r--r--src/windows/kfwlogon/kfwlogon.c344
-rw-r--r--src/windows/kfwlogon/kfwlogon.def12
-rw-r--r--src/windows/kfwlogon/kfwlogon.h200
-rw-r--r--src/windows/kfwlogon/kfwlogon.rc10
8 files changed, 1587 insertions, 0 deletions
diff --git a/src/windows/kfwlogon/Makefile.in b/src/windows/kfwlogon/Makefile.in
new file mode 100644
index 0000000000..69fe7ddb0c
--- /dev/null
+++ b/src/windows/kfwlogon/Makefile.in
@@ -0,0 +1,36 @@
+# Makefile for the KFW Network Provider
+#
+
+thisconfigdir=./..
+myfulldir=windows/nplogon
+mydir=.
+BUILDTOP=$(REL)..$(S)..
+DEFINES =
+LOCALINCLUDES = -I$(BUILDTOP) -I$(PISMERE)\athena\util\loadfuncs \
+ -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV \
+ -I$(PISMERE)\athena\auth\krb4\include
+PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR)
+
+SYSLIBS = kernel32.lib user32.lib advapi32.lib wsock32.lib secur32.lib
+RFLAGS = $(LOCALINCLUDES)
+RCFLAGS = $(RFLAGS) -D_WIN32
+
+all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe
+
+$(OUTPRE)kfwlogon.res: kfwlogon.rc ..\version.rc
+
+$(OUTPRE)kfwcpcc.res: kfwcpcc.rc ..\version.rc
+
+$(OUTPRE)kfwlogon.dll: $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwlogon.res
+ link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB)
+
+$(OUTPRE)kfwcpcc.exe: $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwcpcc.res
+ link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB)
+
+install::
+ copy $(OUTPRE)kfwlogon.dll $(DESTDIR)
+ copy $(OUTPRE)kfwcpcc.exe $(DESTDIR)
+
+clean::
+ $(RM) $(OUTPRE)*.exe $(OUTPRE)*.dll $(OUTPRE)*.res
+
diff --git a/src/windows/kfwlogon/kfwcommon.c b/src/windows/kfwlogon/kfwcommon.c
new file mode 100644
index 0000000000..4074d0da92
--- /dev/null
+++ b/src/windows/kfwlogon/kfwcommon.c
@@ -0,0 +1,936 @@
+/*
+Copyright 2005 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+#include "kfwlogon.h"
+#include <winbase.h>
+
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <winsock2.h>
+#include <lm.h>
+#include <nb30.h>
+
+/* Function Pointer Declarations for Delayed Loading */
+// 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);
+
+// leash functions
+DECL_FUNC_PTR(Leash_get_default_lifetime);
+DECL_FUNC_PTR(Leash_get_default_forwardable);
+DECL_FUNC_PTR(Leash_get_default_renew_till);
+DECL_FUNC_PTR(Leash_get_default_noaddresses);
+DECL_FUNC_PTR(Leash_get_default_proxiable);
+DECL_FUNC_PTR(Leash_get_default_publicip);
+DECL_FUNC_PTR(Leash_get_default_use_krb4);
+DECL_FUNC_PTR(Leash_get_default_life_min);
+DECL_FUNC_PTR(Leash_get_default_life_max);
+DECL_FUNC_PTR(Leash_get_default_renew_min);
+DECL_FUNC_PTR(Leash_get_default_renew_max);
+DECL_FUNC_PTR(Leash_get_default_renewable);
+DECL_FUNC_PTR(Leash_get_default_mslsa_import);
+
+// 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_build_principal_ext);
+DECL_FUNC_PTR(krb5_cc_get_name);
+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_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_free_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_free_addresses);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+
+// ComErr functions
+DECL_FUNC_PTR(com_err);
+DECL_FUNC_PTR(error_message);
+
+// Profile functions
+DECL_FUNC_PTR(profile_init);
+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_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 leash_fi[] = {
+ MAKE_FUNC_INFO(Leash_get_default_lifetime),
+ MAKE_FUNC_INFO(Leash_get_default_renew_till),
+ MAKE_FUNC_INFO(Leash_get_default_forwardable),
+ MAKE_FUNC_INFO(Leash_get_default_noaddresses),
+ MAKE_FUNC_INFO(Leash_get_default_proxiable),
+ MAKE_FUNC_INFO(Leash_get_default_publicip),
+ MAKE_FUNC_INFO(Leash_get_default_use_krb4),
+ MAKE_FUNC_INFO(Leash_get_default_life_min),
+ MAKE_FUNC_INFO(Leash_get_default_life_max),
+ MAKE_FUNC_INFO(Leash_get_default_renew_min),
+ MAKE_FUNC_INFO(Leash_get_default_renew_max),
+ MAKE_FUNC_INFO(Leash_get_default_renewable),
+ END_FUNC_INFO
+};
+
+FUNC_INFO leash_opt_fi[] = {
+ MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
+ 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_build_principal_ext),
+ MAKE_FUNC_INFO(krb5_cc_get_name),
+ 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_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_free_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_free_addresses),
+ MAKE_FUNC_INFO(krb5_c_random_make_octets),
+ END_FUNC_INFO
+};
+
+FUNC_INFO profile_fi[] = {
+ MAKE_FUNC_INFO(profile_init),
+ 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_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
+};
+
+/* Static Declarations */
+static int inited = 0;
+static HINSTANCE hKrb5 = 0;
+static HINSTANCE hKrb524 = 0;
+static HINSTANCE hSecur32 = 0;
+static HINSTANCE hAdvApi32 = 0;
+static HINSTANCE hComErr = 0;
+static HINSTANCE hService = 0;
+static HINSTANCE hProfile = 0;
+static HINSTANCE hLeash = 0;
+static HINSTANCE hLeashOpt = 0;
+static HINSTANCE hCCAPI = 0;
+
+static DWORD TraceOption = 0;
+static HANDLE hDLL;
+
+void DebugEvent0(char *a)
+{
+ HANDLE h; char *ptbuf[1];
+
+ h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
+ ptbuf[0] = a;
+ ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
+ DeregisterEventSource(h);
+}
+
+#define MAXBUF_ 512
+void DebugEvent(char *b,...)
+{
+ HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
+ va_list marker;
+
+ h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
+ va_start(marker,b);
+ StringCbVPrintf(buf, MAXBUF_+1,b,marker);
+ buf[MAXBUF_] = '\0';
+ ptbuf[0] = buf;
+ ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
+ DeregisterEventSource(h);
+ va_end(marker);
+}
+
+void
+UnloadFuncs(
+ FUNC_INFO fi[],
+ HINSTANCE h
+ )
+{
+ int n;
+ if (fi)
+ for (n = 0; fi[n].func_ptr_var; n++)
+ *(fi[n].func_ptr_var) = 0;
+ if (h) FreeLibrary(h);
+}
+
+int
+LoadFuncs(
+ const char* dll_name,
+ FUNC_INFO fi[],
+ HINSTANCE* ph, // [out, optional] - DLL handle
+ int* pindex, // [out, optional] - index of last func loaded (-1 if none)
+ int cleanup, // cleanup function pointers and unload on error
+ int go_on, // continue loading even if some functions cannot be loaded
+ int silent // do not pop-up a system dialog if DLL cannot be loaded
+ )
+{
+ HINSTANCE h;
+ int i, n, last_i;
+ int error = 0;
+ UINT em;
+
+ if (ph) *ph = 0;
+ if (pindex) *pindex = -1;
+
+ for (n = 0; fi[n].func_ptr_var; n++)
+ *(fi[n].func_ptr_var) = 0;
+
+ if (silent)
+ em = SetErrorMode(SEM_FAILCRITICALERRORS);
+ h = LoadLibrary(dll_name);
+ if (silent)
+ SetErrorMode(em);
+
+ if (!h)
+ return 0;
+
+ last_i = -1;
+ for (i = 0; (go_on || !error) && (i < n); i++)
+ {
+ void* p = (void*)GetProcAddress(h, fi[i].func_name);
+ if (!p)
+ error = 1;
+ else
+ {
+ last_i = i;
+ *(fi[i].func_ptr_var) = p;
+ }
+ }
+ if (pindex) *pindex = last_i;
+ if (error && cleanup && !go_on) {
+ for (i = 0; i < n; i++) {
+ *(fi[i].func_ptr_var) = 0;
+ }
+ FreeLibrary(h);
+ return 0;
+ }
+ if (ph) *ph = h;
+ if (error) return 0;
+ return 1;
+}
+
+static HANDLE hInitMutex = NULL;
+static BOOL bInit = FALSE;
+
+/* KFW_initialize cannot be called from DllEntryPoint */
+void
+KFW_initialize(void)
+{
+ static int inited = 0;
+
+ if ( !inited ) {
+ char mutexName[MAX_PATH];
+ HANDLE hMutex = NULL;
+
+ sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
+
+ hMutex = CreateMutex( NULL, TRUE, mutexName );
+ if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+ if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+ return;
+ }
+ }
+ if ( !inited ) {
+ inited = 1;
+ LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+ LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+ LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+ LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
+ LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
+ }
+ ReleaseMutex(hMutex);
+ CloseHandle(hMutex);
+ }
+}
+
+void
+KFW_cleanup(void)
+{
+ if (hLeashOpt)
+ FreeLibrary(hLeashOpt);
+ if (hCCAPI)
+ FreeLibrary(hCCAPI);
+ if (hLeash)
+ FreeLibrary(hLeash);
+ if (hKrb524)
+ FreeLibrary(hKrb524);
+ if (hSecur32)
+ FreeLibrary(hSecur32);
+ if (hService)
+ FreeLibrary(hService);
+ if (hComErr)
+ FreeLibrary(hComErr);
+ if (hProfile)
+ FreeLibrary(hProfile);
+ if (hKrb5)
+ FreeLibrary(hKrb5);
+}
+
+
+int
+KFW_is_available(void)
+{
+ KFW_initialize();
+ if ( hKrb5 && hComErr && hService &&
+#ifdef USE_MS2MIT
+ hSecur32 &&
+#endif /* USE_MS2MIT */
+ hProfile && hLeash && hCCAPI )
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Given a principal return an existing ccache or create one and return */
+int
+KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
+{
+ krb5_context ctx;
+ char * pname = 0;
+ char * ccname = 0;
+ krb5_error_code code;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( alt_ctx ) {
+ ctx = alt_ctx;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( principal ) {
+ code = pkrb5_unparse_name(ctx, principal, &pname);
+ if (code) goto cleanup;
+
+ ccname = (char *)malloc(strlen(pname) + 5);
+ sprintf(ccname,"API:%s",pname);
+
+ code = pkrb5_cc_resolve(ctx, ccname, cc);
+ } else {
+ code = pkrb5_cc_default(ctx, cc);
+ if (code) goto cleanup;
+ }
+
+ cleanup:
+ if (ccname)
+ free(ccname);
+ if (pname)
+ pkrb5_free_unparsed_name(ctx,pname);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+
+int
+KFW_kinit( krb5_context alt_ctx,
+ krb5_ccache alt_cc,
+ HWND hParent,
+ char *principal_name,
+ char *password,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP
+ )
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+ char* name = 0;
+ krb5_creds my_creds;
+ krb5_get_init_creds_opt options;
+ krb5_address ** addrs = NULL;
+ int i = 0, addr_count = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ pkrb5_get_init_creds_opt_init(&options);
+ memset(&my_creds, 0, sizeof(my_creds));
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( alt_cc ) {
+ cc = alt_cc;
+ } else {
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_parse_name(ctx, principal_name, &me);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, me, &name);
+ if (code)
+ goto cleanup;
+
+ if (lifetime == 0)
+ lifetime = pLeash_get_default_lifetime();
+ lifetime *= 60;
+
+ if (renew_life > 0)
+ renew_life *= 60;
+
+ if (lifetime)
+ pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+ pkrb5_get_init_creds_opt_set_forwardable(&options,
+ forwardable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&options,
+ proxiable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_renew_life(&options,
+ renew_life);
+ if (addressless)
+ pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
+ else {
+ if (publicIP)
+ {
+ // we are going to add the public IP address specified by the user
+ // to the list provided by the operating system
+ krb5_address ** local_addrs=NULL;
+ DWORD netIPAddr;
+
+ pkrb5_os_localaddr(ctx, &local_addrs);
+ while ( local_addrs[i++] );
+ addr_count = i + 1;
+
+ addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
+ if ( !addrs ) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+ memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
+ i = 0;
+ while ( local_addrs[i] ) {
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+
+ addrs[i]->magic = local_addrs[i]->magic;
+ addrs[i]->addrtype = local_addrs[i]->addrtype;
+ addrs[i]->length = local_addrs[i]->length;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+
+ memcpy(addrs[i]->contents,local_addrs[i]->contents,
+ local_addrs[i]->length); /* safe */
+ i++;
+ }
+ pkrb5_free_addresses(ctx, local_addrs);
+
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL)
+ goto cleanup;
+
+ addrs[i]->magic = KV5M_ADDRESS;
+ addrs[i]->addrtype = AF_INET;
+ addrs[i]->length = 4;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents)
+ goto cleanup;
+
+ netIPAddr = htonl(publicIP);
+ memcpy(addrs[i]->contents,&netIPAddr,4);
+
+ pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
+
+ }
+ }
+
+ code = pkrb5_get_init_creds_password(ctx,
+ &my_creds,
+ me,
+ password, // password
+ NULL, // no prompter
+ hParent, // prompter data
+ 0, // start time
+ 0, // service name
+ &options);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code)
+ goto cleanup;
+
+ cleanup:
+ if ( addrs ) {
+ for ( i=0;i<addr_count;i++ ) {
+ if ( addrs[i] ) {
+ if ( addrs[i]->contents )
+ free(addrs[i]->contents);
+ free(addrs[i]);
+ }
+ }
+ }
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ pkrb5_free_cred_contents(ctx, &my_creds);
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (cc && (cc != alt_cc))
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+
+int
+KFW_get_cred( char * username,
+ char * password,
+ int lifetime,
+ char ** reasonP )
+{
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ char * realm = 0, * userrealm = 0;
+ int free_realm = 0;
+ krb5_principal principal = 0;
+ char * pname = 0;
+ krb5_error_code code;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_get_cred for token ");
+ OutputDebugString(username);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if ( code ) goto cleanup;
+
+ code = pkrb5_get_default_realm(ctx, &realm);
+
+ userrealm = strchr(username,'@');
+ if (realm) {
+ free_realm = 1;
+ pname = malloc(strlen(username) + strlen(realm) + 2);
+ userrealm = strchr(pname, '@');
+ userrealm++;
+ strcat(userrealm, realm);
+ } else {
+ pname = strdup(username);
+ userrealm = strchr(pname, '@');
+ userrealm++;
+ realm = userrealm;
+ }
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Realm: ");
+ OutputDebugString(realm);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_parse_name(ctx, pname, &principal);
+ if ( code ) goto cleanup;
+
+ code = KFW_get_ccache(ctx, principal, &cc);
+ if ( code ) goto cleanup;
+
+ if ( lifetime == 0 )
+ lifetime = pLeash_get_default_lifetime();
+
+ if ( password && password[0] ) {
+ code = KFW_kinit( ctx, cc, HWND_DESKTOP,
+ pname,
+ password,
+ lifetime,
+ pLeash_get_default_forwardable(),
+ pLeash_get_default_proxiable(),
+ pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
+ pLeash_get_default_noaddresses(),
+ pLeash_get_default_publicip());
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_kinit() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ if ( code ) goto cleanup;
+ }
+
+ cleanup:
+ if ( pname )
+ free(pname);
+ if ( cc )
+ pkrb5_cc_close(ctx, cc);
+
+ if ( code && reasonP ) {
+ *reasonP = (char *)perror_message(code);
+ }
+ return(code);
+}
+
+void
+KFW_copy_cache_to_system_file(char * user, char * szLogonId)
+{
+ char filename[256];
+ DWORD count;
+ char cachename[264] = "FILE:";
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+ krb5_ccache ncc = 0;
+
+ if (!pkrb5_init_context)
+ return;
+
+ count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
+ if ( count > sizeof(filename) || count == 0 ) {
+ GetWindowsDirectory(filename, sizeof(filename));
+ }
+
+ if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
+ return;
+
+ strcat(filename, "\\");
+ strcat(filename, szLogonId);
+
+ strcat(cachename, filename);
+
+ DeleteFile(filename);
+
+ code = pkrb5_init_context(&ctx);
+ if (code) ctx = 0;
+
+ code = pkrb5_parse_name(ctx, user, &princ);
+ if (code) goto cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_resolve(ctx, cachename, &ncc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+
+ cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+}
+
+int
+KFW_copy_system_file_to_default_cache(char * filename)
+{
+ char cachename[264] = "FILE:";
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+ krb5_ccache ncc = 0;
+ int retval = 1;
+
+ if (!pkrb5_init_context)
+ return 1;
+
+ if ( strlen(filename) + 6 > sizeof(cachename) )
+ return 1;
+
+ strcat(cachename, filename);
+
+ code = pkrb5_init_context(&ctx);
+ if (code) ctx = 0;
+
+ code = pkrb5_cc_resolve(ctx, cachename, &cc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_default(ctx, &ncc);
+ if (!code) {
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+
+ if (!code)
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+
+ retval=0; /* success */
+
+ cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+
+ DeleteFile(filename);
+
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return 0;
+}
+
+
+int
+KFW_destroy_tickets_for_principal(char * user)
+{
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_destroy_tickets_for_user: ");
+ OutputDebugString(user);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code) ctx = 0;
+
+ code = pkrb5_parse_name(ctx, user, &princ);
+ if (code) goto loop_cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto loop_cleanup;
+
+ code = pkrb5_cc_destroy(ctx, cc);
+ if (!code) cc = 0;
+
+ loop_cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ pkrb5_free_context(ctx);
+ return 0;
+}
+
diff --git a/src/windows/kfwlogon/kfwcpcc.c b/src/windows/kfwlogon/kfwcpcc.c
new file mode 100644
index 0000000000..4dbace9696
--- /dev/null
+++ b/src/windows/kfwlogon/kfwcpcc.c
@@ -0,0 +1,39 @@
+/*
+
+Copyright 2005 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+#include <windows.h>
+#include "kfwlogon.h"
+
+int main(int argc, char *argv[])
+{
+ if ( argc != 2 )
+ return 1;
+
+ KFW_initialize();
+
+ return KFW_copy_system_file_to_default_cache(argv[1]);
+}
+
+
diff --git a/src/windows/kfwlogon/kfwcpcc.rc b/src/windows/kfwlogon/kfwcpcc.rc
new file mode 100644
index 0000000000..5b0bbf217e
--- /dev/null
+++ b/src/windows/kfwlogon/kfwcpcc.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <winver.h>
+#include "patchlevel.h"
+
+#define K5_DESCRIPTION "Kerberos for Windows Logon Network Provider\0"
+#define K5_FILETYPE VFT_APP
+#define K5_INTERNAL_NAME "KFWLOGON\0"
+#define K5_ORIGINAL_NAME "kfwcpcc.exe\0"
+
+#include "..\version.rc"
diff --git a/src/windows/kfwlogon/kfwlogon.c b/src/windows/kfwlogon/kfwlogon.c
new file mode 100644
index 0000000000..70b6234830
--- /dev/null
+++ b/src/windows/kfwlogon/kfwlogon.c
@@ -0,0 +1,344 @@
+/*
+Copyright 2005 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+#include "kfwlogon.h"
+
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <winsock2.h>
+#include <lm.h>
+#include <nb30.h>
+
+static HANDLE hDLL;
+
+static HANDLE hInitMutex = NULL;
+static BOOL bInit = FALSE;
+
+
+BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
+{
+ hDLL = dll;
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ /* Initialization Mutex */
+ hInitMutex = CreateMutex(NULL, FALSE, NULL);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ CloseHandle(hInitMutex);
+ break;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ default:
+ /* Everything else succeeds but does nothing. */
+ break;
+ }
+
+ return TRUE;
+}
+
+
+
+DWORD APIENTRY NPGetCaps(DWORD index)
+{
+ switch (index) {
+ case WNNC_NET_TYPE:
+ /* Don't have our own type; use somebody else's. */
+ return WNNC_NET_SUN_PC_NFS;
+
+ case WNNC_START:
+ /* Say we are already started, even though we might wait after we receive NPLogonNotify */
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+static BOOL
+WINAPI
+UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
+{
+ CPINFO CodePageInfo;
+
+ GetCPInfo(CP_ACP, &CodePageInfo);
+
+ if (CodePageInfo.MaxCharSize > 1)
+ // Only supporting non-Unicode strings
+ return FALSE;
+
+ if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
+ {
+ // Looks like unicode, better translate it
+ // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
+ WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
+ lpszOutputString, nOutStringLen-1, NULL, NULL);
+ lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
+ return TRUE;
+ }
+ else
+ lpszOutputString[0] = '\0';
+ return FALSE;
+} // UnicodeStringToANSI
+
+
+DWORD APIENTRY NPLogonNotify(
+ PLUID lpLogonId,
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ LPWSTR *lpLogonScript)
+{
+ char uname[MAX_USERNAME_LENGTH]="";
+ char password[MAX_PASSWORD_LENGTH]="";
+ char logonDomain[MAX_DOMAIN_LENGTH]="";
+ char szLogonId[128] = "";
+
+ MSV1_0_INTERACTIVE_LOGON *IL;
+
+ DWORD code = 0;
+
+ char *reason;
+ char *ctemp;
+
+ BOOLEAN interactive;
+ HWND hwndOwner = (HWND)StationHandle;
+ BOOLEAN lowercased_name = TRUE;
+
+ if ( !KFW_is_available() )
+ return 0;
+
+ DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
+
+ /* Initialize Logon Script to none */
+ *lpLogonScript=NULL;
+
+ /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
+ * our purposes */
+
+ if ( wcscmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
+ wcscmp(lpAuthentInfoType,L"Kerberos:Interactive") )
+ {
+ DebugEvent("Unsupported Authentication Info Type: %S",
+ lpAuthentInfoType);
+ return 0;
+ }
+
+ IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
+
+ /* Are we interactive? */
+ interactive = (wcscmp(lpStationName, L"WinSta0") == 0);
+
+ /* Convert from Unicode to ANSI */
+
+ /*TODO: Use SecureZeroMemory to erase passwords */
+ UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH);
+ UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH);
+ UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH);
+
+ /* Make sure AD-DOMANS sent from login that is sent to us is stripped */
+ ctemp = strchr(uname, '@');
+ if (ctemp) *ctemp = 0;
+
+ /* is the name all lowercase? */
+ for ( ctemp = uname; *ctemp ; ctemp++) {
+ if ( !islower(*ctemp) ) {
+ lowercased_name = FALSE;
+ break;
+ }
+ }
+
+ code = KFW_get_cred(uname, password, 0, &reason);
+ DebugEvent("KFW_get_cred uname=[%s] code=[%d]",uname, code);
+
+ /* remove any kerberos 5 tickets currently held by the SYSTEM account
+ * for this user
+ */
+ sprintf(szLogonId,"kfwlogon-%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
+ KFW_copy_cache_to_system_file(uname, szLogonId);
+
+ KFW_destroy_tickets_for_principal(uname);
+
+ if (code) {
+ char msg[128];
+ HANDLE h;
+ char *ptbuf[1];
+
+ StringCbPrintf(msg, sizeof(msg), "Kerberos ticket acquisition failed: %s", reason);
+
+ h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
+ ptbuf[0] = msg;
+ ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
+ 1, 0, ptbuf, NULL);
+ DeregisterEventSource(h);
+ SetLastError(code);
+ }
+
+ return code;
+}
+
+
+DWORD APIENTRY NPPasswordChangeNotify(
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ DWORD dwChangeInfo)
+{
+ return 0;
+}
+
+#include <userenv.h>
+#include <Winwlx.h>
+
+#ifdef COMMENT
+typedef struct _WLX_NOTIFICATION_INFO {
+ ULONG Size;
+ ULONG Flags;
+ PWSTR UserName;
+ PWSTR Domain;
+ PWSTR WindowStation;
+ HANDLE hToken;
+ HDESK hDesktop;
+ PFNMSGECALLBACK pStatusCallback;
+} WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
+#endif
+
+VOID KFW_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
+{
+ DebugEvent0("KFW_Startup_Event");
+}
+
+static BOOL
+GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+ NTSTATUS Status = 0;
+#if 0
+ HANDLE TokenHandle;
+#endif
+ TOKEN_STATISTICS Stats;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (!ppSessionData)
+ return FALSE;
+ *ppSessionData = NULL;
+
+#if 0
+ Success = OpenProcessToken( HANDLE GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( !Success )
+ return FALSE;
+#endif
+
+ Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+#if 0
+ CloseHandle( TokenHandle );
+#endif
+ if ( !Success )
+ return FALSE;
+
+ Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+ if ( FAILED(Status) || !ppSessionData )
+ return FALSE;
+
+ return TRUE;
+}
+
+VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
+{
+ WCHAR szUserW[128] = L"";
+ char szUserA[128] = "";
+ char szPath[MAX_PATH] = "";
+ char szLogonId[128] = "";
+ DWORD count;
+ char filename[256];
+ char commandline[512];
+ STARTUPINFO startupinfo;
+ PROCESS_INFORMATION procinfo;
+
+ LUID LogonId = {0, 0};
+ PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
+
+ HKEY hKey1 = NULL, hKey2 = NULL;
+
+ DebugEvent0("KFW_Logon_Event - Start");
+
+ GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
+
+ if ( pLogonSessionData ) {
+ LogonId = pLogonSessionData->LogonId;
+ DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
+
+ sprintf(szLogonId,"kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart);
+ LsaFreeReturnBuffer( pLogonSessionData );
+ } else {
+ DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
+ return;
+ }
+
+ count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
+ if ( count > sizeof(filename) || count == 0 ) {
+ GetWindowsDirectory(filename, sizeof(filename));
+ }
+
+ if ( strlen(filename) + strlen(szLogonId) + 2 <= sizeof(filename) ) {
+ strcat(filename, "\\");
+ strcat(filename, szLogonId);
+
+ sprintf(commandline, "kfwcpcc.exe \"%s\"", filename);
+
+ GetStartupInfo(&startupinfo);
+ if (CreateProcessAsUser( pInfo->hToken,
+ "kfwcpcc.exe",
+ commandline,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
+ NULL,
+ NULL,
+ &startupinfo,
+ &procinfo))
+ {
+ WaitForSingleObject(procinfo.hProcess, 30000);
+
+ CloseHandle(procinfo.hThread);
+ CloseHandle(procinfo.hProcess);
+ }
+ }
+
+ DeleteFile(filename);
+
+ DebugEvent0("KFW_Logon_Event - End");
+}
+
diff --git a/src/windows/kfwlogon/kfwlogon.def b/src/windows/kfwlogon/kfwlogon.def
new file mode 100644
index 0000000000..52af990907
--- /dev/null
+++ b/src/windows/kfwlogon/kfwlogon.def
@@ -0,0 +1,12 @@
+LIBRARY KFWLOGON
+
+EXPORTS
+
+ DllEntryPoint
+ NPGetCaps
+ NPLogonNotify
+ NPPasswordChangeNotify
+ KFW_Logon_Event
+
+
+
diff --git a/src/windows/kfwlogon/kfwlogon.h b/src/windows/kfwlogon/kfwlogon.h
new file mode 100644
index 0000000000..34c8cc70c8
--- /dev/null
+++ b/src/windows/kfwlogon/kfwlogon.h
@@ -0,0 +1,200 @@
+/*
+
+Copyright 2005 by the Massachusetts Institute of Technology
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the Massachusetts
+Institute of Technology (M.I.T.) not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*/
+
+/* We only support VC 1200 and above anyway */
+#pragma once
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include <windows.h>
+#include <npapi.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+#include <tchar.h>
+#include <strsafe.h>
+
+typedef int errcode_t;
+
+#include <loadfuncs-lsa.h>
+#include <krb5.h>
+#include <loadfuncs-com_err.h>
+#include <loadfuncs-krb5.h>
+#include <loadfuncs-profile.h>
+#include <loadfuncs-leash.h>
+
+// service definitions
+#define SERVICE_DLL "advapi32.dll"
+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);
+
+/* 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
+ )
+);
+/* End private ccapiv2 headers */
+
+#define CCAPI_DLL "krbcc32.dll"
+
+
+/* */
+#define MAX_USERNAME_LENGTH 256
+#define MAX_PASSWORD_LENGTH 256
+#define MAX_DOMAIN_LENGTH 256
+
+#define KFW_LOGON_EVENT_NAME TEXT("KFW Logon")
+
+BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved);
+
+DWORD APIENTRY NPGetCaps(DWORD index);
+
+DWORD APIENTRY NPLogonNotify(
+ PLUID lpLogonId,
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ LPWSTR *lpLogonScript);
+
+DWORD APIENTRY NPPasswordChangeNotify(
+ LPCWSTR lpAuthentInfoType,
+ LPVOID lpAuthentInfo,
+ LPCWSTR lpPreviousAuthentInfoType,
+ LPVOID lpPreviousAuthentInfo,
+ LPWSTR lpStationName,
+ LPVOID StationHandle,
+ DWORD dwChangeInfo);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void UnloadFuncs(FUNC_INFO [], HINSTANCE);
+
+int LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int);
+
+void DebugEvent0(char *a);
+void DebugEvent(char *b,...);
+
+DWORD MapAuthError(DWORD code);
+
+static BOOL WINAPI UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen);
+
+int KFW_is_available(void);
+int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP );
+void KFW_copy_cache_to_system_file(char * user, char * szLogonId);
+int KFW_destroy_tickets_for_principal(char * user);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/windows/kfwlogon/kfwlogon.rc b/src/windows/kfwlogon/kfwlogon.rc
new file mode 100644
index 0000000000..1a3cb15eea
--- /dev/null
+++ b/src/windows/kfwlogon/kfwlogon.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <winver.h>
+#include "patchlevel.h"
+
+#define K5_DESCRIPTION "Kerberos for Windows Logon Network Provider\0"
+#define K5_FILETYPE VFT_DLL
+#define K5_INTERNAL_NAME "KFWLOGON\0"
+#define K5_ORIGINAL_NAME "kfwlogon.dll\0"
+
+#include "..\version.rc"