KFW Logon Network Provider
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 29 Nov 2005 22:22:43 +0000 (22:22 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 29 Nov 2005 22:22:43 +0000 (22:22 +0000)
The Logon Network Provider works like the OpenAFS Integrated
Logon.  It uses the username entered by the user and the
default realm obtained from krb5.ini and the user entered
password.  If possible, tickets are obtained and imported
into the user's CCAPI credential cache.

ticket: new
component: windows
target_version: 1.4.4
status: resolved
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17518 dc483132-0cff-0310-8789-dd5450dbe970

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 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