--- /dev/null
+/*\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
--- /dev/null
+/*\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