Pull up r17518, r17519 from trunk. r17526 corrects some
authorTom Yu <tlyu@mit.edu>
Wed, 30 Nov 2005 18:52:32 +0000 (18:52 +0000)
committerTom Yu <tlyu@mit.edu>
Wed, 30 Nov 2005 18:52:32 +0000 (18:52 +0000)
trunk-specific problems introduced by r17519.

ticket: 3254
version_fixed: 1.4.4

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-4@17527 dc483132-0cff-0310-8789-dd5450dbe970

12 files changed:
src/ChangeLog
src/Makefile.in
src/windows/ChangeLog
src/windows/Makefile.in
src/windows/kfwlogon/Makefile.in [new file with mode: 0644]
src/windows/kfwlogon/kfwcommon.c [new file with mode: 0644]
src/windows/kfwlogon/kfwcpcc.c [new file with mode: 0644]
src/windows/kfwlogon/kfwcpcc.rc [new file with mode: 0644]
src/windows/kfwlogon/kfwlogon.c [new file with mode: 0644]
src/windows/kfwlogon/kfwlogon.def [new file with mode: 0644]
src/windows/kfwlogon/kfwlogon.h [new file with mode: 0644]
src/windows/kfwlogon/kfwlogon.rc [new file with mode: 0644]

index 394ec1269db86897231a4fc952b399fb94885f5a..0b0b6e29179fbda429ed53809cc0023bfacde9c7 100644 (file)
@@ -1,3 +1,7 @@
+2005-11-29  Jeffrey Altman <jaltman@mit.edu>
+
+       * Makefile.in: add src/windows/kfwlogon tree
+
 2005-09-08  Tom Yu  <tlyu@mit.edu>
 
        * aclocal.m4 (AC_LIBRARY_NET): Check for a few more libresolv
index 3a94a769e8ef9bd43ca8d00a27d005cc9eef035d..edc2cbc9c6a45d12c3e3a49873341564b60c8492 100644 (file)
@@ -176,7 +176,7 @@ WINMAKEFILES=Makefile \
        windows\Makefile windows\lib\Makefile \
        windows\cns\Makefile windows\gina\Makefile \
        windows\gss\Makefile windows\ms2mit\Makefile \
-       windows\wintel\Makefile
+       windows\wintel\Makefile windows\kfwlogon\Makefile
 
 ##DOS##Makefile-windows:: $(MKFDEP) $(WINMAKEFILES)
 
@@ -296,6 +296,8 @@ WINMAKEFILES=Makefile \
 ##DOS##        $(WCONFIG) config < $@.in > $@
 ##DOS##windows\wintel\Makefile: windows\wintel\Makefile.in $(MKFDEP)
 ##DOS##        $(WCONFIG) config < $@.in > $@
+##DOS##windows\kfwlogon\Makefile: windows\kfwlogon\Makefile.in $(MKFDEP)
+##DOS##        $(WCONFIG) config < $@.in > $@
 
 clean-windows:: Makefile-windows
        @echo Making clean in util
index c1165b6f35692c4e0c21c171e3393cc26524c21d..d2fcb8fa24b6b79d81b745b7ebb9286ee4e3f2c0 100644 (file)
@@ -1,3 +1,7 @@
+2005-11-29  Jeffrey Altman <jaltman@mit.edu>
+
+       * Makefile.in: build src/windows/kfwlogon
+
 2004-12-15  Jeffrey Altman <jaltman@mit.edu>
    
          * version.rc: rename krb5support.dll to k5sprt32.dll
index ae3c48f120a660cd89035dbddee2a1c71e71d1ec..f1045951ae4d1827dbd279ff5cc9f30dd5eb3fdc 100644 (file)
@@ -24,6 +24,9 @@ all-windows::
        cd ..\ms2mit
        $(MAKE) -$(MFLAGS)
 !if "$(KRB5_KFW_COMPILE)"=="1" 
+        @echo Making in windows\kfwlogon
+        cd ..\kfwlogon
+        $(MAKE) -$(MFLAGS) 
         @echo Making in windows\identity 
         cd ..\identity 
         $(MAKE) -$(MFLAGS) 
@@ -50,6 +53,9 @@ clean-windows::
        cd ..\ms2mit
        $(MAKE) -$(MFLAGS) clean
 !if "$(KRB5_KFW_COMPILE)"=="1" 
+        @echo Making clean in windows\kfwlogon
+        cd ..\kfwlogon
+        $(MAKE) -$(MFLAGS) clean 
         @echo Making clean in windows\identity 
         cd ..\identity 
         $(MAKE) -$(MFLAGS) clean 
diff --git a/src/windows/kfwlogon/Makefile.in b/src/windows/kfwlogon/Makefile.in
new file mode 100644 (file)
index 0000000..69fe7dd
--- /dev/null
@@ -0,0 +1,36 @@
+# Makefile for the KFW Network Provider\r
+#\r
+\r
+thisconfigdir=./..\r
+myfulldir=windows/nplogon\r
+mydir=.\r
+BUILDTOP=$(REL)..$(S)..\r
+DEFINES = \r
+LOCALINCLUDES = -I$(BUILDTOP) -I$(PISMERE)\athena\util\loadfuncs \\r
+       -I$(PISMERE)\athena\auth\krb5\src\include\kerberosIV \\r
+       -I$(PISMERE)\athena\auth\krb4\include\r
+PROG_LIBPATH=-L$(TOPLIBD) -L$(KRB5_LIBDIR)\r
+\r
+SYSLIBS = kernel32.lib user32.lib advapi32.lib wsock32.lib secur32.lib\r
+RFLAGS = $(LOCALINCLUDES)\r
+RCFLAGS = $(RFLAGS) -D_WIN32\r
+\r
+all-windows:: $(OUTPRE)kfwlogon.dll $(OUTPRE)kfwcpcc.exe\r
+\r
+$(OUTPRE)kfwlogon.res: kfwlogon.rc ..\version.rc\r
+\r
+$(OUTPRE)kfwcpcc.res: kfwcpcc.rc ..\version.rc\r
+\r
+$(OUTPRE)kfwlogon.dll: $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwlogon.res\r
+    link $(DLL_LINKOPTS) -out:$@ $(OUTPRE)kfwlogon.obj $(OUTPRE)kfwcommon.obj -entry:DllEntryPoint -def:kfwlogon.def $(SYSLIBS) $(KLIB) $(CLIB)\r
+\r
+$(OUTPRE)kfwcpcc.exe: $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(OUTPRE)kfwcpcc.res\r
+    link $(EXE_LINKOPTS) -out:$@ $(OUTPRE)kfwcpcc.obj $(OUTPRE)kfwcommon.obj $(SYSLIBS) $(KLIB) $(CLIB)\r
+\r
+install::\r
+        copy $(OUTPRE)kfwlogon.dll $(DESTDIR)\r
+        copy $(OUTPRE)kfwcpcc.exe  $(DESTDIR)\r
+\r
+clean::\r
+        $(RM) $(OUTPRE)*.exe $(OUTPRE)*.dll $(OUTPRE)*.res\r
+\r
diff --git a/src/windows/kfwlogon/kfwcommon.c b/src/windows/kfwlogon/kfwcommon.c
new file mode 100644 (file)
index 0000000..4074d0d
--- /dev/null
@@ -0,0 +1,936 @@
+/*\r
+Copyright 2005 by the Massachusetts Institute of Technology\r
+\r
+All rights reserved.\r
+\r
+Permission to use, copy, modify, and distribute this software and its\r
+documentation for any purpose and without fee is hereby granted,\r
+provided that the above copyright notice appear in all copies and that\r
+both that copyright notice and this permission notice appear in\r
+supporting documentation, and that the name of the Massachusetts\r
+Institute of Technology (M.I.T.) not be used in advertising or publicity\r
+pertaining to distribution of the software without specific, written\r
+prior permission.\r
+\r
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+SOFTWARE.\r
+\r
+*/\r
+\r
+#include "kfwlogon.h"\r
+#include <winbase.h>\r
+\r
+#include <io.h>\r
+#include <sys/stat.h>\r
+#include <sys/types.h>\r
+#include <fcntl.h>\r
+\r
+#include <winsock2.h>\r
+#include <lm.h>\r
+#include <nb30.h>\r
+\r
+/* Function Pointer Declarations for Delayed Loading */\r
+// CCAPI\r
+DECL_FUNC_PTR(cc_initialize);\r
+DECL_FUNC_PTR(cc_shutdown);\r
+DECL_FUNC_PTR(cc_get_NC_info);\r
+DECL_FUNC_PTR(cc_free_NC_info);\r
+\r
+// leash functions\r
+DECL_FUNC_PTR(Leash_get_default_lifetime);\r
+DECL_FUNC_PTR(Leash_get_default_forwardable);\r
+DECL_FUNC_PTR(Leash_get_default_renew_till);\r
+DECL_FUNC_PTR(Leash_get_default_noaddresses);\r
+DECL_FUNC_PTR(Leash_get_default_proxiable);\r
+DECL_FUNC_PTR(Leash_get_default_publicip);\r
+DECL_FUNC_PTR(Leash_get_default_use_krb4);\r
+DECL_FUNC_PTR(Leash_get_default_life_min);\r
+DECL_FUNC_PTR(Leash_get_default_life_max);\r
+DECL_FUNC_PTR(Leash_get_default_renew_min);\r
+DECL_FUNC_PTR(Leash_get_default_renew_max);\r
+DECL_FUNC_PTR(Leash_get_default_renewable);\r
+DECL_FUNC_PTR(Leash_get_default_mslsa_import);\r
+\r
+// krb5 functions\r
+DECL_FUNC_PTR(krb5_change_password);\r
+DECL_FUNC_PTR(krb5_get_init_creds_opt_init);\r
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);\r
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);\r
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);\r
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);\r
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);\r
+DECL_FUNC_PTR(krb5_get_init_creds_password);\r
+DECL_FUNC_PTR(krb5_build_principal_ext);\r
+DECL_FUNC_PTR(krb5_cc_get_name);\r
+DECL_FUNC_PTR(krb5_cc_resolve);\r
+DECL_FUNC_PTR(krb5_cc_default);\r
+DECL_FUNC_PTR(krb5_cc_default_name);\r
+DECL_FUNC_PTR(krb5_cc_set_default_name);\r
+DECL_FUNC_PTR(krb5_cc_initialize);\r
+DECL_FUNC_PTR(krb5_cc_destroy);\r
+DECL_FUNC_PTR(krb5_cc_close);\r
+DECL_FUNC_PTR(krb5_cc_store_cred);\r
+DECL_FUNC_PTR(krb5_cc_copy_creds);\r
+DECL_FUNC_PTR(krb5_cc_retrieve_cred);\r
+DECL_FUNC_PTR(krb5_cc_get_principal);\r
+DECL_FUNC_PTR(krb5_cc_start_seq_get);\r
+DECL_FUNC_PTR(krb5_cc_next_cred);\r
+DECL_FUNC_PTR(krb5_cc_end_seq_get);\r
+DECL_FUNC_PTR(krb5_cc_remove_cred);\r
+DECL_FUNC_PTR(krb5_cc_set_flags);\r
+DECL_FUNC_PTR(krb5_cc_get_type);\r
+DECL_FUNC_PTR(krb5_free_context);\r
+DECL_FUNC_PTR(krb5_free_cred_contents);\r
+DECL_FUNC_PTR(krb5_free_principal);\r
+DECL_FUNC_PTR(krb5_get_in_tkt_with_password);\r
+DECL_FUNC_PTR(krb5_init_context);\r
+DECL_FUNC_PTR(krb5_parse_name);\r
+DECL_FUNC_PTR(krb5_timeofday);\r
+DECL_FUNC_PTR(krb5_timestamp_to_sfstring);\r
+DECL_FUNC_PTR(krb5_unparse_name);\r
+DECL_FUNC_PTR(krb5_get_credentials);\r
+DECL_FUNC_PTR(krb5_mk_req);\r
+DECL_FUNC_PTR(krb5_sname_to_principal);\r
+DECL_FUNC_PTR(krb5_get_credentials_renew);\r
+DECL_FUNC_PTR(krb5_free_data);\r
+DECL_FUNC_PTR(krb5_free_data_contents);\r
+DECL_FUNC_PTR(krb5_free_unparsed_name);\r
+DECL_FUNC_PTR(krb5_os_localaddr);\r
+DECL_FUNC_PTR(krb5_copy_keyblock_contents);\r
+DECL_FUNC_PTR(krb5_copy_data);\r
+DECL_FUNC_PTR(krb5_free_creds);\r
+DECL_FUNC_PTR(krb5_build_principal);\r
+DECL_FUNC_PTR(krb5_get_renewed_creds);\r
+DECL_FUNC_PTR(krb5_get_default_config_files);\r
+DECL_FUNC_PTR(krb5_free_config_files);\r
+DECL_FUNC_PTR(krb5_get_default_realm);\r
+DECL_FUNC_PTR(krb5_free_default_realm);\r
+DECL_FUNC_PTR(krb5_free_ticket);\r
+DECL_FUNC_PTR(krb5_decode_ticket);\r
+DECL_FUNC_PTR(krb5_get_host_realm);\r
+DECL_FUNC_PTR(krb5_free_host_realm);\r
+DECL_FUNC_PTR(krb5_free_addresses);\r
+DECL_FUNC_PTR(krb5_c_random_make_octets);\r
+\r
+// ComErr functions\r
+DECL_FUNC_PTR(com_err);\r
+DECL_FUNC_PTR(error_message);\r
+\r
+// Profile functions\r
+DECL_FUNC_PTR(profile_init);\r
+DECL_FUNC_PTR(profile_release);\r
+DECL_FUNC_PTR(profile_get_subsection_names);\r
+DECL_FUNC_PTR(profile_free_list);\r
+DECL_FUNC_PTR(profile_get_string);\r
+DECL_FUNC_PTR(profile_release_string);\r
+\r
+// Service functions\r
+DECL_FUNC_PTR(OpenSCManagerA);\r
+DECL_FUNC_PTR(OpenServiceA);\r
+DECL_FUNC_PTR(QueryServiceStatus);\r
+DECL_FUNC_PTR(CloseServiceHandle);\r
+DECL_FUNC_PTR(LsaNtStatusToWinError);\r
+\r
+// LSA Functions\r
+DECL_FUNC_PTR(LsaConnectUntrusted);\r
+DECL_FUNC_PTR(LsaLookupAuthenticationPackage);\r
+DECL_FUNC_PTR(LsaCallAuthenticationPackage);\r
+DECL_FUNC_PTR(LsaFreeReturnBuffer);\r
+DECL_FUNC_PTR(LsaGetLogonSessionData);\r
+\r
+// CCAPI\r
+FUNC_INFO ccapi_fi[] = {\r
+    MAKE_FUNC_INFO(cc_initialize),\r
+    MAKE_FUNC_INFO(cc_shutdown),\r
+    MAKE_FUNC_INFO(cc_get_NC_info),\r
+    MAKE_FUNC_INFO(cc_free_NC_info),\r
+    END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO leash_fi[] = {\r
+    MAKE_FUNC_INFO(Leash_get_default_lifetime),\r
+    MAKE_FUNC_INFO(Leash_get_default_renew_till),\r
+    MAKE_FUNC_INFO(Leash_get_default_forwardable),\r
+    MAKE_FUNC_INFO(Leash_get_default_noaddresses),\r
+    MAKE_FUNC_INFO(Leash_get_default_proxiable),\r
+    MAKE_FUNC_INFO(Leash_get_default_publicip),\r
+    MAKE_FUNC_INFO(Leash_get_default_use_krb4),\r
+    MAKE_FUNC_INFO(Leash_get_default_life_min),\r
+    MAKE_FUNC_INFO(Leash_get_default_life_max),\r
+    MAKE_FUNC_INFO(Leash_get_default_renew_min),\r
+    MAKE_FUNC_INFO(Leash_get_default_renew_max),\r
+    MAKE_FUNC_INFO(Leash_get_default_renewable),\r
+    END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO leash_opt_fi[] = {\r
+    MAKE_FUNC_INFO(Leash_get_default_mslsa_import),\r
+    END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO k5_fi[] = {\r
+    MAKE_FUNC_INFO(krb5_change_password),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),\r
+    MAKE_FUNC_INFO(krb5_get_init_creds_password),\r
+    MAKE_FUNC_INFO(krb5_build_principal_ext),\r
+    MAKE_FUNC_INFO(krb5_cc_get_name),\r
+    MAKE_FUNC_INFO(krb5_cc_resolve),\r
+    MAKE_FUNC_INFO(krb5_cc_default),\r
+    MAKE_FUNC_INFO(krb5_cc_default_name),\r
+    MAKE_FUNC_INFO(krb5_cc_set_default_name),\r
+    MAKE_FUNC_INFO(krb5_cc_initialize),\r
+    MAKE_FUNC_INFO(krb5_cc_destroy),\r
+    MAKE_FUNC_INFO(krb5_cc_close),\r
+    MAKE_FUNC_INFO(krb5_cc_copy_creds),\r
+    MAKE_FUNC_INFO(krb5_cc_store_cred),\r
+    MAKE_FUNC_INFO(krb5_cc_retrieve_cred),\r
+    MAKE_FUNC_INFO(krb5_cc_get_principal),\r
+    MAKE_FUNC_INFO(krb5_cc_start_seq_get),\r
+    MAKE_FUNC_INFO(krb5_cc_next_cred),\r
+    MAKE_FUNC_INFO(krb5_cc_end_seq_get),\r
+    MAKE_FUNC_INFO(krb5_cc_remove_cred),\r
+    MAKE_FUNC_INFO(krb5_cc_set_flags),\r
+    MAKE_FUNC_INFO(krb5_cc_get_type),\r
+    MAKE_FUNC_INFO(krb5_free_context),\r
+    MAKE_FUNC_INFO(krb5_free_cred_contents),\r
+    MAKE_FUNC_INFO(krb5_free_principal),\r
+    MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),\r
+    MAKE_FUNC_INFO(krb5_init_context),\r
+    MAKE_FUNC_INFO(krb5_parse_name),\r
+    MAKE_FUNC_INFO(krb5_timeofday),\r
+    MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),\r
+    MAKE_FUNC_INFO(krb5_unparse_name),\r
+    MAKE_FUNC_INFO(krb5_get_credentials),\r
+    MAKE_FUNC_INFO(krb5_mk_req),\r
+    MAKE_FUNC_INFO(krb5_sname_to_principal),\r
+    MAKE_FUNC_INFO(krb5_get_credentials_renew),\r
+    MAKE_FUNC_INFO(krb5_free_data),\r
+    MAKE_FUNC_INFO(krb5_free_data_contents),\r
+    MAKE_FUNC_INFO(krb5_free_unparsed_name),\r
+    MAKE_FUNC_INFO(krb5_os_localaddr),\r
+    MAKE_FUNC_INFO(krb5_copy_keyblock_contents),\r
+    MAKE_FUNC_INFO(krb5_copy_data),\r
+    MAKE_FUNC_INFO(krb5_free_creds),\r
+    MAKE_FUNC_INFO(krb5_build_principal),\r
+    MAKE_FUNC_INFO(krb5_get_renewed_creds),\r
+    MAKE_FUNC_INFO(krb5_free_addresses),\r
+    MAKE_FUNC_INFO(krb5_get_default_config_files),\r
+    MAKE_FUNC_INFO(krb5_free_config_files),\r
+    MAKE_FUNC_INFO(krb5_get_default_realm),\r
+    MAKE_FUNC_INFO(krb5_free_default_realm),\r
+    MAKE_FUNC_INFO(krb5_free_ticket),\r
+    MAKE_FUNC_INFO(krb5_decode_ticket),\r
+    MAKE_FUNC_INFO(krb5_get_host_realm),\r
+    MAKE_FUNC_INFO(krb5_free_host_realm),\r
+    MAKE_FUNC_INFO(krb5_free_addresses),\r
+    MAKE_FUNC_INFO(krb5_c_random_make_octets),\r
+    END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO profile_fi[] = {\r
+        MAKE_FUNC_INFO(profile_init),\r
+        MAKE_FUNC_INFO(profile_release),\r
+        MAKE_FUNC_INFO(profile_get_subsection_names),\r
+        MAKE_FUNC_INFO(profile_free_list),\r
+        MAKE_FUNC_INFO(profile_get_string),\r
+        MAKE_FUNC_INFO(profile_release_string),\r
+        END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO ce_fi[] = {\r
+    MAKE_FUNC_INFO(com_err),\r
+    MAKE_FUNC_INFO(error_message),\r
+    END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO service_fi[] = {\r
+    MAKE_FUNC_INFO(OpenSCManagerA),\r
+    MAKE_FUNC_INFO(OpenServiceA),\r
+    MAKE_FUNC_INFO(QueryServiceStatus),\r
+    MAKE_FUNC_INFO(CloseServiceHandle),\r
+    MAKE_FUNC_INFO(LsaNtStatusToWinError),\r
+    END_FUNC_INFO\r
+};\r
+\r
+FUNC_INFO lsa_fi[] = {\r
+    MAKE_FUNC_INFO(LsaConnectUntrusted),\r
+    MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),\r
+    MAKE_FUNC_INFO(LsaCallAuthenticationPackage),\r
+    MAKE_FUNC_INFO(LsaFreeReturnBuffer),\r
+    MAKE_FUNC_INFO(LsaGetLogonSessionData),\r
+    END_FUNC_INFO\r
+};\r
+\r
+/* Static Declarations */\r
+static int       inited = 0;\r
+static HINSTANCE hKrb5 = 0;\r
+static HINSTANCE hKrb524 = 0;\r
+static HINSTANCE hSecur32 = 0;\r
+static HINSTANCE hAdvApi32 = 0;\r
+static HINSTANCE hComErr = 0;\r
+static HINSTANCE hService = 0;\r
+static HINSTANCE hProfile = 0;\r
+static HINSTANCE hLeash = 0;\r
+static HINSTANCE hLeashOpt = 0;\r
+static HINSTANCE hCCAPI = 0;\r
+\r
+static DWORD TraceOption = 0;\r
+static HANDLE hDLL;\r
+\r
+void DebugEvent0(char *a) \r
+{\r
+    HANDLE h; char *ptbuf[1];\r
+    \r
+    h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);\r
+    ptbuf[0] = a;\r
+    ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\r
+    DeregisterEventSource(h);\r
+}\r
+\r
+#define MAXBUF_ 512\r
+void DebugEvent(char *b,...) \r
+{\r
+    HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];\r
+    va_list marker;\r
+\r
+    h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);\r
+    va_start(marker,b);\r
+    StringCbVPrintf(buf, MAXBUF_+1,b,marker);\r
+    buf[MAXBUF_] = '\0';\r
+    ptbuf[0] = buf;\r
+    ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\r
+    DeregisterEventSource(h);\r
+    va_end(marker);\r
+}\r
+\r
+void\r
+UnloadFuncs(\r
+    FUNC_INFO fi[], \r
+    HINSTANCE h\r
+    )\r
+{\r
+    int n;\r
+    if (fi)\r
+        for (n = 0; fi[n].func_ptr_var; n++)\r
+            *(fi[n].func_ptr_var) = 0;\r
+    if (h) FreeLibrary(h);\r
+}\r
+\r
+int\r
+LoadFuncs(\r
+    const char* dll_name, \r
+    FUNC_INFO fi[], \r
+    HINSTANCE* ph,  // [out, optional] - DLL handle\r
+    int* pindex,    // [out, optional] - index of last func loaded (-1 if none)\r
+    int cleanup,    // cleanup function pointers and unload on error\r
+    int go_on,      // continue loading even if some functions cannot be loaded\r
+    int silent      // do not pop-up a system dialog if DLL cannot be loaded\r
+    )\r
+{\r
+    HINSTANCE h;\r
+    int i, n, last_i;\r
+    int error = 0;\r
+    UINT em;\r
+\r
+    if (ph) *ph = 0;\r
+    if (pindex) *pindex = -1;\r
+\r
+    for (n = 0; fi[n].func_ptr_var; n++)\r
+       *(fi[n].func_ptr_var) = 0;\r
+\r
+    if (silent)\r
+       em = SetErrorMode(SEM_FAILCRITICALERRORS);\r
+    h = LoadLibrary(dll_name);\r
+    if (silent)\r
+        SetErrorMode(em);\r
+\r
+    if (!h)\r
+        return 0;\r
+\r
+    last_i = -1;\r
+    for (i = 0; (go_on || !error) && (i < n); i++)\r
+    {\r
+       void* p = (void*)GetProcAddress(h, fi[i].func_name);\r
+       if (!p)\r
+           error = 1;\r
+        else\r
+        {\r
+            last_i = i;\r
+           *(fi[i].func_ptr_var) = p;\r
+        }\r
+    }\r
+    if (pindex) *pindex = last_i;\r
+    if (error && cleanup && !go_on) {\r
+       for (i = 0; i < n; i++) {\r
+           *(fi[i].func_ptr_var) = 0;\r
+       }\r
+       FreeLibrary(h);\r
+       return 0;\r
+    }\r
+    if (ph) *ph = h;\r
+    if (error) return 0;\r
+    return 1;\r
+}\r
+\r
+static HANDLE hInitMutex = NULL;\r
+static BOOL bInit = FALSE;\r
+\r
+/* KFW_initialize cannot be called from DllEntryPoint */\r
+void\r
+KFW_initialize(void)\r
+{\r
+    static int inited = 0;\r
+\r
+    if ( !inited ) {\r
+        char mutexName[MAX_PATH];\r
+        HANDLE hMutex = NULL;\r
+\r
+        sprintf(mutexName, "AFS KFW Init pid=%d", getpid());\r
+        \r
+        hMutex = CreateMutex( NULL, TRUE, mutexName );\r
+        if ( GetLastError() == ERROR_ALREADY_EXISTS ) {\r
+            if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {\r
+                return;\r
+            }\r
+        }\r
+        if ( !inited ) {\r
+            inited = 1;\r
+            LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);\r
+            LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);\r
+            LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);\r
+            LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);\r
+            LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);\r
+            LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);\r
+            LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);\r
+            LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);\r
+        }\r
+        ReleaseMutex(hMutex);\r
+        CloseHandle(hMutex);\r
+    }\r
+}\r
+\r
+void\r
+KFW_cleanup(void)\r
+{\r
+    if (hLeashOpt)\r
+        FreeLibrary(hLeashOpt);\r
+    if (hCCAPI)\r
+        FreeLibrary(hCCAPI);\r
+    if (hLeash)\r
+        FreeLibrary(hLeash);\r
+    if (hKrb524)\r
+        FreeLibrary(hKrb524);\r
+    if (hSecur32)\r
+        FreeLibrary(hSecur32);\r
+    if (hService)\r
+        FreeLibrary(hService);\r
+    if (hComErr)\r
+        FreeLibrary(hComErr);\r
+    if (hProfile)\r
+        FreeLibrary(hProfile);\r
+    if (hKrb5)\r
+        FreeLibrary(hKrb5);\r
+}\r
+\r
+\r
+int \r
+KFW_is_available(void)\r
+{\r
+    KFW_initialize();\r
+    if ( hKrb5 && hComErr && hService && \r
+#ifdef USE_MS2MIT\r
+         hSecur32 && \r
+#endif /* USE_MS2MIT */\r
+         hProfile && hLeash && hCCAPI )\r
+        return TRUE;\r
+\r
+    return FALSE;\r
+}\r
+\r
+/* Given a principal return an existing ccache or create one and return */\r
+int\r
+KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)\r
+{\r
+    krb5_context ctx;\r
+    char * pname = 0;\r
+    char * ccname = 0;\r
+    krb5_error_code code;\r
+\r
+    if (!pkrb5_init_context)\r
+        return 0;\r
+\r
+    if ( alt_ctx ) {\r
+        ctx = alt_ctx;\r
+    } else {\r
+        code = pkrb5_init_context(&ctx);\r
+        if (code) goto cleanup;\r
+    }\r
+\r
+    if ( principal ) {\r
+        code = pkrb5_unparse_name(ctx, principal, &pname);\r
+        if (code) goto cleanup;\r
+\r
+       ccname = (char *)malloc(strlen(pname) + 5);\r
+       sprintf(ccname,"API:%s",pname);\r
+        \r
+       code = pkrb5_cc_resolve(ctx, ccname, cc);\r
+    } else {\r
+        code = pkrb5_cc_default(ctx, cc);\r
+        if (code) goto cleanup;\r
+    }\r
+\r
+  cleanup:\r
+    if (ccname)\r
+        free(ccname);\r
+    if (pname)\r
+        pkrb5_free_unparsed_name(ctx,pname);\r
+    if (ctx && (ctx != alt_ctx))\r
+        pkrb5_free_context(ctx);\r
+    return(code);\r
+}\r
+\r
+\r
+int\r
+KFW_kinit( krb5_context alt_ctx,\r
+            krb5_ccache  alt_cc,\r
+            HWND hParent,\r
+            char *principal_name,\r
+            char *password,\r
+            krb5_deltat lifetime,\r
+            DWORD                       forwardable,\r
+            DWORD                       proxiable,\r
+            krb5_deltat                 renew_life,\r
+            DWORD                       addressless,\r
+            DWORD                       publicIP\r
+            )\r
+{\r
+    krb5_error_code                    code = 0;\r
+    krb5_context                       ctx = 0;\r
+    krb5_ccache                                cc = 0;\r
+    krb5_principal                     me = 0;\r
+    char*                       name = 0;\r
+    krb5_creds                         my_creds;\r
+    krb5_get_init_creds_opt     options;\r
+    krb5_address **             addrs = NULL;\r
+    int                         i = 0, addr_count = 0;\r
+\r
+    if (!pkrb5_init_context)\r
+        return 0;\r
+\r
+    pkrb5_get_init_creds_opt_init(&options);\r
+    memset(&my_creds, 0, sizeof(my_creds));\r
+\r
+    if (alt_ctx)\r
+    {\r
+        ctx = alt_ctx;\r
+    }\r
+    else\r
+    {\r
+        code = pkrb5_init_context(&ctx);\r
+        if (code) goto cleanup;\r
+    }\r
+\r
+    if ( alt_cc ) {\r
+        cc = alt_cc;\r
+    } else {\r
+        code = pkrb5_cc_default(ctx, &cc);  \r
+        if (code) goto cleanup;\r
+    }\r
+\r
+    code = pkrb5_parse_name(ctx, principal_name, &me);\r
+    if (code) \r
+       goto cleanup;\r
+\r
+    code = pkrb5_unparse_name(ctx, me, &name);\r
+    if (code) \r
+       goto cleanup;\r
+\r
+    if (lifetime == 0)\r
+        lifetime = pLeash_get_default_lifetime();\r
+    lifetime *= 60;\r
+\r
+    if (renew_life > 0)\r
+       renew_life *= 60;\r
+\r
+    if (lifetime)\r
+        pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);\r
+       pkrb5_get_init_creds_opt_set_forwardable(&options,\r
+                                                 forwardable ? 1 : 0);\r
+       pkrb5_get_init_creds_opt_set_proxiable(&options,\r
+                                               proxiable ? 1 : 0);\r
+       pkrb5_get_init_creds_opt_set_renew_life(&options,\r
+                                               renew_life);\r
+    if (addressless)\r
+        pkrb5_get_init_creds_opt_set_address_list(&options,NULL);\r
+    else {\r
+       if (publicIP)\r
+        {\r
+            // we are going to add the public IP address specified by the user\r
+            // to the list provided by the operating system\r
+            krb5_address ** local_addrs=NULL;\r
+            DWORD           netIPAddr;\r
+\r
+            pkrb5_os_localaddr(ctx, &local_addrs);\r
+            while ( local_addrs[i++] );\r
+            addr_count = i + 1;\r
+\r
+            addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));\r
+            if ( !addrs ) {\r
+                pkrb5_free_addresses(ctx, local_addrs);\r
+                goto cleanup;\r
+            }\r
+            memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));\r
+            i = 0;\r
+            while ( local_addrs[i] ) {\r
+                addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));\r
+                if (addrs[i] == NULL) {\r
+                    pkrb5_free_addresses(ctx, local_addrs);\r
+                    goto cleanup;\r
+                }\r
+\r
+                addrs[i]->magic = local_addrs[i]->magic;\r
+                addrs[i]->addrtype = local_addrs[i]->addrtype;\r
+                addrs[i]->length = local_addrs[i]->length;\r
+                addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);\r
+                if (!addrs[i]->contents) {\r
+                    pkrb5_free_addresses(ctx, local_addrs);\r
+                    goto cleanup;\r
+                }\r
+\r
+                memcpy(addrs[i]->contents,local_addrs[i]->contents,\r
+                        local_addrs[i]->length);        /* safe */\r
+                i++;\r
+            }\r
+            pkrb5_free_addresses(ctx, local_addrs);\r
+\r
+            addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));\r
+            if (addrs[i] == NULL)\r
+                goto cleanup;\r
+\r
+            addrs[i]->magic = KV5M_ADDRESS;\r
+            addrs[i]->addrtype = AF_INET;\r
+            addrs[i]->length = 4;\r
+            addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);\r
+            if (!addrs[i]->contents)\r
+                goto cleanup;\r
+\r
+            netIPAddr = htonl(publicIP);\r
+            memcpy(addrs[i]->contents,&netIPAddr,4);\r
+        \r
+            pkrb5_get_init_creds_opt_set_address_list(&options,addrs);\r
+\r
+        }\r
+    }\r
+\r
+    code = pkrb5_get_init_creds_password(ctx, \r
+                                       &my_creds, \r
+                                       me,\r
+                                       password, // password\r
+                                       NULL,     // no prompter\r
+                                       hParent, // prompter data\r
+                                       0, // start time\r
+                                       0, // service name\r
+                                       &options);\r
+    if (code) \r
+       goto cleanup;\r
+\r
+    code = pkrb5_cc_initialize(ctx, cc, me);\r
+    if (code) \r
+       goto cleanup;\r
+\r
+    code = pkrb5_cc_store_cred(ctx, cc, &my_creds);\r
+    if (code) \r
+       goto cleanup;\r
+\r
+ cleanup:\r
+    if ( addrs ) {\r
+        for ( i=0;i<addr_count;i++ ) {\r
+            if ( addrs[i] ) {\r
+                if ( addrs[i]->contents )\r
+                    free(addrs[i]->contents);\r
+                free(addrs[i]);\r
+            }\r
+        }\r
+    }\r
+    if (my_creds.client == me)\r
+       my_creds.client = 0;\r
+    pkrb5_free_cred_contents(ctx, &my_creds);\r
+    if (name)\r
+        pkrb5_free_unparsed_name(ctx, name);\r
+    if (me)\r
+        pkrb5_free_principal(ctx, me);\r
+    if (cc && (cc != alt_cc))\r
+        pkrb5_cc_close(ctx, cc);\r
+    if (ctx && (ctx != alt_ctx))\r
+        pkrb5_free_context(ctx);\r
+    return(code);\r
+}\r
+\r
+\r
+int\r
+KFW_get_cred( char * username, \r
+             char * password,\r
+             int lifetime,\r
+             char ** reasonP )\r
+{\r
+    krb5_context ctx = 0;\r
+    krb5_ccache cc = 0;\r
+    char * realm = 0, * userrealm = 0;\r
+    int free_realm = 0;\r
+    krb5_principal principal = 0;\r
+    char * pname = 0;\r
+    krb5_error_code code;\r
+\r
+    if (!pkrb5_init_context)\r
+        return 0;\r
+\r
+    if ( IsDebuggerPresent() ) {\r
+        OutputDebugString("KFW_get_cred for token ");\r
+        OutputDebugString(username);\r
+        OutputDebugString("\n");\r
+    }\r
+\r
+    code = pkrb5_init_context(&ctx);\r
+    if ( code ) goto cleanup;\r
+\r
+    code = pkrb5_get_default_realm(ctx, &realm);\r
+\r
+    userrealm = strchr(username,'@');\r
+    if (realm) {\r
+       free_realm = 1;\r
+        pname = malloc(strlen(username) + strlen(realm) + 2);\r
+        userrealm = strchr(pname, '@');\r
+        userrealm++;\r
+       strcat(userrealm, realm);\r
+    } else {\r
+        pname = strdup(username);\r
+        userrealm = strchr(pname, '@');\r
+        userrealm++;\r
+       realm = userrealm;\r
+    }\r
+    \r
+    if ( IsDebuggerPresent() ) {\r
+        OutputDebugString("Realm: ");\r
+        OutputDebugString(realm);\r
+        OutputDebugString("\n");\r
+    }\r
+\r
+    code = pkrb5_parse_name(ctx, pname, &principal);\r
+    if ( code ) goto cleanup;\r
+\r
+    code = KFW_get_ccache(ctx, principal, &cc);\r
+    if ( code ) goto cleanup;\r
+\r
+    if ( lifetime == 0 )\r
+        lifetime = pLeash_get_default_lifetime();\r
+\r
+    if ( password && password[0] ) {\r
+        code = KFW_kinit( ctx, cc, HWND_DESKTOP, \r
+                          pname, \r
+                          password,\r
+                          lifetime,\r
+                          pLeash_get_default_forwardable(),\r
+                          pLeash_get_default_proxiable(),\r
+                          pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,\r
+                          pLeash_get_default_noaddresses(),\r
+                          pLeash_get_default_publicip());\r
+        if ( IsDebuggerPresent() ) {\r
+            char message[256];\r
+            sprintf(message,"KFW_kinit() returns: %d\n",code);\r
+            OutputDebugString(message);\r
+        }\r
+        if ( code ) goto cleanup;\r
+    }\r
+\r
+  cleanup:\r
+    if ( pname )\r
+        free(pname);\r
+    if ( cc )\r
+        pkrb5_cc_close(ctx, cc);\r
+\r
+    if ( code && reasonP ) {\r
+        *reasonP = (char *)perror_message(code);\r
+    }\r
+    return(code);\r
+}\r
+\r
+void\r
+KFW_copy_cache_to_system_file(char * user, char * szLogonId)\r
+{\r
+    char filename[256];\r
+    DWORD count;\r
+    char cachename[264] = "FILE:";\r
+    krb5_context               ctx = 0;\r
+    krb5_error_code            code;\r
+    krb5_principal              princ = 0;\r
+    krb5_ccache                        cc  = 0;\r
+    krb5_ccache                 ncc = 0;\r
+\r
+    if (!pkrb5_init_context)\r
+        return;\r
+\r
+    count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));\r
+    if ( count > sizeof(filename) || count == 0 ) {\r
+        GetWindowsDirectory(filename, sizeof(filename));\r
+    }\r
+\r
+    if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )\r
+        return;\r
+\r
+    strcat(filename, "\\");\r
+    strcat(filename, szLogonId);    \r
+\r
+    strcat(cachename, filename);\r
+\r
+    DeleteFile(filename);\r
+\r
+    code = pkrb5_init_context(&ctx);\r
+    if (code) ctx = 0;\r
+\r
+    code = pkrb5_parse_name(ctx, user, &princ);\r
+    if (code) goto cleanup;\r
+\r
+    code = KFW_get_ccache(ctx, princ, &cc);\r
+    if (code) goto cleanup;\r
+\r
+    code = pkrb5_cc_resolve(ctx, cachename, &ncc);\r
+    if (code) goto cleanup;\r
+\r
+    code = pkrb5_cc_initialize(ctx, ncc, princ);\r
+    if (code) goto cleanup;\r
+\r
+    code = pkrb5_cc_copy_creds(ctx,cc,ncc);\r
+\r
+  cleanup:\r
+    if ( cc ) {\r
+        pkrb5_cc_close(ctx, cc);\r
+        cc = 0;\r
+    }\r
+    if ( ncc ) {\r
+        pkrb5_cc_close(ctx, ncc);\r
+        ncc = 0;\r
+    }\r
+    if ( princ ) {\r
+        pkrb5_free_principal(ctx, princ);\r
+        princ = 0;\r
+    }\r
+\r
+    if (ctx)\r
+        pkrb5_free_context(ctx);\r
+}\r
+\r
+int\r
+KFW_copy_system_file_to_default_cache(char * filename)\r
+{\r
+    char cachename[264] = "FILE:";\r
+    krb5_context               ctx = 0;\r
+    krb5_error_code            code;\r
+    krb5_principal              princ = 0;\r
+    krb5_ccache                        cc  = 0;\r
+    krb5_ccache                 ncc = 0;\r
+    int retval = 1;\r
+\r
+    if (!pkrb5_init_context)\r
+        return 1;\r
+\r
+    if ( strlen(filename) + 6 > sizeof(cachename) )\r
+        return 1;\r
+\r
+    strcat(cachename, filename);\r
+\r
+    code = pkrb5_init_context(&ctx);\r
+    if (code) ctx = 0;\r
+\r
+    code = pkrb5_cc_resolve(ctx, cachename, &cc);\r
+    if (code) goto cleanup;\r
+    \r
+    code = pkrb5_cc_get_principal(ctx, cc, &princ);\r
+    if (code) goto cleanup;\r
+\r
+    code = pkrb5_cc_default(ctx, &ncc);\r
+    if (!code) {\r
+        code = pkrb5_cc_initialize(ctx, ncc, princ);\r
+\r
+        if (!code)\r
+            code = pkrb5_cc_copy_creds(ctx,cc,ncc);\r
+    }\r
+    if ( ncc ) {\r
+        pkrb5_cc_close(ctx, ncc);\r
+        ncc = 0;\r
+    }\r
+\r
+    retval=0;   /* success */\r
+\r
+  cleanup:\r
+    if ( cc ) {\r
+        pkrb5_cc_close(ctx, cc);\r
+        cc = 0;\r
+    }\r
+\r
+    DeleteFile(filename);\r
+\r
+    if ( princ ) {\r
+        pkrb5_free_principal(ctx, princ);\r
+        princ = 0;\r
+    }\r
+\r
+    if (ctx)\r
+        pkrb5_free_context(ctx);\r
+\r
+    return 0;\r
+}\r
+\r
+\r
+int \r
+KFW_destroy_tickets_for_principal(char * user)\r
+{\r
+    krb5_context               ctx = 0;\r
+    krb5_error_code            code;\r
+    krb5_principal      princ = 0;\r
+    krb5_ccache                        cc  = 0;\r
+\r
+    if (!pkrb5_init_context)\r
+        return 0;\r
+\r
+    if ( IsDebuggerPresent() ) {\r
+        OutputDebugString("KFW_destroy_tickets_for_user: ");\r
+        OutputDebugString(user);\r
+        OutputDebugString("\n");\r
+    }\r
+\r
+    code = pkrb5_init_context(&ctx);\r
+    if (code) ctx = 0;\r
+\r
+    code = pkrb5_parse_name(ctx, user, &princ);\r
+    if (code) goto loop_cleanup;\r
+\r
+    code = KFW_get_ccache(ctx, princ, &cc);\r
+    if (code) goto loop_cleanup;\r
+\r
+    code = pkrb5_cc_destroy(ctx, cc);\r
+    if (!code) cc = 0;\r
+\r
+  loop_cleanup:\r
+    if ( cc ) {\r
+        pkrb5_cc_close(ctx, cc);\r
+        cc = 0;\r
+    }\r
+    if ( princ ) {\r
+        pkrb5_free_principal(ctx, princ);\r
+        princ = 0;\r
+    }\r
+\r
+    pkrb5_free_context(ctx);\r
+    return 0;\r
+}\r
+\r
diff --git a/src/windows/kfwlogon/kfwcpcc.c b/src/windows/kfwlogon/kfwcpcc.c
new file mode 100644 (file)
index 0000000..4dbace9
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+\r
+Copyright 2005 by the Massachusetts Institute of Technology\r
+\r
+All rights reserved.\r
+\r
+Permission to use, copy, modify, and distribute this software and its\r
+documentation for any purpose and without fee is hereby granted,\r
+provided that the above copyright notice appear in all copies and that\r
+both that copyright notice and this permission notice appear in\r
+supporting documentation, and that the name of the Massachusetts\r
+Institute of Technology (M.I.T.) not be used in advertising or publicity\r
+pertaining to distribution of the software without specific, written\r
+prior permission.\r
+\r
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+SOFTWARE.\r
+\r
+*/\r
+\r
+#include <windows.h>\r
+#include "kfwlogon.h"\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+    if ( argc != 2 )\r
+        return 1;\r
+\r
+    KFW_initialize();\r
+\r
+    return KFW_copy_system_file_to_default_cache(argv[1]);\r
+}\r
+\r
+\r
diff --git a/src/windows/kfwlogon/kfwcpcc.rc b/src/windows/kfwlogon/kfwcpcc.rc
new file mode 100644 (file)
index 0000000..5b0bbf2
--- /dev/null
@@ -0,0 +1,10 @@
+#include <windows.h>\r
+#include <winver.h>\r
+#include "patchlevel.h"\r
+\r
+#define K5_DESCRIPTION "Kerberos for Windows Logon Network Provider\0"\r
+#define K5_FILETYPE    VFT_APP\r
+#define K5_INTERNAL_NAME "KFWLOGON\0"\r
+#define K5_ORIGINAL_NAME "kfwcpcc.exe\0"\r
+\r
+#include "..\version.rc"\r
diff --git a/src/windows/kfwlogon/kfwlogon.c b/src/windows/kfwlogon/kfwlogon.c
new file mode 100644 (file)
index 0000000..70b6234
--- /dev/null
@@ -0,0 +1,344 @@
+/*\r
+Copyright 2005 by the Massachusetts Institute of Technology\r
+\r
+All rights reserved.\r
+\r
+Permission to use, copy, modify, and distribute this software and its\r
+documentation for any purpose and without fee is hereby granted,\r
+provided that the above copyright notice appear in all copies and that\r
+both that copyright notice and this permission notice appear in\r
+supporting documentation, and that the name of the Massachusetts\r
+Institute of Technology (M.I.T.) not be used in advertising or publicity\r
+pertaining to distribution of the software without specific, written\r
+prior permission.\r
+\r
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+SOFTWARE.\r
+\r
+*/\r
+\r
+#include "kfwlogon.h"\r
+\r
+#include <io.h>\r
+#include <sys/stat.h>\r
+#include <sys/types.h>\r
+#include <fcntl.h>\r
+\r
+#include <winsock2.h>\r
+#include <lm.h>\r
+#include <nb30.h>\r
+\r
+static HANDLE hDLL;\r
+\r
+static HANDLE hInitMutex = NULL;\r
+static BOOL bInit = FALSE;\r
+\r
+\r
+BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)\r
+{\r
+    hDLL = dll;\r
+    switch (reason) {\r
+    case DLL_PROCESS_ATTACH:\r
+        /* Initialization Mutex */\r
+        hInitMutex = CreateMutex(NULL, FALSE, NULL);\r
+        break;\r
+\r
+    case DLL_PROCESS_DETACH:\r
+        CloseHandle(hInitMutex);\r
+        break;\r
+\r
+    case DLL_THREAD_ATTACH:\r
+    case DLL_THREAD_DETACH:\r
+    default:\r
+        /* Everything else succeeds but does nothing. */\r
+        break;\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+\r
+\r
+DWORD APIENTRY NPGetCaps(DWORD index)\r
+{\r
+    switch (index) {\r
+    case WNNC_NET_TYPE:\r
+        /* Don't have our own type; use somebody else's. */\r
+        return WNNC_NET_SUN_PC_NFS;\r
+\r
+    case WNNC_START:\r
+        /* Say we are already started, even though we might wait after we receive NPLogonNotify */\r
+        return 1;\r
+\r
+    default:\r
+        return 0;\r
+    }\r
+}       \r
+\r
+static BOOL\r
+WINAPI\r
+UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)\r
+{\r
+    CPINFO CodePageInfo;\r
+\r
+    GetCPInfo(CP_ACP, &CodePageInfo);\r
+\r
+    if (CodePageInfo.MaxCharSize > 1)\r
+        // Only supporting non-Unicode strings\r
+        return FALSE;\r
+    \r
+    if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')\r
+    {\r
+        // Looks like unicode, better translate it\r
+        // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS\r
+        WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,\r
+                            lpszOutputString, nOutStringLen-1, NULL, NULL);\r
+        lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';\r
+        return TRUE;\r
+    }\r
+    else\r
+        lpszOutputString[0] = '\0';\r
+    return FALSE;\r
+}  // UnicodeStringToANSI\r
+\r
+\r
+DWORD APIENTRY NPLogonNotify(\r
+       PLUID lpLogonId,\r
+       LPCWSTR lpAuthentInfoType,\r
+       LPVOID lpAuthentInfo,\r
+       LPCWSTR lpPreviousAuthentInfoType,\r
+       LPVOID lpPreviousAuthentInfo,\r
+       LPWSTR lpStationName,\r
+       LPVOID StationHandle,\r
+       LPWSTR *lpLogonScript)\r
+{\r
+    char uname[MAX_USERNAME_LENGTH]="";\r
+    char password[MAX_PASSWORD_LENGTH]="";\r
+    char logonDomain[MAX_DOMAIN_LENGTH]="";\r
+    char szLogonId[128] = "";\r
+\r
+    MSV1_0_INTERACTIVE_LOGON *IL;\r
+\r
+    DWORD code = 0;\r
+\r
+    char *reason;\r
+    char *ctemp;\r
+\r
+    BOOLEAN interactive;\r
+    HWND hwndOwner = (HWND)StationHandle;\r
+    BOOLEAN lowercased_name = TRUE;\r
+\r
+    if ( !KFW_is_available() )\r
+       return 0;\r
+\r
+    DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);\r
+\r
+    /* Initialize Logon Script to none */\r
+    *lpLogonScript=NULL;\r
+    \r
+    /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for\r
+     * our purposes */\r
+\r
+    if ( wcscmp(lpAuthentInfoType,L"MSV1_0:Interactive") && \r
+         wcscmp(lpAuthentInfoType,L"Kerberos:Interactive") )\r
+    {\r
+        DebugEvent("Unsupported Authentication Info Type: %S",\r
+                   lpAuthentInfoType);\r
+        return 0;\r
+    }\r
+\r
+    IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;\r
+\r
+    /* Are we interactive? */\r
+    interactive = (wcscmp(lpStationName, L"WinSta0") == 0);\r
+\r
+    /* Convert from Unicode to ANSI */\r
+\r
+    /*TODO: Use SecureZeroMemory to erase passwords */\r
+    UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH);\r
+    UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH);\r
+    UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH);\r
+\r
+    /* Make sure AD-DOMANS sent from login that is sent to us is stripped */\r
+    ctemp = strchr(uname, '@');\r
+    if (ctemp) *ctemp = 0;\r
+\r
+    /* is the name all lowercase? */\r
+    for ( ctemp = uname; *ctemp ; ctemp++) {\r
+        if ( !islower(*ctemp) ) {\r
+            lowercased_name = FALSE;\r
+            break;\r
+        }\r
+    }\r
+\r
+    code = KFW_get_cred(uname, password, 0, &reason);\r
+    DebugEvent("KFW_get_cred  uname=[%s] code=[%d]",uname, code);\r
+    \r
+    /* remove any kerberos 5 tickets currently held by the SYSTEM account\r
+     * for this user \r
+     */\r
+    sprintf(szLogonId,"kfwlogon-%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);\r
+    KFW_copy_cache_to_system_file(uname, szLogonId);\r
+\r
+    KFW_destroy_tickets_for_principal(uname);\r
+\r
+    if (code) {\r
+        char msg[128];\r
+        HANDLE h;\r
+        char *ptbuf[1];\r
+\r
+        StringCbPrintf(msg, sizeof(msg), "Kerberos ticket acquisition failed: %s", reason);\r
+\r
+        h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);\r
+        ptbuf[0] = msg;\r
+        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,\r
+                     1, 0, ptbuf, NULL);\r
+        DeregisterEventSource(h);\r
+        SetLastError(code);\r
+    }\r
+\r
+    return code;\r
+}       \r
+\r
+\r
+DWORD APIENTRY NPPasswordChangeNotify(\r
+       LPCWSTR lpAuthentInfoType,\r
+       LPVOID lpAuthentInfo,\r
+       LPCWSTR lpPreviousAuthentInfoType,\r
+       LPVOID lpPreviousAuthentInfo,\r
+       LPWSTR lpStationName,\r
+       LPVOID StationHandle,\r
+       DWORD dwChangeInfo)\r
+{\r
+    return 0;\r
+}\r
+\r
+#include <userenv.h>\r
+#include <Winwlx.h>\r
+\r
+#ifdef COMMENT\r
+typedef struct _WLX_NOTIFICATION_INFO {  \r
+    ULONG Size;  \r
+    ULONG Flags;  \r
+    PWSTR UserName;  \r
+    PWSTR Domain;  \r
+    PWSTR WindowStation;  \r
+    HANDLE hToken;  \r
+    HDESK hDesktop;  \r
+    PFNMSGECALLBACK pStatusCallback;\r
+} WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;\r
+#endif\r
+\r
+VOID KFW_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )\r
+{\r
+    DebugEvent0("KFW_Startup_Event");\r
+}\r
+\r
+static BOOL\r
+GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)\r
+{\r
+    NTSTATUS Status = 0;\r
+#if 0\r
+    HANDLE  TokenHandle;\r
+#endif\r
+    TOKEN_STATISTICS Stats;\r
+    DWORD   ReqLen;\r
+    BOOL    Success;\r
+\r
+    if (!ppSessionData)\r
+        return FALSE;\r
+    *ppSessionData = NULL;\r
+\r
+#if 0\r
+    Success = OpenProcessToken( HANDLE GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );\r
+    if ( !Success )\r
+        return FALSE;\r
+#endif\r
+\r
+    Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );\r
+#if 0\r
+    CloseHandle( TokenHandle );\r
+#endif\r
+    if ( !Success )\r
+        return FALSE;\r
+\r
+    Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );\r
+    if ( FAILED(Status) || !ppSessionData )\r
+        return FALSE;\r
+\r
+    return TRUE;\r
+}\r
+\r
+VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )\r
+{\r
+    WCHAR szUserW[128] = L"";\r
+    char  szUserA[128] = "";\r
+    char szPath[MAX_PATH] = "";\r
+    char szLogonId[128] = "";\r
+    DWORD count;\r
+    char filename[256];\r
+    char commandline[512];\r
+    STARTUPINFO startupinfo;\r
+    PROCESS_INFORMATION procinfo;\r
+\r
+    LUID LogonId = {0, 0};\r
+    PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;\r
+\r
+    HKEY hKey1 = NULL, hKey2 = NULL;\r
+\r
+    DebugEvent0("KFW_Logon_Event - Start");\r
+\r
+    GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );\r
+\r
+    if ( pLogonSessionData ) {\r
+        LogonId = pLogonSessionData->LogonId;\r
+        DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);\r
+\r
+        sprintf(szLogonId,"kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart);\r
+        LsaFreeReturnBuffer( pLogonSessionData );\r
+    } else {\r
+        DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");\r
+        return;\r
+    }\r
+\r
+    count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));\r
+    if ( count > sizeof(filename) || count == 0 ) {\r
+        GetWindowsDirectory(filename, sizeof(filename));\r
+    }\r
+\r
+    if ( strlen(filename) + strlen(szLogonId) + 2 <= sizeof(filename) ) {\r
+        strcat(filename, "\\");\r
+        strcat(filename, szLogonId);    \r
+\r
+        sprintf(commandline, "kfwcpcc.exe \"%s\"", filename);\r
+\r
+        GetStartupInfo(&startupinfo);\r
+        if (CreateProcessAsUser( pInfo->hToken,\r
+                             "kfwcpcc.exe",\r
+                             commandline,\r
+                             NULL,\r
+                             NULL,\r
+                             FALSE,\r
+                             CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,\r
+                             NULL,\r
+                             NULL,\r
+                             &startupinfo,\r
+                             &procinfo)) \r
+        {\r
+            WaitForSingleObject(procinfo.hProcess, 30000);\r
+\r
+            CloseHandle(procinfo.hThread);\r
+            CloseHandle(procinfo.hProcess);\r
+        }\r
+    }\r
+\r
+    DeleteFile(filename);\r
+\r
+    DebugEvent0("KFW_Logon_Event - End");\r
+}\r
+\r
diff --git a/src/windows/kfwlogon/kfwlogon.def b/src/windows/kfwlogon/kfwlogon.def
new file mode 100644 (file)
index 0000000..52af990
--- /dev/null
@@ -0,0 +1,12 @@
+LIBRARY KFWLOGON\r
+\r
+EXPORTS\r
+\r
+    DllEntryPoint\r
+    NPGetCaps\r
+    NPLogonNotify\r
+    NPPasswordChangeNotify\r
+    KFW_Logon_Event\r
+\r
+\r
+\r
diff --git a/src/windows/kfwlogon/kfwlogon.h b/src/windows/kfwlogon/kfwlogon.h
new file mode 100644 (file)
index 0000000..34c8cc7
--- /dev/null
@@ -0,0 +1,200 @@
+/*\r
+\r
+Copyright 2005 by the Massachusetts Institute of Technology\r
+\r
+All rights reserved.\r
+\r
+Permission to use, copy, modify, and distribute this software and its\r
+documentation for any purpose and without fee is hereby granted,\r
+provided that the above copyright notice appear in all copies and that\r
+both that copyright notice and this permission notice appear in\r
+supporting documentation, and that the name of the Massachusetts\r
+Institute of Technology (M.I.T.) not be used in advertising or publicity\r
+pertaining to distribution of the software without specific, written\r
+prior permission.\r
+\r
+M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
+M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+SOFTWARE.\r
+\r
+*/\r
+\r
+/* We only support VC 1200 and above anyway */\r
+#pragma once\r
+\r
+#ifndef _WIN32_WINNT\r
+#define _WIN32_WINNT 0x0500\r
+#endif\r
+\r
+#include <windows.h>\r
+#include <npapi.h>\r
+#define SECURITY_WIN32\r
+#include <security.h>\r
+#include <ntsecapi.h>\r
+#include <tchar.h>\r
+#include <strsafe.h>\r
+\r
+typedef int errcode_t;\r
+\r
+#include <loadfuncs-lsa.h>\r
+#include <krb5.h>\r
+#include <loadfuncs-com_err.h>\r
+#include <loadfuncs-krb5.h>\r
+#include <loadfuncs-profile.h>\r
+#include <loadfuncs-leash.h>\r
+\r
+// service definitions\r
+#define SERVICE_DLL   "advapi32.dll"\r
+typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);\r
+typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);\r
+typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);\r
+typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);\r
+\r
+/* In order to avoid including the private CCAPI headers */\r
+typedef int cc_int32;\r
+\r
+#define CC_API_VER_1 1\r
+#define CC_API_VER_2 2\r
+\r
+#define CCACHE_API cc_int32\r
+\r
+/*\r
+** The Official Error Codes\r
+*/\r
+#define CC_NOERROR           0\r
+#define CC_BADNAME           1\r
+#define CC_NOTFOUND          2\r
+#define CC_END               3\r
+#define CC_IO                4\r
+#define CC_WRITE             5\r
+#define CC_NOMEM             6\r
+#define CC_FORMAT            7\r
+#define CC_LOCKED            8\r
+#define CC_BAD_API_VERSION   9\r
+#define CC_NO_EXIST          10\r
+#define CC_NOT_SUPP          11\r
+#define CC_BAD_PARM          12\r
+#define CC_ERR_CACHE_ATTACH  13\r
+#define CC_ERR_CACHE_RELEASE 14\r
+#define CC_ERR_CACHE_FULL    15\r
+#define CC_ERR_CRED_VERSION  16\r
+\r
+enum {\r
+    CC_CRED_VUNKNOWN = 0,       // For validation\r
+    CC_CRED_V4 = 1,\r
+    CC_CRED_V5 = 2,\r
+    CC_CRED_VMAX = 3            // For validation\r
+};\r
+\r
+typedef struct opaque_dll_control_block_type* apiCB;\r
+typedef struct _infoNC {\r
+    char*     name;\r
+    char*     principal;\r
+    cc_int32  vers;\r
+} infoNC;\r
+\r
+TYPEDEF_FUNC(\r
+CCACHE_API,\r
+CALLCONV_C,\r
+cc_initialize,\r
+    (\r
+    apiCB** cc_ctx,           // <  DLL's primary control structure.\r
+                              //    returned here, passed everywhere else\r
+    cc_int32 api_version,     // >  ver supported by caller (use CC_API_VER_1)\r
+    cc_int32*  api_supported, // <  if ~NULL, max ver supported by DLL\r
+    const char** vendor       // <  if ~NULL, vendor name in read only C string\r
+    )\r
+);\r
+\r
+TYPEDEF_FUNC(\r
+CCACHE_API,\r
+CALLCONV_C,\r
+cc_shutdown,\r
+    (\r
+    apiCB** cc_ctx            // <> DLL's primary control structure. NULL after\r
+    )\r
+);\r
+\r
+TYPEDEF_FUNC(\r
+CCACHE_API,\r
+CALLCONV_C,\r
+cc_get_NC_info,\r
+    (\r
+    apiCB* cc_ctx,          // >  DLL's primary control structure\r
+    struct _infoNC*** ppNCi // <  (NULL before call) null terminated,\r
+                            //    list of a structs (free via cc_free_infoNC())\r
+    )\r
+);\r
+\r
+TYPEDEF_FUNC(\r
+CCACHE_API,\r
+CALLCONV_C,\r
+cc_free_NC_info,\r
+    (\r
+    apiCB* cc_ctx,\r
+    struct _infoNC*** ppNCi // <  free list of structs returned by\r
+                            //    cc_get_cache_names().  set to NULL on return\r
+    )\r
+);\r
+/* End private ccapiv2 headers */\r
+\r
+#define CCAPI_DLL   "krbcc32.dll"\r
+\r
+\r
+/* */\r
+#define MAX_USERNAME_LENGTH 256\r
+#define MAX_PASSWORD_LENGTH 256\r
+#define MAX_DOMAIN_LENGTH 256\r
+\r
+#define KFW_LOGON_EVENT_NAME TEXT("KFW Logon")\r
+\r
+BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved);\r
+\r
+DWORD APIENTRY NPGetCaps(DWORD index);\r
+\r
+DWORD APIENTRY NPLogonNotify(\r
+       PLUID lpLogonId,\r
+       LPCWSTR lpAuthentInfoType,\r
+       LPVOID lpAuthentInfo,\r
+       LPCWSTR lpPreviousAuthentInfoType,\r
+       LPVOID lpPreviousAuthentInfo,\r
+       LPWSTR lpStationName,\r
+       LPVOID StationHandle,\r
+       LPWSTR *lpLogonScript);\r
+\r
+DWORD APIENTRY NPPasswordChangeNotify(\r
+       LPCWSTR lpAuthentInfoType,\r
+       LPVOID lpAuthentInfo,\r
+       LPCWSTR lpPreviousAuthentInfoType,\r
+       LPVOID lpPreviousAuthentInfo,\r
+       LPWSTR lpStationName,\r
+       LPVOID StationHandle,\r
+       DWORD dwChangeInfo);\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+void UnloadFuncs(FUNC_INFO [], HINSTANCE);\r
+\r
+int  LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int);\r
+\r
+void DebugEvent0(char *a);\r
+void DebugEvent(char *b,...);\r
+\r
+DWORD MapAuthError(DWORD code);\r
+\r
+static BOOL WINAPI UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen);\r
+\r
+int KFW_is_available(void);\r
+int KFW_get_cred( char * username, char * password, int lifetime, char ** reasonP );\r
+void KFW_copy_cache_to_system_file(char * user, char * szLogonId);\r
+int KFW_destroy_tickets_for_principal(char * user);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/src/windows/kfwlogon/kfwlogon.rc b/src/windows/kfwlogon/kfwlogon.rc
new file mode 100644 (file)
index 0000000..1a3cb15
--- /dev/null
@@ -0,0 +1,10 @@
+#include <windows.h>\r
+#include <winver.h>\r
+#include "patchlevel.h"\r
+\r
+#define K5_DESCRIPTION "Kerberos for Windows Logon Network Provider\0"\r
+#define K5_FILETYPE    VFT_DLL\r
+#define K5_INTERNAL_NAME "KFWLOGON\0"\r
+#define K5_ORIGINAL_NAME "kfwlogon.dll\0"\r
+\r
+#include "..\version.rc"\r