# License. For details, see the LICENSE file in the top-level source
# directory or online at http://www.openafs.org/dl/license10.html
-AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL"
+AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" -I..\kfw\inc\loadfuncs -I..\kfw\inc\krb5 -I..\kfw\inc\leash
AFSDEV_NETGUI = 1
RELDIR=WINNT\afsd
!INCLUDE ..\..\config\NTMakefile.$(SYS_NAME)
$(INCFILEDIR)\cm_buf.h \
$(INCFILEDIR)\cm_freelance.h \
$(INCFILEDIR)\afsd_eventlog.h \
- $(INCFILEDIR)\afsd_eventmessages.h
+ $(INCFILEDIR)\afsd_eventmessages.h \
+ $(INCFILEDIR)\afskfw.h
IDLFILES =\
afsrpc.h $(OUT)\afsrpc_c.obj
$(COPY) $*.lib $(ILIBDIR)
$(DEL) $*.lib $*.exp
+############################################################################
+# lanahelper.lib
+
+LANAHELPERLIB = $(DESTDIR)\lib\lanahelper.lib
+
+LANAHELPERLIB_OBJS =\
+ $(OUT)\lanahelper.obj
+
+$(LANAHELPERLIB_OBJS):
+
+$(LANAHELPERLIB): $(LANAHELPERLIB_OBJS)
+ $(LIBARCH) netapi32.lib
+
+############################################################################
+# afskfw.lib
+
+AFSKFWLIB = $(DESTDIR)\lib\afskfw.lib
+
+AFSKFWLIB_OBJS =\
+ $(OUT)\afskfw.obj
+
+$(AFSKFWLIB_OBJS):
+
+$(AFSKFWLIB): $(AFSKFWLIB_OBJS)
+ $(LIBARCH)
+
############################################################################
# afslogon.dll
LOGON_DLLLIBS =\
$(DESTDIR)\lib\afsauthent.lib \
- $(DESTDIR)\lib\libafsconf.lib
+ $(DESTDIR)\lib\libafsconf.lib \
+ $(DESTDIR)\lib\afsrxkad.lib \
+ $(DESTDIR)\lib\afsdes.lib \
+ $(AFSKFWLIB)
$(LOGON_DLLFILE): $(LOGON_DLLOBJS) $(LOGON_DLLLIBS)
$(DLLGUILINK) $(LOGONLINKFLAGS) -def:afslogon.def dnsapi.lib secur32.lib
$(COPY) $*.lib $(DESTDIR)\lib
$(DEL) $*.lib $*.exp
-############################################################################
-# lanahelper.lib
-
-LANAHELPERLIB = $(DESTDIR)\lib\lanahelper.lib
-
-LANAHELPERLIB_OBJS =\
- $(OUT)\lanahelper.obj
-
-$(LANAHELPERLIB_OBJS):
-
-$(LANAHELPERLIB): $(LANAHELPERLIB_OBJS)
- $(LIBARCH) netapi32.lib
-
############################################################################
# Install target; primary makefile target
--- /dev/null
+/*
+ * Copyright (c) 2003 SkyRope, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Skyrope, LLC nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission from Skyrope, LLC.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Portions of this code are derived from portions of the MIT
+ * Leash Ticket Manager and LoadFuncs utilities. For these portions the
+ * following copyright applies.
+ *
+ * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#ifndef AFSKRB5_INT_H
+#define AFSKRB5_INT_H
+
+#include <windows.h>
+#ifdef USE_MS2MIT
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+#endif /* USE_MS2MIT */
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <winsock2.h>
+
+#ifdef USE_MS2MIT
+#include <loadfuncs-lsa.h>
+#endif /* USE_MS2MIT */
+
+#include <afs/stds.h>
+#include <krb5.h>
+
+#include <rxkad.h>
+
+/* Defined in the KRBV4W32 version of krb.h but not the Kerberos V version */
+/* Required for some of the loadfuncs headers */
+typedef struct ktext far *KTEXT;
+typedef struct ktext far *KTEXT_FP;
+#include <KerberosIV/krb.h>
+
+/* AFS has its own version of com_err.h */
+typedef afs_int32 errcode_t;
+
+#include <loadfuncs-com_err.h>
+#include <loadfuncs-krb5.h>
+#include <loadfuncs-profile.h>
+#include <loadfuncs-krb.h>
+#include <loadfuncs-krb524.h>
+#include <loadfuncs-afs36.h>
+#include <loadfuncs-leash.h>
+
+// service definitions
+#define SERVICE_DLL "advapi32.dll"
+typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
+typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
+typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
+
+#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
+#define LSA_CCNAME "MSLSA:"
+
+#define KTC_ERROR 11862784L
+#define KTC_TOOBIG 11862785L
+#define KTC_INVAL 11862786L
+#define KTC_NOENT 11862787L
+#define KTC_PIOCTLFAIL 11862788L
+#define KTC_NOPIOCTL 11862789L
+#define KTC_NOCELL 11862790L
+#define KTC_NOCM 11862791L
+
+/* User Query data structures and functions */
+
+struct textField {
+ char * buf; /* Destination buffer address */
+ int len; /* Destination buffer length */
+ char * label; /* Label for this field */
+ char * def; /* Default response for this field */
+ int echo; /* 0 = no, 1 = yes, 2 = asterisks */
+};
+
+#define ID_TEXT 150
+#define ID_MID_TEXT 300
+
+struct principal_ccache_data {
+ struct principal_ccache_data * next;
+ char * principal;
+ char * ccache_name;
+ int from_lsa;
+ int expired;
+ int expiration_time;
+ int renew;
+};
+
+struct cell_principal_map {
+ struct cell_principal_map * next;
+ char * cell;
+ char * principal;
+ int active;
+};
+
+/* In order to avoid including the private CCAPI headers */
+typedef int cc_int32;
+
+#define CC_API_VER_1 1
+#define CC_API_VER_2 2
+
+#define CCACHE_API cc_int32
+
+/*
+** The Official Error Codes
+*/
+#define CC_NOERROR 0
+#define CC_BADNAME 1
+#define CC_NOTFOUND 2
+#define CC_END 3
+#define CC_IO 4
+#define CC_WRITE 5
+#define CC_NOMEM 6
+#define CC_FORMAT 7
+#define CC_LOCKED 8
+#define CC_BAD_API_VERSION 9
+#define CC_NO_EXIST 10
+#define CC_NOT_SUPP 11
+#define CC_BAD_PARM 12
+#define CC_ERR_CACHE_ATTACH 13
+#define CC_ERR_CACHE_RELEASE 14
+#define CC_ERR_CACHE_FULL 15
+#define CC_ERR_CRED_VERSION 16
+
+enum {
+ CC_CRED_VUNKNOWN = 0, // For validation
+ CC_CRED_V4 = 1,
+ CC_CRED_V5 = 2,
+ CC_CRED_VMAX = 3 // For validation
+};
+
+typedef struct opaque_dll_control_block_type* apiCB;
+typedef struct _infoNC {
+ char* name;
+ char* principal;
+ cc_int32 vers;
+} infoNC;
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_initialize,
+ (
+ apiCB** cc_ctx, // < DLL's primary control structure.
+ // returned here, passed everywhere else
+ cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
+ cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
+ const char** vendor // < if ~NULL, vendor name in read only C string
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_shutdown,
+ (
+ apiCB** cc_ctx // <> DLL's primary control structure. NULL after
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_get_NC_info,
+ (
+ apiCB* cc_ctx, // > DLL's primary control structure
+ struct _infoNC*** ppNCi // < (NULL before call) null terminated,
+ // list of a structs (free via cc_free_infoNC())
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_free_NC_info,
+ (
+ apiCB* cc_ctx,
+ struct _infoNC*** ppNCi // < free list of structs returned by
+ // cc_get_cache_names(). set to NULL on return
+ )
+);
+#define CCAPI_DLL "krbcc32.dll"
+
+/* Function Prototypes */
+DWORD GetServiceStatus(LPSTR, LPSTR, DWORD *);
+void KFW_AFS_error(LONG, LPCSTR);
+
+void UnloadFuncs(FUNC_INFO [], HINSTANCE);
+int LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int);
+int KFW_get_ccache(krb5_context, krb5_principal, krb5_ccache *);
+int KFW_error(krb5_error_code, LPCSTR, int, krb5_context *, krb5_ccache *);
+int KFW_kinit(krb5_context, krb5_ccache, HWND, char *, char *, krb5_deltat,
+ DWORD, DWORD, krb5_deltat, DWORD, DWORD);
+int KFW_renew(krb5_context, krb5_ccache);
+int KFW_destroy(krb5_context, krb5_ccache);
+BOOL KFW_ms2mit(krb5_context, krb5_ccache, BOOL);
+int KFW_AFS_unlog(void);
+int KFW_AFS_klog(krb5_context, krb5_ccache, char*, char*, char*, int, char*);
+void KFW_import_ccache_data(void);
+BOOL MSLSA_IsKerberosLogon();
+char *afs_realm_of_cell(struct afsconf_cell *);
+#endif /* AFSKFW_INT_H */
--- /dev/null
+/*
+ * Copyright (c) 2003 SkyRope, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Skyrope, LLC nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission from Skyrope, LLC.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Portions of this code are derived from portions of the MIT
+ * Leash Ticket Manager and LoadFuncs utilities. For these portions the
+ * following copyright applies.
+ *
+ * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+
+#define USE_MS2MIT
+#define USE_KRB4
+#include "afskfw-int.h"
+#include "afskfw.h"
+
+#include <osilog.h>
+#include <rxkad_prototypes.h> /* for life_to_time */
+
+/*
+ * TIMING _____________________________________________________________________
+ *
+ */
+
+#define cminREMIND_TEST 1 // test every minute for expired creds
+#define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
+#define cminRENEW 20 // renew creds when there are 20 minutes remaining
+#define cminMINLIFE 30 // minimum life of Kerberos creds
+
+#define c100ns1SECOND (LONGLONG)10000000
+#define cmsec1SECOND 1000
+#define cmsec1MINUTE 60000
+#define csec1MINUTE 60
+
+/* Function Pointer Declarations for Delayed Loading */
+// CCAPI
+DECL_FUNC_PTR(cc_initialize);
+DECL_FUNC_PTR(cc_shutdown);
+DECL_FUNC_PTR(cc_get_NC_info);
+DECL_FUNC_PTR(cc_free_NC_info);
+
+// leash functions
+DECL_FUNC_PTR(Leash_get_default_lifetime);
+DECL_FUNC_PTR(Leash_get_default_forwardable);
+DECL_FUNC_PTR(Leash_get_default_renew_till);
+DECL_FUNC_PTR(Leash_get_default_noaddresses);
+DECL_FUNC_PTR(Leash_get_default_proxiable);
+DECL_FUNC_PTR(Leash_get_default_publicip);
+DECL_FUNC_PTR(Leash_get_default_use_krb4);
+DECL_FUNC_PTR(Leash_get_default_life_min);
+DECL_FUNC_PTR(Leash_get_default_life_max);
+DECL_FUNC_PTR(Leash_get_default_renew_min);
+DECL_FUNC_PTR(Leash_get_default_renew_max);
+DECL_FUNC_PTR(Leash_get_default_renewable);
+
+// krb5 functions
+DECL_FUNC_PTR(krb5_change_password);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+DECL_FUNC_PTR(krb5_get_init_creds_password);
+DECL_FUNC_PTR(krb5_build_principal_ext);
+DECL_FUNC_PTR(krb5_cc_get_name);
+DECL_FUNC_PTR(krb5_cc_resolve);
+DECL_FUNC_PTR(krb5_cc_default);
+DECL_FUNC_PTR(krb5_cc_default_name);
+DECL_FUNC_PTR(krb5_cc_set_default_name);
+DECL_FUNC_PTR(krb5_cc_initialize);
+DECL_FUNC_PTR(krb5_cc_destroy);
+DECL_FUNC_PTR(krb5_cc_close);
+DECL_FUNC_PTR(krb5_cc_store_cred);
+DECL_FUNC_PTR(krb5_cc_copy_creds);
+DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+DECL_FUNC_PTR(krb5_cc_get_principal);
+DECL_FUNC_PTR(krb5_cc_start_seq_get);
+DECL_FUNC_PTR(krb5_cc_next_cred);
+DECL_FUNC_PTR(krb5_cc_end_seq_get);
+DECL_FUNC_PTR(krb5_cc_remove_cred);
+DECL_FUNC_PTR(krb5_cc_set_flags);
+DECL_FUNC_PTR(krb5_cc_get_type);
+DECL_FUNC_PTR(krb5_free_context);
+DECL_FUNC_PTR(krb5_free_cred_contents);
+DECL_FUNC_PTR(krb5_free_principal);
+DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+DECL_FUNC_PTR(krb5_init_context);
+DECL_FUNC_PTR(krb5_parse_name);
+DECL_FUNC_PTR(krb5_timeofday);
+DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+DECL_FUNC_PTR(krb5_unparse_name);
+DECL_FUNC_PTR(krb5_get_credentials);
+DECL_FUNC_PTR(krb5_mk_req);
+DECL_FUNC_PTR(krb5_sname_to_principal);
+DECL_FUNC_PTR(krb5_get_credentials_renew);
+DECL_FUNC_PTR(krb5_free_data);
+DECL_FUNC_PTR(krb5_free_data_contents);
+DECL_FUNC_PTR(krb5_free_unparsed_name);
+DECL_FUNC_PTR(krb5_os_localaddr);
+DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+DECL_FUNC_PTR(krb5_copy_data);
+DECL_FUNC_PTR(krb5_free_creds);
+DECL_FUNC_PTR(krb5_build_principal);
+DECL_FUNC_PTR(krb5_get_renewed_creds);
+DECL_FUNC_PTR(krb5_get_default_config_files);
+DECL_FUNC_PTR(krb5_free_config_files);
+DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_free_ticket);
+DECL_FUNC_PTR(krb5_decode_ticket);
+DECL_FUNC_PTR(krb5_get_host_realm);
+DECL_FUNC_PTR(krb5_free_host_realm);
+DECL_FUNC_PTR(krb5_free_addresses);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+
+// Krb524 functions
+DECL_FUNC_PTR(krb524_init_ets);
+DECL_FUNC_PTR(krb524_convert_creds_kdc);
+
+// krb4 functions
+DECL_FUNC_PTR(krb_get_cred);
+DECL_FUNC_PTR(tkt_string);
+DECL_FUNC_PTR(krb_get_tf_realm);
+DECL_FUNC_PTR(krb_mk_req);
+
+// ComErr functions
+DECL_FUNC_PTR(com_err);
+DECL_FUNC_PTR(error_message);
+
+// Profile functions
+DECL_FUNC_PTR(profile_init);
+DECL_FUNC_PTR(profile_release);
+DECL_FUNC_PTR(profile_get_subsection_names);
+DECL_FUNC_PTR(profile_free_list);
+DECL_FUNC_PTR(profile_get_string);
+DECL_FUNC_PTR(profile_release_string);
+
+// Service functions
+DECL_FUNC_PTR(OpenSCManagerA);
+DECL_FUNC_PTR(OpenServiceA);
+DECL_FUNC_PTR(QueryServiceStatus);
+DECL_FUNC_PTR(CloseServiceHandle);
+#ifdef USE_MS2MIT
+DECL_FUNC_PTR(LsaNtStatusToWinError);
+#endif /* USE_MS2MIT */
+
+#ifdef USE_MS2MIT
+// LSA Functions
+DECL_FUNC_PTR(LsaConnectUntrusted);
+DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+DECL_FUNC_PTR(LsaFreeReturnBuffer);
+DECL_FUNC_PTR(LsaGetLogonSessionData);
+#endif /* USE_MS2MIT */
+
+// AFS36 Token Functions
+DECL_FUNC_PTR(ktc_ListTokens);
+DECL_FUNC_PTR(ktc_GetToken);
+DECL_FUNC_PTR(ktc_SetToken);
+DECL_FUNC_PTR(ktc_ForgetAllTokens);
+
+// AFS36 Config Functions
+DECL_FUNC_PTR(cm_SearchCellFile);
+DECL_FUNC_PTR(cm_GetRootCellName);
+
+// CCAPI
+FUNC_INFO ccapi_fi[] = {
+ MAKE_FUNC_INFO(cc_initialize),
+ MAKE_FUNC_INFO(cc_shutdown),
+ MAKE_FUNC_INFO(cc_get_NC_info),
+ MAKE_FUNC_INFO(cc_free_NC_info),
+ END_FUNC_INFO
+};
+
+FUNC_INFO leash_fi[] = {
+ MAKE_FUNC_INFO(Leash_get_default_lifetime),
+ MAKE_FUNC_INFO(Leash_get_default_renew_till),
+ MAKE_FUNC_INFO(Leash_get_default_forwardable),
+ MAKE_FUNC_INFO(Leash_get_default_noaddresses),
+ MAKE_FUNC_INFO(Leash_get_default_proxiable),
+ MAKE_FUNC_INFO(Leash_get_default_publicip),
+ MAKE_FUNC_INFO(Leash_get_default_use_krb4),
+ MAKE_FUNC_INFO(Leash_get_default_life_min),
+ MAKE_FUNC_INFO(Leash_get_default_life_max),
+ MAKE_FUNC_INFO(Leash_get_default_renew_min),
+ MAKE_FUNC_INFO(Leash_get_default_renew_max),
+ MAKE_FUNC_INFO(Leash_get_default_renewable),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k5_fi[] = {
+ MAKE_FUNC_INFO(krb5_change_password),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
+ MAKE_FUNC_INFO(krb5_get_init_creds_password),
+ MAKE_FUNC_INFO(krb5_build_principal_ext),
+ MAKE_FUNC_INFO(krb5_cc_get_name),
+ MAKE_FUNC_INFO(krb5_cc_resolve),
+ MAKE_FUNC_INFO(krb5_cc_default),
+ MAKE_FUNC_INFO(krb5_cc_default_name),
+ MAKE_FUNC_INFO(krb5_cc_set_default_name),
+ MAKE_FUNC_INFO(krb5_cc_initialize),
+ MAKE_FUNC_INFO(krb5_cc_destroy),
+ MAKE_FUNC_INFO(krb5_cc_close),
+ MAKE_FUNC_INFO(krb5_cc_copy_creds),
+ MAKE_FUNC_INFO(krb5_cc_store_cred),
+ MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
+ MAKE_FUNC_INFO(krb5_cc_get_principal),
+ MAKE_FUNC_INFO(krb5_cc_start_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_next_cred),
+ MAKE_FUNC_INFO(krb5_cc_end_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_remove_cred),
+ MAKE_FUNC_INFO(krb5_cc_set_flags),
+ MAKE_FUNC_INFO(krb5_cc_get_type),
+ MAKE_FUNC_INFO(krb5_free_context),
+ MAKE_FUNC_INFO(krb5_free_cred_contents),
+ MAKE_FUNC_INFO(krb5_free_principal),
+ MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
+ MAKE_FUNC_INFO(krb5_init_context),
+ MAKE_FUNC_INFO(krb5_parse_name),
+ MAKE_FUNC_INFO(krb5_timeofday),
+ MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
+ MAKE_FUNC_INFO(krb5_unparse_name),
+ MAKE_FUNC_INFO(krb5_get_credentials),
+ MAKE_FUNC_INFO(krb5_mk_req),
+ MAKE_FUNC_INFO(krb5_sname_to_principal),
+ MAKE_FUNC_INFO(krb5_get_credentials_renew),
+ MAKE_FUNC_INFO(krb5_free_data),
+ MAKE_FUNC_INFO(krb5_free_data_contents),
+ MAKE_FUNC_INFO(krb5_free_unparsed_name),
+ MAKE_FUNC_INFO(krb5_os_localaddr),
+ MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
+ MAKE_FUNC_INFO(krb5_copy_data),
+ MAKE_FUNC_INFO(krb5_free_creds),
+ MAKE_FUNC_INFO(krb5_build_principal),
+ MAKE_FUNC_INFO(krb5_get_renewed_creds),
+ MAKE_FUNC_INFO(krb5_free_addresses),
+ MAKE_FUNC_INFO(krb5_get_default_config_files),
+ MAKE_FUNC_INFO(krb5_free_config_files),
+ MAKE_FUNC_INFO(krb5_get_default_realm),
+ MAKE_FUNC_INFO(krb5_free_ticket),
+ MAKE_FUNC_INFO(krb5_decode_ticket),
+ MAKE_FUNC_INFO(krb5_get_host_realm),
+ MAKE_FUNC_INFO(krb5_free_host_realm),
+ MAKE_FUNC_INFO(krb5_free_addresses),
+ MAKE_FUNC_INFO(krb5_c_random_make_octets),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k4_fi[] = {
+ MAKE_FUNC_INFO(krb_get_cred),
+ MAKE_FUNC_INFO(krb_get_tf_realm),
+ MAKE_FUNC_INFO(krb_mk_req),
+ MAKE_FUNC_INFO(tkt_string),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k524_fi[] = {
+ MAKE_FUNC_INFO(krb524_init_ets),
+ MAKE_FUNC_INFO(krb524_convert_creds_kdc),
+ END_FUNC_INFO
+};
+
+FUNC_INFO profile_fi[] = {
+ MAKE_FUNC_INFO(profile_init),
+ MAKE_FUNC_INFO(profile_release),
+ MAKE_FUNC_INFO(profile_get_subsection_names),
+ MAKE_FUNC_INFO(profile_free_list),
+ MAKE_FUNC_INFO(profile_get_string),
+ MAKE_FUNC_INFO(profile_release_string),
+ END_FUNC_INFO
+};
+
+FUNC_INFO ce_fi[] = {
+ MAKE_FUNC_INFO(com_err),
+ MAKE_FUNC_INFO(error_message),
+ END_FUNC_INFO
+};
+
+FUNC_INFO service_fi[] = {
+ MAKE_FUNC_INFO(OpenSCManagerA),
+ MAKE_FUNC_INFO(OpenServiceA),
+ MAKE_FUNC_INFO(QueryServiceStatus),
+ MAKE_FUNC_INFO(CloseServiceHandle),
+#ifdef USE_MS2MIT
+ MAKE_FUNC_INFO(LsaNtStatusToWinError),
+#endif /* USE_MS2MIT */
+ END_FUNC_INFO
+};
+
+#ifdef USE_MS2MIT
+FUNC_INFO lsa_fi[] = {
+ MAKE_FUNC_INFO(LsaConnectUntrusted),
+ MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaFreeReturnBuffer),
+ MAKE_FUNC_INFO(LsaGetLogonSessionData),
+ END_FUNC_INFO
+};
+#endif /* USE_MS2MIT */
+
+FUNC_INFO afst_fi[] = {
+ MAKE_FUNC_INFO(ktc_ListTokens),
+ MAKE_FUNC_INFO(ktc_GetToken),
+ MAKE_FUNC_INFO(ktc_SetToken),
+ MAKE_FUNC_INFO(ktc_ForgetAllTokens),
+ END_FUNC_INFO
+};
+
+FUNC_INFO afsc_fi[] = {
+ MAKE_FUNC_INFO(cm_SearchCellFile),
+ MAKE_FUNC_INFO(cm_GetRootCellName),
+ END_FUNC_INFO
+};
+
+/* Static Prototypes */
+char *afs_realm_of_cell(struct afsconf_cell *);
+static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
+int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
+static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
+ void *data, const char *name, const char *banner, int num_prompts,
+ krb5_prompt prompts[]);
+
+
+/* Static Declarations */
+static int inited = 0;
+static int mid_cnt = 0;
+static struct textField * mid_tb = NULL;
+static HINSTANCE hKrb5 = 0;
+static HINSTANCE hKrb4 = 0;
+static HINSTANCE hKrb524 = 0;
+#ifdef USE_MS2MIT
+static HINSTANCE hSecur32 = 0;
+#endif /* USE_MS2MIT */
+static HINSTANCE hAdvApi32 = 0;
+static HINSTANCE hAfsTokens = 0;
+static HINSTANCE hAfsConf = 0;
+static HINSTANCE hComErr = 0;
+static HINSTANCE hService = 0;
+static HINSTANCE hProfile = 0;
+static HINSTANCE hLeash = 0;
+static HINSTANCE hCCAPI = 0;
+static struct principal_ccache_data * princ_cc_data = NULL;
+static struct cell_principal_map * cell_princ_map = NULL;
+
+void
+KFW_initialize(void)
+{
+ static int inited = 0;
+
+ if ( !inited ) {
+ char mutexName[MAX_PATH];
+ HANDLE hMutex = NULL;
+
+ sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
+
+ hMutex = CreateMutex( NULL, TRUE, mutexName );
+ if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+ if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+ return;
+ }
+ }
+ if ( !inited ) {
+ inited = 1;
+ LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+ LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
+ LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+#ifdef USE_MS2MIT
+ LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+#endif /* USE_MS2MIT */
+ LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
+ LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ LoadFuncs(AFSTOKENS_DLL, afst_fi, &hAfsTokens, 0, 1, 0, 0);
+ LoadFuncs(AFSCONF_DLL, afsc_fi, &hAfsConf, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
+ LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+
+ if ( KFW_is_available() ) {
+ char rootcell[MAXCELLCHARS+1];
+#ifdef USE_MS2MIT
+ KFW_import_windows_lsa();
+#endif /* USE_MS2MIT */
+ KFW_import_ccache_data();
+ KFW_AFS_renew_expiring_tokens();
+
+ /* WIN32 NOTE: no way to get max chars */
+ if (!pcm_GetRootCellName(rootcell))
+ KFW_AFS_renew_token_for_cell(rootcell);
+ }
+ }
+ ReleaseMutex(hMutex);
+ CloseHandle(hMutex);
+ }
+}
+
+void
+KFW_cleanup(void)
+{
+ if (hKrb5)
+ FreeLibrary(hKrb5);
+ if (hKrb4)
+ FreeLibrary(hKrb4);
+ if (hProfile)
+ FreeLibrary(hProfile);
+ if (hAfsTokens)
+ FreeLibrary(hAfsTokens);
+ if (hAfsConf)
+ FreeLibrary(hAfsConf);
+ if (hComErr)
+ FreeLibrary(hComErr);
+ if (hService)
+ FreeLibrary(hService);
+#ifdef USE_MS2MIT
+ if (hSecur32)
+ FreeLibrary(hSecur32);
+#endif /* USE_MS2MIT */
+ if (hKrb524)
+ FreeLibrary(hKrb524);
+ if (hLeash)
+ FreeLibrary(hLeash);
+ if (hCCAPI)
+ FreeLibrary(hCCAPI);
+}
+
+static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
+
+int
+KFW_is_available(void)
+{
+ HKEY parmKey;
+ DWORD code, len;
+ DWORD enableKFW = 1;
+
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code != ERROR_SUCCESS)
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(enableKFW);
+ code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
+ (BYTE *) &enableKFW, &len);
+ if (code != ERROR_SUCCESS) {
+ enableKFW = 1;
+ }
+ RegCloseKey (parmKey);
+ }
+
+ if ( !enableKFW )
+ return FALSE;
+
+ KFW_initialize();
+ if ( hKrb5 && hComErr && hService &&
+#ifdef USE_MS2MIT
+ hSecur32 &&
+#endif /* USE_MS2MIT */
+ hKrb524 &&
+ hProfile && hAfsTokens && hAfsConf && hLeash && hCCAPI )
+ return TRUE;
+ return FALSE;
+}
+
+int
+KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+ int FreeContextFlag, krb5_context * ctx,
+ krb5_ccache * cache)
+{
+ char message[256];
+ const char *errText;
+ int krb5Error = ((int)(rc & 255));
+
+ /*
+ switch (krb5Error)
+ {
+ // Wrong password
+ case 31:
+ case 8:
+ return;
+ }
+ */
+
+ errText = perror_message(rc);
+ _snprintf(message, sizeof(message),
+ "%s\n(Kerberos error %ld)\n\n%s failed",
+ errText,
+ krb5Error,
+ FailedFunctionName);
+
+ if ( IsDebuggerPresent() )
+ OutputDebugString(message);
+
+ MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
+ MB_TASKMODAL |
+ MB_SETFOREGROUND);
+ if (FreeContextFlag == 1)
+ {
+ if (ctx && *ctx != NULL)
+ {
+ if (cache && *cache != NULL) {
+ pkrb5_cc_close(*ctx, *cache);
+ *cache = NULL;
+ }
+
+ pkrb5_free_context(*ctx);
+ *ctx = NULL;
+ }
+ }
+
+ return rc;
+}
+
+void
+KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
+{
+ struct principal_ccache_data * next = princ_cc_data;
+ krb5_principal principal = 0;
+ char * pname = NULL;
+ const char * ccname = NULL;
+ krb5_error_code code = 0;
+ krb5_error_code cc_code = 0;
+ krb5_cc_cursor cur;
+ krb5_creds creds;
+ krb5_flags flags=0;
+ krb5_timestamp now;
+
+ if (ctx == 0 || cc == 0)
+ return;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &principal);
+ if ( code ) return;
+
+ code = pkrb5_unparse_name(ctx, principal, &pname);
+ if ( code ) goto cleanup;
+
+ ccname = pkrb5_cc_get_name(ctx, cc);
+ if (!ccname) goto cleanup;
+
+ // Search the existing list to see if we have a match
+ if ( next ) {
+ for ( ; next ; next = next->next ) {
+ if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccname) )
+ break;
+ }
+ }
+
+ // If not, match add a new node to the beginning of the list and assign init it
+ if ( !next ) {
+ next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
+ next->next = princ_cc_data;
+ princ_cc_data = next;
+ next->principal = _strdup(pname);
+ next->ccache_name = _strdup(ccname);
+ next->from_lsa = lsa;
+ next->expired = 1;
+ next->expiration_time = 0;
+ next->renew = 0;
+ }
+
+ flags = 0; // turn off OPENCLOSE mode
+ code = pkrb5_cc_set_flags(ctx, cc, flags);
+ if ( code ) goto cleanup;
+
+ code = pkrb5_timeofday(ctx, &now);
+
+ cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
+
+ while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
+ if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
+ int valid;
+ // we found the ticket we are looking for
+ // check validity of timestamp
+ // We add a 5 minutes fudge factor to compensate for potential
+ // clock skew errors between the KDC and client OS
+
+ valid = ((creds.times.starttime > 0) &&
+ now >= (creds.times.starttime - 300) &&
+ now < (creds.times.endtime + 300) &&
+ !(creds.ticket_flags & TKT_FLG_INVALID));
+
+ if ( next->from_lsa) {
+ next->expired = 0;
+ next->expiration_time = creds.times.endtime;
+ next->renew = 1;
+ } else if ( valid ) {
+ next->expired = 0;
+ next->expiration_time = creds.times.endtime;
+ next->renew = (creds.times.renew_till > creds.times.endtime) &&
+ (creds.ticket_flags & TKT_FLG_RENEWABLE);
+ } else {
+ next->expired = 1;
+ next->expiration_time = 0;
+ next->renew = 0;
+ }
+
+ pkrb5_free_cred_contents(ctx, &creds);
+ cc_code = KRB5_CC_END;
+ break;
+ }
+ pkrb5_free_cred_contents(ctx, &creds);
+ }
+
+ if (cc_code == KRB5_CC_END) {
+ code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
+ if (code) goto cleanup;
+ }
+
+ cleanup:
+ flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
+ code = pkrb5_cc_set_flags(ctx, cc, flags);
+
+ if ( pname )
+ pkrb5_free_unparsed_name(ctx,pname);
+ if ( principal )
+ pkrb5_free_principal(ctx,principal);
+}
+
+int
+KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
+{
+ struct principal_ccache_data * next = princ_cc_data;
+ char * response = NULL;
+
+ if ( !principal || !ccache )
+ return 0;
+
+ while ( next ) {
+ if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
+ if (response) {
+ // we always want to prefer the MS Kerberos LSA cache or
+ // the cache afscreds created specifically for the principal
+ // if the current entry is either one, drop the previous find
+ if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
+ free(response);
+ }
+ response = _strdup(next->ccache_name);
+ // MS Kerberos LSA is our best option so use it and quit
+ if ( next->from_lsa )
+ break;
+ }
+ next = next->next;
+ }
+
+ if ( response ) {
+ *ccache = response;
+ return 1;
+ }
+ return 0;
+}
+
+void
+KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
+{
+ struct principal_ccache_data ** next = &princ_cc_data;
+
+ if ( !pname && !ccname )
+ return;
+
+ while ( (*next) ) {
+ if ( !strcmp((*next)->principal,pname) ||
+ !strcmp((*next)->ccache_name,ccname) ) {
+ void * temp;
+ free((*next)->principal);
+ free((*next)->ccache_name);
+ temp = (*next);
+ (*next) = (*next)->next;
+ free(temp);
+ }
+ }
+}
+
+void
+KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
+{
+ struct cell_principal_map * next = cell_princ_map;
+
+ // Search the existing list to see if we have a match
+ if ( next ) {
+ for ( ; next ; next = next->next ) {
+ if ( !strcmp(next->cell, cell) ) {
+ if ( !strcmp(next->principal,pname) ) {
+ next->active = active;
+ break;
+ } else {
+ // OpenAFS currently has a restriction of one active token per cell
+ // Therefore, whenever we update the table with a new active cell we
+ // must mark all of the other principal to cell entries as inactive.
+ if (active)
+ next->active = 0;
+ }
+ }
+ }
+ }
+
+ // If not, match add a new node to the beginning of the list and assign init it
+ if ( !next ) {
+ next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
+ next->next = cell_princ_map;
+ cell_princ_map = next;
+ next->principal = _strdup(pname);
+ next->cell = _strdup(cell);
+ next->active = active;
+ }
+}
+
+void
+KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
+{
+ struct cell_principal_map ** next = &cell_princ_map;
+
+ if ( !pname && !cell )
+ return;
+
+ while ( (*next) ) {
+ if ( !strcmp((*next)->principal,pname) ||
+ !strcmp((*next)->cell,cell) ) {
+ void * temp;
+ free((*next)->principal);
+ free((*next)->cell);
+ temp = (*next);
+ (*next) = (*next)->next;
+ free(temp);
+ }
+ }
+}
+
+// Returns (if possible) a principal which has been known in
+// the past to have been used to obtain tokens for the specified
+// cell.
+// TODO: Attempt to return one which has not yet expired by checking
+// the principal/ccache data
+int
+KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
+{
+ struct cell_principal_map * next_map = cell_princ_map;
+ const char * princ = NULL;
+ int count = 0, i;
+
+ if ( !cell )
+ return 0;
+
+ while ( next_map ) {
+ if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
+ count++;
+ }
+ next_map = next_map->next;
+ }
+
+ if ( !principals || !count )
+ return count;
+
+ *principals = (char **) malloc(sizeof(char *) * count);
+ for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
+ {
+ if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
+ (*principals)[i++] = _strdup(next_map->principal);
+ }
+ }
+ return count;
+}
+
+int
+KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
+{
+ int count = 0, i;
+ struct cell_principal_map * next_map = cell_princ_map;
+ const char * princ = NULL;
+
+ if ( !pname )
+ return 0;
+
+ while ( next_map ) {
+ if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
+ count++;
+ }
+ next_map = next_map->next;
+ }
+
+ if ( !cells )
+ return count;
+
+ *cells = (char **) malloc(sizeof(char *) * count);
+ for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
+ {
+ if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
+ (*cells)[i++] = _strdup(next_map->cell);
+ }
+ }
+ return count;
+}
+
+/* Given a principal return an existing ccache or create one and return */
+int
+KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
+{
+ krb5_context ctx;
+ char * pname = 0;
+ char * ccname = 0;
+ krb5_error_code code;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( alt_ctx ) {
+ ctx = alt_ctx;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( principal ) {
+ code = pkrb5_unparse_name(ctx, principal, &pname);
+ if (code) goto cleanup;
+
+ if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
+ !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
+ ccname = (char *)malloc(strlen(pname) + 5);
+ sprintf(ccname,"API:%s",pname);
+ }
+ code = pkrb5_cc_resolve(ctx, ccname, cc);
+ } else {
+ code = pkrb5_cc_default(ctx, cc);
+ if (code) goto cleanup;
+ }
+
+ cleanup:
+ if (ccname)
+ free(ccname);
+ if (pname)
+ pkrb5_free_unparsed_name(ctx,pname);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+#ifdef USE_MS2MIT
+// Import Microsoft Credentials into a new MIT ccache
+void
+KFW_import_windows_lsa(void)
+{
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal princ = 0;
+ char * pname = NULL;
+ krb5_data * realm;
+ krb5_error_code code;
+ char cell[128]="";
+ int i;
+
+ if (!pkrb5_init_context)
+ return;
+
+#ifdef COMMENT
+ if ( !MSLSA_IsKerberosLogon() )
+ return;
+#endif
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
+ if (code) goto cleanup;
+
+ KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+ if ( code ) goto cleanup;
+
+ code = pkrb5_unparse_name(ctx,princ,&pname);
+ if ( code ) goto cleanup;
+
+ realm = krb5_princ_realm(ctx, princ);
+ for ( i=0; i<realm->length; i++ ) {
+ cell[i] = tolower(realm->data[i]);
+ }
+ cell[i] = '\0';
+
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm->data, pLeash_get_default_lifetime(),NULL);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ if ( code ) goto cleanup;
+
+ KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
+
+ cleanup:
+ if (pname)
+ pkrb5_free_unparsed_name(ctx,pname);
+ if (princ)
+ pkrb5_free_principal(ctx,princ);
+ if (cc)
+ pkrb5_cc_close(ctx,cc);
+ if (ctx)
+ pkrb5_free_context(ctx);
+}
+#endif /* USE_MS2MIT */
+
+// If there are existing MIT credentials, copy them to a new
+// ccache named after the principal
+
+// Enumerate all existing MIT ccaches and construct entries
+// in the principal_ccache table
+
+// Enumerate all existing AFS Tokens and construct entries
+// in the cell_principal table
+void
+KFW_import_ccache_data(void)
+{
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal principal = 0;
+ krb5_creds creds;
+ krb5_error_code code;
+ krb5_error_code cc_code;
+ krb5_cc_cursor cur;
+ apiCB * cc_ctx = 0;
+ struct _infoNC ** pNCi = NULL;
+ int i, j, flags;
+
+ if ( !pcc_initialize )
+ return;
+
+ if ( IsDebuggerPresent() )
+ OutputDebugString("KFW_import_ccache_data()\n");
+
+ code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
+ if (code) goto cleanup;
+
+ code = pcc_get_NC_info(cc_ctx, &pNCi);
+ if (code) goto cleanup;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ for ( i=0; pNCi[i]; i++ ) {
+ if ( pNCi[i]->vers != CC_CRED_V5 )
+ continue;
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Principal: ");
+ OutputDebugString(pNCi[i]->principal);
+ OutputDebugString(" in ccache ");
+ OutputDebugString(pNCi[i]->name);
+ OutputDebugString("\n");
+ }
+ if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
+ && strcmp(pNCi[i]->name,LSA_CCNAME)
+ ) {
+ int found = 0;
+ for ( j=0; pNCi[j]; j++ ) {
+ if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
+ found = 1;
+ break;
+ }
+ }
+
+ code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
+ if (code) goto loop_cleanup;
+
+ if (!found) {
+ krb5_ccache oldcc = 0;
+
+ if ( IsDebuggerPresent() )
+ OutputDebugString("copying ccache data to new ccache\n");
+
+ code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
+ if (code) goto loop_cleanup;
+ code = pkrb5_cc_initialize(ctx, cc, principal);
+ if (code) goto loop_cleanup;
+
+ code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
+ if (code) goto loop_cleanup;
+ code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
+ if (code) {
+ code = pkrb5_cc_close(ctx,cc);
+ cc = 0;
+ code = pkrb5_cc_close(ctx,oldcc);
+ cc = 0;
+ KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
+ continue;
+ }
+ code = pkrb5_cc_close(ctx,oldcc);
+ }
+ } else {
+ code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
+ if (code) goto loop_cleanup;
+ }
+
+ flags = 0; // turn off OPENCLOSE mode
+ code = pkrb5_cc_set_flags(ctx, cc, flags);
+ if ( code ) goto cleanup;
+
+ KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
+
+ cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
+
+ while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
+ krb5_data * sname = krb5_princ_name(ctx, creds.server);
+ krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
+ krb5_data * realm = krb5_princ_realm(ctx, creds.server);
+ if ( sname && cell && !strcmp("afs",sname->data) ) {
+ struct ktc_principal aserver;
+ struct ktc_principal aclient;
+ struct ktc_token atoken;
+ int active = TRUE;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Found AFS ticket: ");
+ OutputDebugString(sname->data);
+ if ( cell->data ) {
+ OutputDebugString("/");
+ OutputDebugString(cell->data);
+ }
+ OutputDebugString("@");
+ OutputDebugString(realm->data);
+ OutputDebugString("\n");
+ }
+
+ memset(&aserver, '\0', sizeof(aserver));
+ strcpy(aserver.name, sname->data);
+ strcpy(aserver.cell, cell->data);
+
+ code = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
+ if (!code) {
+ // Found a token in AFS Client Server which matches
+ char pname[128], *p, *q;
+ for ( p=pname, q=aclient.name; *q; p++, q++)
+ *p = *q;
+ for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
+ *p = toupper(*q);
+ *p = '\0';
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Found AFS token: ");
+ OutputDebugString(pname);
+ OutputDebugString("\n");
+ }
+
+ if ( strcmp(pname,pNCi[i]->principal) )
+ active = FALSE;
+ KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
+ } else {
+ // Attempt to import it
+ KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
+ }
+
+ code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, pLeash_get_default_lifetime(),NULL);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ }
+ } else if ( IsDebuggerPresent() ) {
+ OutputDebugString("Found ticket: ");
+ OutputDebugString(sname->data);
+ if ( cell && cell->data ) {
+ OutputDebugString("/");
+ OutputDebugString(cell->data);
+ }
+ OutputDebugString("@");
+ OutputDebugString(realm->data);
+ OutputDebugString("\n");
+ }
+ pkrb5_free_cred_contents(ctx, &creds);
+ }
+
+ if (cc_code == KRB5_CC_END) {
+ cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
+ if (cc_code) goto loop_cleanup;
+ }
+
+ loop_cleanup:
+ flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
+ code = pkrb5_cc_set_flags(ctx, cc, flags);
+ if (cc) {
+ pkrb5_cc_close(ctx,cc);
+ cc = 0;
+ }
+ if (principal) {
+ pkrb5_free_principal(ctx,principal);
+ principal = 0;
+ }
+ }
+
+ cleanup:
+ if (ctx)
+ pkrb5_free_context(ctx);
+ if (pNCi)
+ pcc_free_NC_info(cc_ctx, &pNCi);
+ if (cc_ctx)
+ pcc_shutdown(&cc_ctx);
+}
+
+
+int
+KFW_AFS_get_cred(char * username,
+ char * instance,
+ char * cell,
+ char * password,
+ int lifetime,
+ char * smbname,
+ char ** reasonP )
+{
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ char * realm = 0;
+ char ** realmlist = 0;
+ krb5_principal principal = 0;
+ char * pname = 0;
+ krb5_error_code code;
+ char local_cell[MAXCELLCHARS+1];
+ char **cells = NULL;
+ int cell_count=0;
+ struct afsconf_cell cellconfig;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_AFS_get_cred for token ");
+ OutputDebugString(username);
+ if ( instance ) {
+ OutputDebugString("/");
+ OutputDebugString(instance);
+ }
+ OutputDebugString("@");
+ OutputDebugString(cell);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if ( code ) goto cleanup;
+
+ code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
+ if ( code ) goto cleanup;
+
+ realm = strchr(username,'@');
+ if (realm) {
+ *realm = '\0';
+ realm++;
+ }
+ if ( !realm || !realm[0] )
+ realm = afs_realm_of_cell(&cellconfig); // do not free
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Realm: ");
+ OutputDebugString(realm);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_build_principal(ctx, &principal, strlen(realm),
+ realm, username,
+ (instance && instance[0]) ? instance : NULL,
+ NULL);
+
+ code = KFW_get_ccache(ctx, principal, &cc);
+ if ( code ) goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, principal, &pname);
+ if ( code ) goto cleanup;
+
+ if ( lifetime == 0 )
+ lifetime = pLeash_get_default_lifetime();
+
+ code = KFW_kinit(ctx, cc, HWND_DESKTOP,
+ pname,
+ password,
+ lifetime,
+ pLeash_get_default_forwardable(),
+ pLeash_get_default_proxiable(),
+ pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
+ pLeash_get_default_noaddresses(),
+ pLeash_get_default_publicip());
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_kinit() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ if ( code ) goto cleanup;
+
+ KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
+
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ if ( code ) goto cleanup;
+
+ KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
+
+ // Attempt to obtain new tokens for other cells supported by the same
+ // principal
+ cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
+ if ( cell_count > 1 ) {
+ while ( cell_count-- ) {
+ if ( strcmp(cells[cell_count],cell) ) {
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"found another cell for the same principal: %s\n",cell);
+ OutputDebugString(message);
+ }
+ code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
+ if ( code ) continue;
+
+ realm = afs_realm_of_cell(&cellconfig); // do not free
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Realm: ");
+ OutputDebugString(realm);
+ OutputDebugString("\n");
+ }
+
+ code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime,smbname);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ }
+ free(cells[cell_count]);
+ }
+ free(cells);
+ } else if ( cell_count == 1 ) {
+ free(cells[0]);
+ free(cells);
+ }
+
+ cleanup:
+ if ( pname )
+ pkrb5_free_unparsed_name(ctx,pname);
+ if ( cc )
+ pkrb5_cc_close(ctx, cc);
+
+ if ( code && reasonP ) {
+ *reasonP = (char *)perror_message(code);
+ }
+ return(code);
+}
+
+int
+KFW_AFS_destroy_tickets_for_cell(char * cell)
+{
+ krb5_context ctx = 0;
+ krb5_error_code code;
+ int count;
+ char ** principals = NULL;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
+ OutputDebugString(cell);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code) ctx = 0;
+
+ count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
+ if ( count > 0 ) {
+ krb5_principal princ = 0;
+ krb5_ccache cc = 0;
+
+ while ( count-- ) {
+ int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
+ if ( cell_count > 1 ) {
+ // TODO - What we really should do here is verify whether or not any of the
+ // other cells which use this principal to obtain its credentials actually
+ // have valid tokens or not. If they are currently using these credentials
+ // we will skip them. For the time being we assume that if there is an active
+ // map in the table that they are actively being used.
+ goto loop_cleanup;
+ }
+
+ code = pkrb5_parse_name(ctx, principals[count], &princ);
+ if (code) goto loop_cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto loop_cleanup;
+
+ code = pkrb5_cc_destroy(ctx, cc);
+ if (!code) cc = 0;
+
+ loop_cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
+ free(principals[count]);
+ }
+ free(principals);
+ }
+ pkrb5_free_context(ctx);
+ return 0;
+}
+
+int
+KFW_AFS_renew_expiring_tokens(void)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_timestamp now;
+ struct principal_ccache_data * pcc_next = princ_cc_data;
+ int cell_count;
+ char ** cells=NULL;
+ const char * realm = NULL;
+ char local_cell[MAXCELLCHARS+1]="";
+ struct afsconf_cell cellconfig;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( pcc_next == NULL ) // nothing to do
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ code = pkrb5_timeofday(ctx, &now);
+ if (code) goto cleanup;
+
+ for ( ; pcc_next ; pcc_next = pcc_next->next ) {
+ if ( pcc_next->expired )
+ continue;
+
+ if ( now >= (pcc_next->expiration_time) ) {
+ if ( !pcc_next->from_lsa ) {
+ pcc_next->expired = 1;
+ continue;
+ }
+ }
+
+ if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
+ code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
+ if ( code )
+ goto loop_cleanup;
+ code = KFW_renew(ctx,cc);
+#ifdef USE_MS2MIT
+ if ( code && pcc_next->from_lsa)
+ goto loop_cleanup;
+#endif /* USE_MS2MIT */
+
+
+ KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
+ if (code) goto loop_cleanup;
+
+ // Attempt to obtain new tokens for other cells supported by the same
+ // principal
+ cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
+ if ( cell_count > 0 ) {
+ while ( cell_count-- ) {
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Cell: ");
+ OutputDebugString(cells[cell_count]);
+ OutputDebugString("\n");
+ }
+ code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
+ if ( code ) continue;
+ realm = afs_realm_of_cell(&cellconfig); // do not free
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Realm: ");
+ OutputDebugString(realm);
+ OutputDebugString("\n");
+ }
+ code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime(),NULL);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ free(cells[cell_count]);
+ }
+ free(cells);
+ }
+ }
+
+ loop_cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx,cc);
+ cc = 0;
+ }
+ }
+
+ cleanup:
+ if ( cc )
+ pkrb5_cc_close(ctx,cc);
+ if ( ctx )
+ pkrb5_free_context(ctx);
+
+ return 0;
+}
+
+
+BOOL
+KFW_AFS_renew_token_for_cell(char * cell)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ int count;
+ char ** principals = NULL;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_AFS_renew_token_for_cell:");
+ OutputDebugString(cell);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
+ if ( count == 0 ) {
+ // We know we must have a credential somewhere since we are
+ // trying to renew a token
+
+ KFW_import_ccache_data();
+ count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
+ }
+ if ( count > 0 ) {
+ krb5_principal princ = 0;
+ krb5_principal service = 0;
+#ifdef COMMENT
+ krb5_creds mcreds, creds;
+#endif /* COMMENT */
+ krb5_ccache cc = 0;
+ const char * realm = NULL;
+ struct afsconf_cell cellconfig;
+ char local_cell[MAXCELLCHARS+1];
+
+ while ( count-- ) {
+ code = pkrb5_parse_name(ctx, principals[count], &princ);
+ if (code) goto loop_cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto loop_cleanup;
+
+ code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
+ if ( code ) goto loop_cleanup;
+
+ realm = afs_realm_of_cell(&cellconfig); // do not free
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("Realm: ");
+ OutputDebugString(realm);
+ OutputDebugString("\n");
+ }
+
+#ifdef COMMENT
+ /* krb5_cc_remove_cred() is not implemented
+ * for a single cred
+ */
+ code = pkrb5_build_principal(ctx, &service, strlen(realm),
+ realm, "afs", cell, NULL);
+ if (!code) {
+ memset(&mcreds, 0, sizeof(krb5_creds));
+ mcreds.client = princ;
+ mcreds.server = service;
+
+ code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
+ if (!code) {
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, creds.client, &cname);
+ pkrb5_unparse_name(ctx, creds.server, &sname);
+ OutputDebugString("Removing credential for client \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ }
+
+ code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
+ pkrb5_free_principal(ctx, creds.client);
+ pkrb5_free_principal(ctx, creds.server);
+ }
+ }
+#endif /* COMMENT */
+
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime(),NULL);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+
+ loop_cleanup:
+ if (cc) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if (princ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+ if (service) {
+ pkrb5_free_principal(ctx, service);
+ princ = 0;
+ }
+
+ KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
+ free(principals[count]);
+ }
+ free(principals);
+ } else
+ code = -1; // we did not renew the tokens
+
+ cleanup:
+ pkrb5_free_context(ctx);
+ return (code ? FALSE : TRUE);
+
+}
+
+int
+KFW_AFS_renew_tokens_for_all_cells(void)
+{
+ struct cell_principal_map * next = cell_princ_map;
+
+ if ( IsDebuggerPresent() )
+ OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
+
+ if ( !next )
+ return 0;
+
+ for ( ; next ; next = next->next ) {
+ if ( next->active )
+ KFW_AFS_renew_token_for_cell(next->cell);
+ }
+ return 0;
+}
+
+int
+KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+ krb5_principal server = 0;
+ krb5_creds my_creds;
+ krb5_data *realm = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ memset(&my_creds, 0, sizeof(krb5_creds));
+
+ if ( alt_ctx ) {
+ ctx = alt_ctx;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( alt_cc ) {
+ cc = alt_cc;
+ } else {
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_cc_get_principal(ctx, cc, &me);
+ if (code) goto cleanup;
+
+ realm = krb5_princ_realm(ctx, me);
+
+ code = pkrb5_build_principal_ext(ctx, &server,
+ realm->length,realm->data,
+ KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+ realm->length,realm->data,
+ 0);
+ if ( code )
+ goto cleanup;
+
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, me, &cname);
+ pkrb5_unparse_name(ctx, server, &sname);
+ OutputDebugString("Renewing credential for client \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ }
+
+ my_creds.client = me;
+ my_creds.server = server;
+
+ code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
+ if (code) {
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
+ OutputDebugString(message);
+ }
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code) {
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
+ OutputDebugString(message);
+ }
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code) {
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
+ OutputDebugString(message);
+ }
+ goto cleanup;
+ }
+
+ cleanup:
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ if (my_creds.server == server)
+ my_creds.server = 0;
+ pkrb5_free_cred_contents(ctx, &my_creds);
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (server)
+ pkrb5_free_principal(ctx, server);
+ if (cc && (cc != alt_cc))
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+int
+KFW_kinit( krb5_context alt_ctx,
+ krb5_ccache alt_cc,
+ HWND hParent,
+ char *principal_name,
+ char *password,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP
+ )
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+ char* name = 0;
+ krb5_creds my_creds;
+ krb5_get_init_creds_opt options;
+ krb5_address ** addrs = NULL;
+ int i = 0, addr_count = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ pkrb5_get_init_creds_opt_init(&options);
+ memset(&my_creds, 0, sizeof(my_creds));
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( alt_cc ) {
+ cc = alt_cc;
+ } else {
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_parse_name(ctx, principal_name, &me);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, me, &name);
+ if (code)
+ goto cleanup;
+
+ if (lifetime == 0)
+ lifetime = pLeash_get_default_lifetime();
+ else
+ lifetime *= 5*60;
+
+ if (renew_life > 0)
+ renew_life *= 5*60;
+
+ if (lifetime)
+ pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+ pkrb5_get_init_creds_opt_set_forwardable(&options,
+ forwardable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&options,
+ proxiable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_renew_life(&options,
+ renew_life);
+ if (addressless)
+ pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
+ else {
+ if (publicIP)
+ {
+ // we are going to add the public IP address specified by the user
+ // to the list provided by the operating system
+ krb5_address ** local_addrs=NULL;
+ DWORD netIPAddr;
+
+ pkrb5_os_localaddr(ctx, &local_addrs);
+ while ( local_addrs[i++] );
+ addr_count = i + 1;
+
+ addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
+ if ( !addrs ) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+ memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
+ i = 0;
+ while ( local_addrs[i] ) {
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+
+ addrs[i]->magic = local_addrs[i]->magic;
+ addrs[i]->addrtype = local_addrs[i]->addrtype;
+ addrs[i]->length = local_addrs[i]->length;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ goto cleanup;
+ }
+
+ memcpy(addrs[i]->contents,local_addrs[i]->contents,
+ local_addrs[i]->length); /* safe */
+ i++;
+ }
+ pkrb5_free_addresses(ctx, local_addrs);
+
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL)
+ goto cleanup;
+
+ addrs[i]->magic = KV5M_ADDRESS;
+ addrs[i]->addrtype = AF_INET;
+ addrs[i]->length = 4;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents)
+ goto cleanup;
+
+ netIPAddr = htonl(publicIP);
+ memcpy(addrs[i]->contents,&netIPAddr,4);
+
+ pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
+
+ }
+ }
+
+ code = pkrb5_get_init_creds_password(ctx,
+ &my_creds,
+ me,
+ password, // password
+ KRB5_prompter, // prompter
+ hParent, // prompter data
+ 0, // start time
+ 0, // service name
+ &options);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code)
+ goto cleanup;
+
+ cleanup:
+ if ( addrs ) {
+ for ( i=0;i<addr_count;i++ ) {
+ if ( addrs[i] ) {
+ if ( addrs[i]->contents )
+ free(addrs[i]->contents);
+ free(addrs[i]);
+ }
+ }
+ }
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ pkrb5_free_cred_contents(ctx, &my_creds);
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (cc && (cc != alt_cc))
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+
+int
+KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
+{
+ krb5_context ctx;
+ krb5_ccache cc;
+ krb5_error_code code;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( alt_cc ) {
+ cc = alt_cc;
+ } else {
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_cc_destroy(ctx, cc);
+ if ( !code ) cc = 0;
+
+ cleanup:
+ if (cc && (cc != alt_cc))
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+
+ return(code);
+}
+
+
+#ifdef USE_MS2MIT
+static BOOL
+GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+ NTSTATUS Status = 0;
+ HANDLE TokenHandle;
+ TOKEN_STATISTICS Stats;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (!ppSessionData)
+ return FALSE;
+ *ppSessionData = NULL;
+
+ Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+ CloseHandle( TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+ if ( FAILED(Status) || !ppSessionData )
+ return FALSE;
+
+ return TRUE;
+}
+
+//
+// MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
+// cache. It validates whether or not it is reasonable to assume that if we
+// attempted to retrieve valid tickets we could do so. Microsoft does not
+// automatically renew expired tickets. Therefore, the cache could contain
+// expired or invalid tickets. Microsoft also caches the user's password
+// and will use it to retrieve new TGTs if the cache is empty and tickets
+// are requested.
+
+static BOOL
+MSLSA_IsKerberosLogon(VOID)
+{
+ PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+ BOOL Success = FALSE;
+
+ if ( GetSecurityLogonSessionData(&pSessionData) ) {
+ if ( pSessionData->AuthenticationPackage.Buffer ) {
+ WCHAR buffer[256];
+ WCHAR *usBuffer;
+ int usLength;
+
+ Success = FALSE;
+ usBuffer = (pSessionData->AuthenticationPackage).Buffer;
+ usLength = (pSessionData->AuthenticationPackage).Length;
+ if (usLength < 256)
+ {
+ lstrcpynW (buffer, usBuffer, usLength);
+ lstrcatW (buffer,L"");
+ if ( !lstrcmpW(L"Kerberos",buffer) )
+ Success = TRUE;
+ }
+ }
+ pLsaFreeReturnBuffer(pSessionData);
+ }
+ return Success;
+}
+#endif /* USE_MS2MIT */
+
+static BOOL CALLBACK
+MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ int i;
+
+ switch ( message ) {
+ case WM_INITDIALOG:
+ if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
+ {
+ SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
+ return FALSE;
+ }
+ for ( i=0; i < mid_cnt ; i++ ) {
+ if (mid_tb[i].echo == 0)
+ SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
+ else if (mid_tb[i].echo == 2)
+ SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch ( LOWORD(wParam) ) {
+ case IDOK:
+ for ( i=0; i < mid_cnt ; i++ ) {
+ if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
+ *mid_tb[i].buf = '\0';
+ }
+ /* fallthrough */
+ case IDCANCEL:
+ EndDialog(hDialog, LOWORD(wParam));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static LPWORD
+lpwAlign( LPWORD lpIn )
+{
+ ULONG ul;
+
+ ul = (ULONG) lpIn;
+ ul += 3;
+ ul >>=2;
+ ul <<=2;
+ return (LPWORD) ul;;
+}
+
+/*
+ * dialog widths are measured in 1/4 character widths
+ * dialog height are measured in 1/8 character heights
+ */
+
+static LRESULT
+MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
+ char * ptext[], int numlines, int width,
+ int tb_cnt, struct textField * tb)
+{
+ HGLOBAL hgbl;
+ LPDLGTEMPLATE lpdt;
+ LPDLGITEMTEMPLATE lpdit;
+ LPWORD lpw;
+ LPWSTR lpwsz;
+ LRESULT ret;
+ int nchar, i, pwid;
+
+ hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
+ if (!hgbl)
+ return -1;
+
+ mid_cnt = tb_cnt;
+ mid_tb = tb;
+
+ lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
+
+ // Define a dialog box.
+
+ lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
+ | DS_MODALFRAME | WS_CAPTION | DS_CENTER
+ | DS_SETFOREGROUND | DS_3DLOOK
+ | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
+ lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
+ lpdt->x = 10;
+ lpdt->y = 10;
+ lpdt->cx = 20 + width * 4;
+ lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
+
+ lpw = (LPWORD) (lpdt + 1);
+ *lpw++ = 0; // no menu
+ *lpw++ = 0; // predefined dialog box class (by default)
+
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
+ lpw += nchar;
+ *lpw++ = 8; // font size (points)
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
+ -1, lpwsz, 128);
+ lpw += nchar;
+
+ //-----------------------
+ // Define an OK button.
+ //-----------------------
+ lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
+ lpdit = (LPDLGITEMTEMPLATE) lpw;
+ lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
+ lpdit->dwExtendedStyle = 0;
+ lpdit->x = (lpdt->cx - 14)/4 - 20;
+ lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
+ lpdit->cx = 40;
+ lpdit->cy = 14;
+ lpdit->id = IDOK; // OK button identifier
+
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0080; // button class
+
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
+ lpw += nchar;
+ *lpw++ = 0; // no creation data
+
+ //-----------------------
+ // Define an Cancel button.
+ //-----------------------
+ lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
+ lpdit = (LPDLGITEMTEMPLATE) lpw;
+ lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
+ lpdit->dwExtendedStyle = 0;
+ lpdit->x = (lpdt->cx - 14)*3/4 - 20;
+ lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
+ lpdit->cx = 40;
+ lpdit->cy = 14;
+ lpdit->id = IDCANCEL; // CANCEL button identifier
+
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0080; // button class
+
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
+ lpw += nchar;
+ *lpw++ = 0; // no creation data
+
+ /* Add controls for preface data */
+ for ( i=0; i<numlines; i++) {
+ /*-----------------------
+ * Define a static text control.
+ *-----------------------*/
+ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
+ lpdit = (LPDLGITEMTEMPLATE) lpw;
+ lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
+ lpdit->dwExtendedStyle = 0;
+ lpdit->x = 10;
+ lpdit->y = 10 + i * 14;
+ lpdit->cx = strlen(ptext[i]) * 4 + 10;
+ lpdit->cy = 14;
+ lpdit->id = ID_TEXT + i; // text identifier
+
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0082; // static class
+
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
+ -1, lpwsz, 2*width);
+ lpw += nchar;
+ *lpw++ = 0; // no creation data
+ }
+
+ for ( i=0, pwid = 0; i<tb_cnt; i++) {
+ if ( pwid < strlen(tb[i].label) )
+ pwid = strlen(tb[i].label);
+ }
+
+ for ( i=0; i<tb_cnt; i++) {
+ /* Prompt */
+ /*-----------------------
+ * Define a static text control.
+ *-----------------------*/
+ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
+ lpdit = (LPDLGITEMTEMPLATE) lpw;
+ lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
+ lpdit->dwExtendedStyle = 0;
+ lpdit->x = 10;
+ lpdit->y = 10 + (numlines + i + 1) * 14;
+ lpdit->cx = pwid * 4;
+ lpdit->cy = 14;
+ lpdit->id = ID_TEXT + numlines + i; // text identifier
+
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0082; // static class
+
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
+ -1, lpwsz, 128);
+ lpw += nchar;
+ *lpw++ = 0; // no creation data
+
+ /*-----------------------
+ * Define an edit control.
+ *-----------------------*/
+ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
+ lpdit = (LPDLGITEMTEMPLATE) lpw;
+ lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
+ lpdit->dwExtendedStyle = 0;
+ lpdit->x = 10 + (pwid + 1) * 4;
+ lpdit->y = 10 + (numlines + i + 1) * 14;
+ lpdit->cx = (width - (pwid + 1)) * 4;
+ lpdit->cy = 14;
+ lpdit->id = ID_MID_TEXT + i; // identifier
+
+ lpw = (LPWORD) (lpdit + 1);
+ *lpw++ = 0xFFFF;
+ *lpw++ = 0x0081; // edit class
+
+ lpwsz = (LPWSTR) lpw;
+ nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
+ -1, lpwsz, 128);
+ lpw += nchar;
+ *lpw++ = 0; // no creation data
+ }
+
+ GlobalUnlock(hgbl);
+ ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
+ hwndOwner, (DLGPROC) MultiInputDialogProc);
+ GlobalFree(hgbl);
+
+ switch ( ret ) {
+ case 0: /* Timeout */
+ return -1;
+ case IDOK:
+ return 1;
+ case IDCANCEL:
+ return 0;
+ default: {
+ char buf[256];
+ sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
+ MessageBox(hwndOwner,
+ buf,
+ "GetLastError()",
+ MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ return -1;
+ }
+ }
+}
+
+static int
+multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
+{
+ HINSTANCE hInst = 0;
+ int maxwidth = 0;
+ int numlines = 0;
+ int len;
+ char * plines[16], *p = preface ? preface : "";
+ int i;
+
+ for ( i=0; i<16; i++ )
+ plines[i] = NULL;
+
+ while (*p && numlines < 16) {
+ plines[numlines++] = p;
+ for ( ;*p && *p != '\r' && *p != '\n'; p++ );
+ if ( *p == '\r' && *(p+1) == '\n' ) {
+ *p++ = '\0';
+ p++;
+ } else if ( *p == '\n' ) {
+ *p++ = '\0';
+ }
+ if ( strlen(plines[numlines-1]) > maxwidth )
+ maxwidth = strlen(plines[numlines-1]);
+ }
+
+ for ( i=0;i<n;i++ ) {
+ len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
+ if ( maxwidth < len )
+ maxwidth = len;
+ }
+
+ return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb));
+}
+
+static krb5_error_code KRB5_CALLCONV
+KRB5_prompter( krb5_context context,
+ void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[])
+{
+ krb5_error_code errcode = 0;
+ int i;
+ struct textField * tb = NULL;
+ int len = 0, blen=0, nlen=0;
+ HWND hParent = (HWND)data;
+
+ if (name)
+ nlen = strlen(name)+2;
+
+ if (banner)
+ blen = strlen(banner)+2;
+
+ tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
+ if ( tb != NULL ) {
+ int ok;
+ memset(tb,0,sizeof(struct textField) * num_prompts);
+ for ( i=0; i < num_prompts; i++ ) {
+ tb[i].buf = prompts[i].reply->data;
+ tb[i].len = prompts[i].reply->length;
+ tb[i].label = prompts[i].prompt;
+ tb[i].def = NULL;
+ tb[i].echo = (prompts[i].hidden ? 2 : 1);
+ }
+
+ ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
+ if ( ok ) {
+ for ( i=0; i < num_prompts; i++ )
+ prompts[i].reply->length = strlen(prompts[i].reply->data);
+ } else
+ errcode = -2;
+ }
+
+ if ( tb )
+ free(tb);
+ if (errcode) {
+ for (i = 0; i < num_prompts; i++) {
+ memset(prompts[i].reply->data, 0, prompts[i].reply->length);
+ }
+ }
+ return errcode;
+}
+
+BOOL
+KFW_AFS_wait_for_service_start(void)
+{
+ char HostName[64];
+ DWORD CurrentState;
+
+ CurrentState = SERVICE_START_PENDING;
+ memset(HostName, '\0', sizeof(HostName));
+ gethostname(HostName, sizeof(HostName));
+
+ while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
+ {
+ if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
+ return(0);
+ if ( IsDebuggerPresent() ) {
+ switch ( CurrentState ) {
+ case SERVICE_STOPPED:
+ OutputDebugString("SERVICE_STOPPED\n");
+ break;
+ case SERVICE_START_PENDING:
+ OutputDebugString("SERVICE_START_PENDING\n");
+ break;
+ case SERVICE_STOP_PENDING:
+ OutputDebugString("SERVICE_STOP_PENDING\n");
+ break;
+ case SERVICE_RUNNING:
+ OutputDebugString("SERVICE_RUNNING\n");
+ break;
+ case SERVICE_CONTINUE_PENDING:
+ OutputDebugString("SERVICE_CONTINUE_PENDING\n");
+ break;
+ case SERVICE_PAUSE_PENDING:
+ OutputDebugString("SERVICE_PAUSE_PENDING\n");
+ break;
+ case SERVICE_PAUSED:
+ OutputDebugString("SERVICE_PAUSED\n");
+ break;
+ default:
+ OutputDebugString("UNKNOWN Service State\n");
+ }
+ }
+ if (CurrentState == SERVICE_STOPPED)
+ return(0);
+ if (CurrentState == SERVICE_RUNNING)
+ return(1);
+ Sleep(500);
+ }
+ return(0);
+}
+
+
+int
+KFW_AFS_unlog(void)
+{
+ long rc;
+ char HostName[64];
+ DWORD CurrentState;
+
+ CurrentState = 0;
+ memset(HostName, '\0', sizeof(HostName));
+ gethostname(HostName, sizeof(HostName));
+ if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
+ return(0);
+ if (CurrentState != SERVICE_RUNNING)
+ return(0);
+
+ rc = pktc_ForgetAllTokens();
+
+ return(0);
+}
+
+int
+KFW_AFS_klog(
+ krb5_context alt_ctx,
+ krb5_ccache alt_cc,
+ char *service,
+ char *cell,
+ char *realm,
+ int LifeTime,
+ char *smbname
+ )
+{
+ long rc = 0;
+ CREDENTIALS creds;
+ KTEXT_ST ticket;
+ struct ktc_principal aserver;
+ struct ktc_principal aclient;
+ char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
+ char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
+ char local_cell[MAXCELLCHARS+1];
+ char Dmycell[MAXCELLCHARS+1];
+ struct ktc_token atoken;
+ struct ktc_token btoken;
+ struct afsconf_cell ak_cellconfig; /* General information about the cell */
+ char RealmName[128];
+ char CellName[128];
+ char ServiceName[128];
+ DWORD CurrentState;
+ char HostName[64];
+ BOOL try_krb5 = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_creds increds;
+ krb5_creds * k5creds = 0;
+ krb5_error_code code;
+ krb5_principal client_principal = 0;
+ char * cname = 0, *sname = 0;
+ int i, retry = 0;
+
+ CurrentState = 0;
+ memset(HostName, '\0', sizeof(HostName));
+ gethostname(HostName, sizeof(HostName));
+ if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
+ if ( IsDebuggerPresent() )
+ OutputDebugString("Unable to retrieve AFSD Service Status\n");
+ return(-1);
+ }
+ if (CurrentState != SERVICE_RUNNING) {
+ if ( IsDebuggerPresent() )
+ OutputDebugString("AFSD Service NOT RUNNING\n");
+ return(-2);
+ }
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ memset(RealmName, '\0', sizeof(RealmName));
+ memset(CellName, '\0', sizeof(CellName));
+ memset(ServiceName, '\0', sizeof(ServiceName));
+ memset(realm_of_user, '\0', sizeof(realm_of_user));
+ memset(realm_of_cell, '\0', sizeof(realm_of_cell));
+ if (cell && cell[0])
+ strcpy(Dmycell, cell);
+ else
+ memset(Dmycell, '\0', sizeof(Dmycell));
+
+ // NULL or empty cell returns information on local cell
+ if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
+ {
+ // KFW_AFS_error(rc, "get_cellconfig()");
+ return(rc);
+ }
+
+ if ( alt_ctx ) {
+ ctx = alt_ctx;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ if ( alt_cc ) {
+ cc = alt_cc;
+ } else {
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto skip_krb5_init;
+ }
+
+ memset((char *)&increds, 0, sizeof(increds));
+
+ code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
+ if (code) {
+ if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
+ {
+ OutputDebugString("Principal Not Found for ccache\n");
+ }
+ goto skip_krb5_init;
+ }
+ i = krb5_princ_realm(ctx, client_principal)->length;
+ if (i > REALM_SZ-1)
+ i = REALM_SZ-1;
+ strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
+ realm_of_user[i] = 0;
+ try_krb5 = 1;
+
+ skip_krb5_init:
+#ifdef USE_KRB4
+ if ( !try_krb5 || !realm_of_user[0] ) {
+ if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
+ {
+ goto cleanup;
+ }
+ }
+#else
+ goto cleanup;
+#endif
+ strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
+
+ if (strlen(service) == 0)
+ strcpy(ServiceName, "afs");
+ else
+ strcpy(ServiceName, service);
+
+ if (strlen(cell) == 0)
+ strcpy(CellName, local_cell);
+ else
+ strcpy(CellName, cell);
+
+ if (strlen(realm) == 0)
+ strcpy(RealmName, realm_of_cell);
+ else
+ strcpy(RealmName, realm);
+
+ memset(&creds, '\0', sizeof(creds));
+
+ if ( try_krb5 ) {
+ int len;
+
+ /* First try service/cell@REALM */
+ if (code = pkrb5_build_principal(ctx, &increds.server,
+ strlen(RealmName),
+ RealmName,
+ ServiceName,
+ CellName,
+ 0))
+ {
+ goto cleanup;
+ }
+
+ increds.client = client_principal;
+ increds.times.endtime = 0;
+ /* Ask for DES since that is what V4 understands */
+ increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+
+
+ if ( IsDebuggerPresent() ) {
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("Getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ cname = sname = 0;
+ }
+
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ code == KRB5KRB_AP_ERR_MSG_TYPE) {
+ /* Or service@REALM */
+ pkrb5_free_principal(ctx,increds.server);
+ increds.server = 0;
+ code = pkrb5_build_principal(ctx, &increds.server,
+ strlen(RealmName),
+ RealmName,
+ ServiceName,
+ 0);
+
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ cname = sname = 0;
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ }
+
+ if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ code == KRB5KRB_AP_ERR_MSG_TYPE) &&
+ strcmp(RealmName, realm_of_cell)) {
+ /* Or service/cell@REALM_OF_CELL */
+ strcpy(RealmName, realm_of_cell);
+ pkrb5_free_principal(ctx,increds.server);
+ increds.server = 0;
+ code = pkrb5_build_principal(ctx, &increds.server,
+ strlen(RealmName),
+ RealmName,
+ ServiceName,
+ CellName,
+ 0);
+
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ cname = sname = 0;
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+
+
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ code == KRB5KRB_AP_ERR_MSG_TYPE) {
+ /* Or service@REALM_OF_CELL */
+ pkrb5_free_principal(ctx,increds.server);
+ increds.server = 0;
+ code = pkrb5_build_principal(ctx, &increds.server,
+ strlen(RealmName),
+ RealmName,
+ ServiceName,
+ 0);
+
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ cname = sname = 0;
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ }
+ }
+
+ if (code) {
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"krb5_get_credentials returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ try_krb5 = 0;
+ goto use_krb4;
+ }
+
+ /* This code inserts the entire K5 ticket into the token
+ * No need to perform a krb524 translation which is
+ * commented out in the code below
+ */
+ if (k5creds->ticket.length > MAXKTCTICKETLEN)
+ goto try_krb524d;
+
+ memset(&aserver, '\0', sizeof(aserver));
+ strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
+ strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
+
+ memset(&atoken, '\0', sizeof(atoken));
+ atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
+ atoken.startTime = k5creds->times.starttime;
+ atoken.endTime = k5creds->times.endtime;
+ memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
+ atoken.ticketLen = k5creds->ticket.length;
+ memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
+
+ retry_gettoken5:
+ rc = pktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
+ if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
+ if ( rc == KTC_NOCM && retry < 20 ) {
+ Sleep(500);
+ retry++;
+ goto retry_gettoken5;
+ }
+ goto try_krb524d;
+ }
+
+ if (atoken.kvno == btoken.kvno &&
+ atoken.ticketLen == btoken.ticketLen &&
+ !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
+ !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
+ {
+ /* Success - Nothing to do */
+ goto cleanup;
+ }
+
+ // * Reset the "aclient" structure before we call ktc_SetToken.
+ // * This structure was first set by the ktc_GetToken call when
+ // * we were comparing whether identical tokens already existed.
+
+ len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
+ strncpy(aclient.name, k5creds->client->data[0].data, len);
+ aclient.name[len] = '\0';
+
+ if ( k5creds->client->length > 1 ) {
+ char * p;
+ strcat(aclient.name, ".");
+ p = aclient.name + strlen(aclient.name);
+ len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+ strncpy(p, k5creds->client->data[1].data, len);
+ p[len] = '\0';
+ }
+ aclient.instance[0] = '\0';
+
+ strcpy(aclient.cell, realm_of_cell);
+
+ len = min(k5creds->client->realm.length,strlen(realm_of_cell));
+ if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
+ char * p;
+ strcat(aclient.name, "@");
+ p = aclient.name + strlen(aclient.name);
+ len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+ strncpy(p, k5creds->client->realm.data, len);
+ p[len] = '\0';
+ }
+
+ if ( smbname ) {
+ strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
+ aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+ } else {
+ aclient.smbname[0] = '\0';
+ }
+
+ rc = pktc_SetToken(&aserver, &atoken, &aclient, 0);
+ if (!rc)
+ goto cleanup; /* We have successfully inserted the token */
+
+ try_krb524d:
+ /* Otherwise, the ticket could have been too large so try to
+ * convert using the krb524d running with the KDC
+ */
+ code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
+ pkrb5_free_creds(ctx, k5creds);
+ if (code) {
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ try_krb5 = 0;
+ goto use_krb4;
+ }
+ } else {
+ use_krb4:
+#ifdef USE_KRB4
+ code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
+ if (code == NO_TKT_FIL) {
+ // if the problem is that we have no krb4 tickets
+ // do not attempt to continue
+ goto cleanup;
+ }
+ if (code != KSUCCESS)
+ code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
+
+ if (code != KSUCCESS)
+ {
+ if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
+ {
+ if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
+ {
+ goto cleanup;
+ }
+ }
+ else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
+ {
+ if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
+ {
+ goto cleanup;
+ }
+ }
+ else
+ {
+ goto cleanup;
+ }
+ }
+#else
+ goto cleanup;
+#endif
+ }
+
+ memset(&aserver, '\0', sizeof(aserver));
+ strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
+ strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
+
+ memset(&atoken, '\0', sizeof(atoken));
+ atoken.kvno = creds.kvno;
+ atoken.startTime = creds.issue_date;
+ atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
+ memcpy(&atoken.sessionKey, creds.session, 8);
+ atoken.ticketLen = creds.ticket_st.length;
+ memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
+
+ retry_gettoken:
+ rc = pktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
+ if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
+ if ( rc == KTC_NOCM && retry < 20 ) {
+ Sleep(500);
+ retry++;
+ goto retry_gettoken;
+ }
+ KFW_AFS_error(rc, "ktc_GetToken()");
+ code = rc;
+ goto cleanup;
+ }
+
+ if (atoken.kvno == btoken.kvno &&
+ atoken.ticketLen == btoken.ticketLen &&
+ !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
+ !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
+ {
+ goto cleanup;
+ }
+
+ // * Reset the "aclient" structure before we call ktc_SetToken.
+ // * This structure was first set by the ktc_GetToken call when
+ // * we were comparing whether identical tokens already existed.
+
+ strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
+ if (creds.pinst[0])
+ {
+ strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
+ strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
+ }
+ strcpy(aclient.instance, "");
+
+ if ( strcmp(realm_of_cell, creds.realm) )
+ {
+ strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
+ strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
+ }
+ aclient.name[MAXKTCREALMLEN-1] = '\0';
+
+ strcpy(aclient.cell, CellName);
+
+ if ( smbname ) {
+ strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
+ aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+ } else {
+ aclient.smbname[0] = '\0';
+ }
+
+ if (rc = pktc_SetToken(&aserver, &atoken, &aclient, 0))
+ {
+ KFW_AFS_error(rc, "ktc_SetToken()");
+ code = rc;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (cname)
+ pkrb5_free_unparsed_name(ctx,cname);
+ if (sname)
+ pkrb5_free_unparsed_name(ctx,sname);
+ if (client_principal)
+ pkrb5_free_principal(ctx,client_principal);
+ /* increds.client == client_principal */
+ if (increds.server)
+ pkrb5_free_principal(ctx,increds.server);
+ if (cc && (cc != alt_cc))
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+
+ return(rc? rc : code);
+}
+
+/**************************************/
+/* afs_realm_of_cell(): */
+/**************************************/
+static char *
+afs_realm_of_cell(struct afsconf_cell *cellconfig)
+{
+ static char krbrlm[REALM_SZ+1]="";
+ krb5_context ctx = 0;
+ char ** realmlist=NULL;
+ krb5_error_code r;
+
+ if (!cellconfig)
+ return 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ r = pkrb5_init_context(&ctx);
+ if ( !r )
+ r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
+ if ( !r && realmlist && realmlist[0] ) {
+ strcpy(krbrlm, realmlist[0]);
+ pkrb5_free_host_realm(ctx, realmlist);
+ }
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ if ( !krbrlm[0] )
+ {
+ char *s = krbrlm;
+ char *t = cellconfig->name;
+ int c;
+
+ while (c = *t++)
+ {
+ if (islower(c)) c=toupper(c);
+ *s++ = c;
+ }
+ *s++ = 0;
+ }
+ return(krbrlm);
+}
+
+/**************************************/
+/* KFW_AFS_get_cellconfig(): */
+/**************************************/
+int
+KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
+{
+ int rc;
+ char newcell[MAXCELLCHARS+1];
+
+ local_cell[0] = (char)0;
+ memset(cellconfig, 0, sizeof(*cellconfig));
+
+ /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
+ if (rc = pcm_GetRootCellName(local_cell))
+ {
+ return(rc);
+ }
+
+ if (strlen(cell) == 0)
+ strcpy(cell, local_cell);
+
+ /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
+ strcpy(cellconfig->name, cell);
+
+ return pcm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
+}
+
+/**************************************/
+/* get_cellconfig_callback(): */
+/**************************************/
+static long
+get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
+{
+ struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
+
+ cc->hostAddr[cc->numServers] = *addrp;
+ strcpy(cc->hostName[cc->numServers], namep);
+ cc->numServers++;
+ return(0);
+}
+
+
+/**************************************/
+/* KFW_AFS_error(): */
+/**************************************/
+void
+KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
+{
+ char message[256];
+ const char *errText;
+
+ // Using AFS defines as error messages for now, until Transarc
+ // gets back to me with "string" translations of each of these
+ // const. defines.
+ if (rc == KTC_ERROR)
+ errText = "KTC_ERROR";
+ else if (rc == KTC_TOOBIG)
+ errText = "KTC_TOOBIG";
+ else if (rc == KTC_INVAL)
+ errText = "KTC_INVAL";
+ else if (rc == KTC_NOENT)
+ errText = "KTC_NOENT";
+ else if (rc == KTC_PIOCTLFAIL)
+ errText = "KTC_PIOCTLFAIL";
+ else if (rc == KTC_NOPIOCTL)
+ errText = "KTC_NOPIOCTL";
+ else if (rc == KTC_NOCELL)
+ errText = "KTC_NOCELL";
+ else if (rc == KTC_NOCM)
+ errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
+ else
+ errText = "Unknown error!";
+
+ sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString(message);
+ OutputDebugString("\n");
+ }
+ MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
+ return;
+}
+
+static DWORD
+GetServiceStatus(
+ LPSTR lpszMachineName,
+ LPSTR lpszServiceName,
+ DWORD *lpdwCurrentState)
+{
+ DWORD hr = NOERROR;
+ SC_HANDLE schSCManager = NULL;
+ SC_HANDLE schService = NULL;
+ DWORD fdwDesiredAccess = 0;
+ SERVICE_STATUS ssServiceStatus = {0};
+ BOOL fRet = FALSE;
+
+ *lpdwCurrentState = 0;
+
+ fdwDesiredAccess = GENERIC_READ;
+
+ schSCManager = OpenSCManager(lpszMachineName,
+ NULL,
+ fdwDesiredAccess);
+
+ if(schSCManager == NULL)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ schService = OpenService(schSCManager,
+ lpszServiceName,
+ fdwDesiredAccess);
+
+ if(schService == NULL)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ fRet = QueryServiceStatus(schService,
+ &ssServiceStatus);
+
+ if(fRet == FALSE)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ *lpdwCurrentState = ssServiceStatus.dwCurrentState;
+
+cleanup:
+
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+
+ return(hr);
+}
+
+void
+UnloadFuncs(
+ FUNC_INFO fi[],
+ HINSTANCE h
+ )
+{
+ int n;
+ if (fi)
+ for (n = 0; fi[n].func_ptr_var; n++)
+ *(fi[n].func_ptr_var) = 0;
+ if (h) FreeLibrary(h);
+}
+
+int
+LoadFuncs(
+ const char* dll_name,
+ FUNC_INFO fi[],
+ HINSTANCE* ph, // [out, optional] - DLL handle
+ int* pindex, // [out, optional] - index of last func loaded (-1 if none)
+ int cleanup, // cleanup function pointers and unload on error
+ int go_on, // continue loading even if some functions cannot be loaded
+ int silent // do not pop-up a system dialog if DLL cannot be loaded
+ )
+{
+ HINSTANCE h;
+ int i, n, last_i;
+ int error = 0;
+ UINT em;
+
+ if (ph) *ph = 0;
+ if (pindex) *pindex = -1;
+
+ for (n = 0; fi[n].func_ptr_var; n++)
+ *(fi[n].func_ptr_var) = 0;
+
+ if (silent)
+ em = SetErrorMode(SEM_FAILCRITICALERRORS);
+ h = LoadLibrary(dll_name);
+ if (silent)
+ SetErrorMode(em);
+
+ if (!h)
+ return 0;
+
+ last_i = -1;
+ for (i = 0; (go_on || !error) && (i < n); i++)
+ {
+ void* p = (void*)GetProcAddress(h, fi[i].func_name);
+ if (!p)
+ error = 1;
+ else
+ {
+ last_i = i;
+ *(fi[i].func_ptr_var) = p;
+ }
+ }
+ if (pindex) *pindex = last_i;
+ if (error && cleanup && !go_on) {
+ for (i = 0; i < n; i++) {
+ *(fi[i].func_ptr_var) = 0;
+ }
+ FreeLibrary(h);
+ return 0;
+ }
+ if (ph) *ph = h;
+ if (error) return 0;
+ return 1;
+}
+
+BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
+{
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_error_code code;
+ krb5_data pwdata;
+ const char * realm = 0;
+ krb5_principal principal = 0;
+ char * pname = 0;
+ char password[PROBE_PASSWORD_LEN+1];
+ BOOL serverReachable = 0;
+
+ realm = afs_realm_of_cell(cellconfig); // do not free
+
+ code = pkrb5_build_principal(ctx, &principal, strlen(realm),
+ realm, PROBE_USERNAME, NULL, NULL);
+ if ( code ) goto cleanup;
+
+ code = KFW_get_ccache(ctx, principal, &cc);
+ if ( code ) goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, principal, &pname);
+ if ( code ) goto cleanup;
+
+ pwdata.data = password;
+ pwdata.length = PROBE_PASSWORD_LEN;
+ code = pkrb5_c_random_make_octets(ctx, &pwdata);
+ if (code) {
+ int i;
+ for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
+ password[i] = 'x';
+ }
+ password[PROBE_PASSWORD_LEN] = '\0';
+
+ code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
+ pname,
+ password,
+ 5,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0);
+ switch ( code ) {
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ case KRB5KDC_ERR_CLIENT_REVOKED:
+ case KRB5KDC_ERR_CLIENT_NOTYET:
+ case KRB5KDC_ERR_PREAUTH_FAILED:
+ case KRB5KDC_ERR_PREAUTH_REQUIRED:
+ case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
+ serverReachable = TRUE;
+ break;
+ default:
+ serverReachable = FALSE;
+ }
+
+ cleanup:
+ if ( pname )
+ pkrb5_free_unparsed_name(ctx,pname);
+ if ( principal )
+ pkrb5_free_principal(ctx,principal);
+ if (cc)
+ pkrb5_cc_close(ctx,cc);
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return serverReachable;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2003 SkyRope, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Skyrope, LLC nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission from Skyrope, LLC.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef AFSKFW_H
+#define AFSKFW_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <afs/stds.h>
+#include <afs/auth.h>
+#include <afs/cellconfig.h>
+#include <rxkad.h>
+
+#define MAXCELLCHARS 64
+#define MAXHOSTCHARS 64
+#define MAXHOSTSPERCELL 8
+#define TRANSARCAFSDAEMON "TransarcAFSDaemon"
+
+void KFW_initialize(void);
+void KFW_cleanup(void);
+int KFW_is_available(void);
+int KFW_AFS_destroy_tickets_for_cell(char *);
+int KFW_AFS_renew_expiring_tokens(void);
+int KFW_AFS_get_cred( char * username,
+ char * instance,
+ char * cell,
+ char * password,
+ int lifetime,
+ char * smbname,
+ char ** reasonP );
+int KFW_AFS_renew_token_for_cell(char * cell);
+int KFW_AFS_renew_tokens_for_all_cells(void);
+BOOL KFW_AFS_wait_for_service_start(void);
+BOOL KFW_probe_kdc(struct afsconf_cell *);
+int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
+void KFW_import_windows_lsa(void);
+
+/* From afs/krb_prot.h */
+/* values for kerb error codes */
+#define KERB_ERR_OK 0
+#define KERB_ERR_NAME_EXP 1
+#define KERB_ERR_SERVICE_EXP 2
+#define KERB_ERR_AUTH_EXP 3
+#define KERB_ERR_PKT_VER 4
+#define KERB_ERR_NAME_MAST_KEY_VER 5
+#define KERB_ERR_SERV_MAST_KEY_VER 6
+#define KERB_ERR_BYTE_ORDER 7
+#define KERB_ERR_PRINCIPAL_UNKNOWN 8
+#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
+#define KERB_ERR_NULL_KEY 10
+
+/* From afs/krb.h */
+#define RD_AP_TIME 37 /* delta_t too big */
+#define INTK_BADPW 62 /* Incorrect password */
+
+#define PROBE_USERNAME "OPENAFS-KDC-PROBE"
+#define PROBE_PASSWORD_LEN 16
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* AFSKFW_H */
/* if Integrated Logon only */
if (ISLOGONINTEGRATED(LogonOption) && !ISHIGHSECURITY(LogonOption))
{
- code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
- uname, "", cell, password,uname, 0, &pw_exp, 0,
+ if ( KFW_is_available() )
+ code = KFW_AFS_get_cred(uname, "", cell, password, 0, uname, &reason);
+ else
+ code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
+ uname, "", cell, password, uname, 0, &pw_exp, 0,
&reason);
DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2","Code[%x]",
code);
/* if Integrated Logon and High Security pass random generated name*/
else if (ISLOGONINTEGRATED(LogonOption) && ISHIGHSECURITY(LogonOption))
{
- code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
+ if ( KFW_is_available() )
+ code = KFW_AFS_get_cred(uname, "", cell, password, 0, RandomName, &reason);
+ else
+ code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
uname, "", cell, password,RandomName, 0, &pw_exp, 0,
&reason);
DebugEvent("AFS AfsLogon - (Both)ka_UserAuthenticateGeneral2","Code[%x] RandomName[%s]",
retryInterval -= sleepInterval;
}
+ /* remove any kerberos 5 tickets currently held by the SYSTEM account */
+ if ( KFW_is_available() )
+ KFW_AFS_destroy_tickets_for_cell(cell);
+
if (code) {
char msg[128];
sprintf(msg, "Integrated login failed: %s", reason);
# include the AFSD source tree on our inclusion path
-AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" -I..\afsd -I..\client_config -I..\kfw\inc\loadfuncs -I..\kfw\inc\krb5 -I..\kfw\inc\leash
+AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" -I..\afsd -I..\client_config -I..\kfw\inc\krb5
# include the primary makefile
RELDIR=WINNT\client_creds
$(OUT)\window.obj
EXECOBJS = \
- $(OUT)\afskfw.obj
+ $(OUT)\ipaddrchg.obj
EXERES = \
$(OUT)\afscreds_stub.res
$(DESTDIR)\lib\afs\TaLocale.lib \
$(DESTDIR)\lib\lanahelper.lib \
$(DESTDIR)\lib\afsrxkad.lib \
- $(DESTDIR)\lib\afsdes.lib
+ $(DESTDIR)\lib\afsdes.lib \
+ $(DESTDIR)\lib\afsauthent.lib \
+ $(DESTDIR)\lib\libafsconf.lib \
+ $(DESTDIR)\lib\afskfw.lib
############################################################################
#
#include <osithrdnt.h>
#include <osisleep.h>
#include <osibasel.h>
+#include <rxkad.h>
#ifdef __cplusplus
}
#endif
TCHAR szHelpFile[ MAX_PATH ];
osi_mutex_t expirationCheckLock;
osi_mutex_t credsLock;
+ TCHAR SmbName[ MAXRANDOMNAMELEN ];
} GLOBALS;
extern GLOBALS g;
+++ /dev/null
-/*
- * Copyright (c) 2003 SkyRope, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of Skyrope, LLC nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission from Skyrope, LLC.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Portions of this code are derived from portions of the MIT
- * Leash Ticket Manager and LoadFuncs utilities. For these portions the
- * following copyright applies.
- *
- * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
- * All rights reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-#ifndef AFSKRB5_INT_H
-#define AFSKRB5_INT_H
-
-#include <windows.h>
-#ifdef USE_MS2MIT
-#define SECURITY_WIN32
-#include <security.h>
-#include <ntsecapi.h>
-#endif /* USE_MS2MIT */
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <winsock2.h>
-
-#ifdef USE_MS2MIT
-#include <loadfuncs-lsa.h>
-#endif /* USE_MS2MIT */
-
-#include <afs/stds.h>
-#include <krb5.h>
-
-#include <rxkad.h>
-
-/* Defined in the KRBV4W32 version of krb.h but not the Kerberos V version */
-/* Required for some of the loadfuncs headers */
-typedef struct ktext far *KTEXT;
-typedef struct ktext far *KTEXT_FP;
-#include <KerberosIV/krb.h>
-
-/* AFS has its own version of com_err.h */
-typedef afs_int32 errcode_t;
-
-#include <loadfuncs-com_err.h>
-#include <loadfuncs-krb5.h>
-#include <loadfuncs-profile.h>
-#include <loadfuncs-krb.h>
-#include <loadfuncs-krb524.h>
-#include <loadfuncs-afs36.h>
-#include <loadfuncs-leash.h>
-
-// service definitions
-#define SERVICE_DLL "advapi32.dll"
-typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
-typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
-typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
-typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
-
-#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
-#define LSA_CCNAME "MSLSA:"
-
-#define PROBE_USERNAME "OPENAFS-KDC-PROBE"
-#define PROBE_PASSWORD_LEN 16
-
-#define MAXCELLCHARS 64
-#define MAXHOSTCHARS 64
-#define MAXHOSTSPERCELL 8
-#define TRANSARCAFSDAEMON "TransarcAFSDaemon"
-typedef struct {
- char name[MAXCELLCHARS];
- short numServers;
- short flags;
- struct sockaddr_in hostAddr[MAXHOSTSPERCELL];
- char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS];
- char *linkedCell;
-} afsconf_cell;
-
-struct ktc_token {
- time_t startTime;
- time_t endTime;
- struct ktc_encryptionKey sessionKey;
- short kvno; /* XXX UNALIGNED */
- int ticketLen;
- char ticket[MAXKTCTICKETLEN];
-};
-
-#define KTC_ERROR 11862784L
-#define KTC_TOOBIG 11862785L
-#define KTC_INVAL 11862786L
-#define KTC_NOENT 11862787L
-#define KTC_PIOCTLFAIL 11862788L
-#define KTC_NOPIOCTL 11862789L
-#define KTC_NOCELL 11862790L
-#define KTC_NOCM 11862791L
-
-/* User Query data structures and functions */
-
-struct textField {
- char * buf; /* Destination buffer address */
- int len; /* Destination buffer length */
- char * label; /* Label for this field */
- char * def; /* Default response for this field */
- int echo; /* 0 = no, 1 = yes, 2 = asterisks */
-};
-
-#define ID_TEXT 150
-#define ID_MID_TEXT 300
-
-struct principal_ccache_data {
- struct principal_ccache_data * next;
- char * principal;
- char * ccache_name;
- int from_lsa;
- int expired;
- int expiration_time;
- int renew;
-};
-
-struct cell_principal_map {
- struct cell_principal_map * next;
- char * cell;
- char * principal;
- int active;
-};
-
-/* In order to avoid including the private CCAPI headers */
-typedef int cc_int32;
-
-#define CC_API_VER_1 1
-#define CC_API_VER_2 2
-
-#define CCACHE_API cc_int32
-
-/*
-** The Official Error Codes
-*/
-#define CC_NOERROR 0
-#define CC_BADNAME 1
-#define CC_NOTFOUND 2
-#define CC_END 3
-#define CC_IO 4
-#define CC_WRITE 5
-#define CC_NOMEM 6
-#define CC_FORMAT 7
-#define CC_LOCKED 8
-#define CC_BAD_API_VERSION 9
-#define CC_NO_EXIST 10
-#define CC_NOT_SUPP 11
-#define CC_BAD_PARM 12
-#define CC_ERR_CACHE_ATTACH 13
-#define CC_ERR_CACHE_RELEASE 14
-#define CC_ERR_CACHE_FULL 15
-#define CC_ERR_CRED_VERSION 16
-
-enum {
- CC_CRED_VUNKNOWN = 0, // For validation
- CC_CRED_V4 = 1,
- CC_CRED_V5 = 2,
- CC_CRED_VMAX = 3 // For validation
-};
-
-typedef struct opaque_dll_control_block_type* apiCB;
-typedef struct _infoNC {
- char* name;
- char* principal;
- cc_int32 vers;
-} infoNC;
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_initialize,
- (
- apiCB** cc_ctx, // < DLL's primary control structure.
- // returned here, passed everywhere else
- cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
- cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
- const char** vendor // < if ~NULL, vendor name in read only C string
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_shutdown,
- (
- apiCB** cc_ctx // <> DLL's primary control structure. NULL after
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_get_NC_info,
- (
- apiCB* cc_ctx, // > DLL's primary control structure
- struct _infoNC*** ppNCi // < (NULL before call) null terminated,
- // list of a structs (free via cc_free_infoNC())
- )
-);
-
-TYPEDEF_FUNC(
-CCACHE_API,
-CALLCONV_C,
-cc_free_NC_info,
- (
- apiCB* cc_ctx,
- struct _infoNC*** ppNCi // < free list of structs returned by
- // cc_get_cache_names(). set to NULL on return
- )
-);
-#define CCAPI_DLL "krbcc32.dll"
-
-/* Function Prototypes */
-DWORD GetServiceStatus(LPSTR, LPSTR, DWORD *);
-void KFW_AFS_error(LONG, LPCSTR);
-
-void UnloadFuncs(FUNC_INFO [], HINSTANCE);
-int LoadFuncs(const char*, FUNC_INFO [], HINSTANCE*, int*, int, int, int);
-int KFW_get_ccache(krb5_context, krb5_principal, krb5_ccache *);
-int KFW_error(krb5_error_code, LPCSTR, int, krb5_context *, krb5_ccache *);
-int KFW_kinit(krb5_context, krb5_ccache, HWND, char *, char *, krb5_deltat,
- DWORD, DWORD, krb5_deltat, DWORD, DWORD);
-int KFW_AFS_get_cred(char *, char *, char *, char *, int, char **);
-int KFW_renew(krb5_context, krb5_ccache);
-int KFW_destroy(krb5_context, krb5_ccache);
-BOOL KFW_ms2mit(krb5_context, krb5_ccache, BOOL);
-int KFW_AFS_unlog(void);
-int KFW_AFS_klog(krb5_context, krb5_ccache, char*, char*, char*, int);
-void KFW_import_ccache_data(void);
-void KFW_import_windows_lsa(void);
-BOOL MSLSA_IsKerberosLogon();
-
-/* From afs/krb_prot.h */
-/* values for kerb error codes */
-#define KERB_ERR_OK 0
-#define KERB_ERR_NAME_EXP 1
-#define KERB_ERR_SERVICE_EXP 2
-#define KERB_ERR_AUTH_EXP 3
-#define KERB_ERR_PKT_VER 4
-#define KERB_ERR_NAME_MAST_KEY_VER 5
-#define KERB_ERR_SERV_MAST_KEY_VER 6
-#define KERB_ERR_BYTE_ORDER 7
-#define KERB_ERR_PRINCIPAL_UNKNOWN 8
-#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
-#define KERB_ERR_NULL_KEY 10
-#endif /* AFSKFW_INT_H */
+++ /dev/null
-/*
- * Copyright (c) 2003 SkyRope, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of Skyrope, LLC nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission from Skyrope, LLC.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Portions of this code are derived from portions of the MIT
- * Leash Ticket Manager and LoadFuncs utilities. For these portions the
- * following copyright applies.
- *
- * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
- * All rights reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-
-#define USE_MS2MIT
-#define USE_KRB4
-#include "afskfw-int.h"
-#include "afskfw.h"
-#include "creds.h"
-
-#include <osilog.h>
-#include <rxkad_prototypes.h> /* for life_to_time */
-
-/*
- * TIMING _____________________________________________________________________
- *
- */
-
-#define cminREMIND_TEST 1 // test every minute for expired creds
-#define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
-#define cminRENEW 20 // renew creds when there are 20 minutes remaining
-#define cminMINLIFE 30 // minimum life of Kerberos creds
-
-#define c100ns1SECOND (LONGLONG)10000000
-#define cmsec1SECOND 1000
-#define cmsec1MINUTE 60000
-#define csec1MINUTE 60
-
-/* Function Pointer Declarations for Delayed Loading */
-// CCAPI
-DECL_FUNC_PTR(cc_initialize);
-DECL_FUNC_PTR(cc_shutdown);
-DECL_FUNC_PTR(cc_get_NC_info);
-DECL_FUNC_PTR(cc_free_NC_info);
-
-// leash functions
-DECL_FUNC_PTR(Leash_get_default_lifetime);
-DECL_FUNC_PTR(Leash_get_default_forwardable);
-DECL_FUNC_PTR(Leash_get_default_renew_till);
-DECL_FUNC_PTR(Leash_get_default_noaddresses);
-DECL_FUNC_PTR(Leash_get_default_proxiable);
-DECL_FUNC_PTR(Leash_get_default_publicip);
-DECL_FUNC_PTR(Leash_get_default_use_krb4);
-DECL_FUNC_PTR(Leash_get_default_life_min);
-DECL_FUNC_PTR(Leash_get_default_life_max);
-DECL_FUNC_PTR(Leash_get_default_renew_min);
-DECL_FUNC_PTR(Leash_get_default_renew_max);
-DECL_FUNC_PTR(Leash_get_default_renewable);
-
-// krb5 functions
-DECL_FUNC_PTR(krb5_change_password);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
-DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
-DECL_FUNC_PTR(krb5_get_init_creds_password);
-DECL_FUNC_PTR(krb5_build_principal_ext);
-DECL_FUNC_PTR(krb5_cc_get_name);
-DECL_FUNC_PTR(krb5_cc_resolve);
-DECL_FUNC_PTR(krb5_cc_default);
-DECL_FUNC_PTR(krb5_cc_default_name);
-DECL_FUNC_PTR(krb5_cc_set_default_name);
-DECL_FUNC_PTR(krb5_cc_initialize);
-DECL_FUNC_PTR(krb5_cc_destroy);
-DECL_FUNC_PTR(krb5_cc_close);
-DECL_FUNC_PTR(krb5_cc_store_cred);
-DECL_FUNC_PTR(krb5_cc_copy_creds);
-DECL_FUNC_PTR(krb5_cc_retrieve_cred);
-DECL_FUNC_PTR(krb5_cc_get_principal);
-DECL_FUNC_PTR(krb5_cc_start_seq_get);
-DECL_FUNC_PTR(krb5_cc_next_cred);
-DECL_FUNC_PTR(krb5_cc_end_seq_get);
-DECL_FUNC_PTR(krb5_cc_remove_cred);
-DECL_FUNC_PTR(krb5_cc_set_flags);
-DECL_FUNC_PTR(krb5_cc_get_type);
-DECL_FUNC_PTR(krb5_free_context);
-DECL_FUNC_PTR(krb5_free_cred_contents);
-DECL_FUNC_PTR(krb5_free_principal);
-DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
-DECL_FUNC_PTR(krb5_init_context);
-DECL_FUNC_PTR(krb5_parse_name);
-DECL_FUNC_PTR(krb5_timeofday);
-DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
-DECL_FUNC_PTR(krb5_unparse_name);
-DECL_FUNC_PTR(krb5_get_credentials);
-DECL_FUNC_PTR(krb5_mk_req);
-DECL_FUNC_PTR(krb5_sname_to_principal);
-DECL_FUNC_PTR(krb5_get_credentials_renew);
-DECL_FUNC_PTR(krb5_free_data);
-DECL_FUNC_PTR(krb5_free_data_contents);
-DECL_FUNC_PTR(krb5_free_unparsed_name);
-DECL_FUNC_PTR(krb5_os_localaddr);
-DECL_FUNC_PTR(krb5_copy_keyblock_contents);
-DECL_FUNC_PTR(krb5_copy_data);
-DECL_FUNC_PTR(krb5_free_creds);
-DECL_FUNC_PTR(krb5_build_principal);
-DECL_FUNC_PTR(krb5_get_renewed_creds);
-DECL_FUNC_PTR(krb5_get_default_config_files);
-DECL_FUNC_PTR(krb5_free_config_files);
-DECL_FUNC_PTR(krb5_get_default_realm);
-DECL_FUNC_PTR(krb5_free_ticket);
-DECL_FUNC_PTR(krb5_decode_ticket);
-DECL_FUNC_PTR(krb5_get_host_realm);
-DECL_FUNC_PTR(krb5_free_host_realm);
-DECL_FUNC_PTR(krb5_free_addresses);
-DECL_FUNC_PTR(krb5_c_random_make_octets);
-
-// Krb524 functions
-DECL_FUNC_PTR(krb524_init_ets);
-DECL_FUNC_PTR(krb524_convert_creds_kdc);
-
-// krb4 functions
-DECL_FUNC_PTR(krb_get_cred);
-DECL_FUNC_PTR(tkt_string);
-DECL_FUNC_PTR(krb_get_tf_realm);
-DECL_FUNC_PTR(krb_mk_req);
-
-// ComErr functions
-DECL_FUNC_PTR(com_err);
-DECL_FUNC_PTR(error_message);
-
-// Profile functions
-DECL_FUNC_PTR(profile_init);
-DECL_FUNC_PTR(profile_release);
-DECL_FUNC_PTR(profile_get_subsection_names);
-DECL_FUNC_PTR(profile_free_list);
-DECL_FUNC_PTR(profile_get_string);
-DECL_FUNC_PTR(profile_release_string);
-
-// Service functions
-DECL_FUNC_PTR(OpenSCManagerA);
-DECL_FUNC_PTR(OpenServiceA);
-DECL_FUNC_PTR(QueryServiceStatus);
-DECL_FUNC_PTR(CloseServiceHandle);
-#ifdef USE_MS2MIT
-DECL_FUNC_PTR(LsaNtStatusToWinError);
-#endif /* USE_MS2MIT */
-
-#ifdef USE_MS2MIT
-// LSA Functions
-DECL_FUNC_PTR(LsaConnectUntrusted);
-DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
-DECL_FUNC_PTR(LsaCallAuthenticationPackage);
-DECL_FUNC_PTR(LsaFreeReturnBuffer);
-DECL_FUNC_PTR(LsaGetLogonSessionData);
-#endif /* USE_MS2MIT */
-
-// AFS36 Token Functions
-DECL_FUNC_PTR(ktc_ListTokens);
-DECL_FUNC_PTR(ktc_GetToken);
-DECL_FUNC_PTR(ktc_SetToken);
-DECL_FUNC_PTR(ktc_ForgetAllTokens);
-
-// AFS36 Config Functions
-DECL_FUNC_PTR(cm_SearchCellFile);
-DECL_FUNC_PTR(cm_GetRootCellName);
-
-// CCAPI
-FUNC_INFO ccapi_fi[] = {
- MAKE_FUNC_INFO(cc_initialize),
- MAKE_FUNC_INFO(cc_shutdown),
- MAKE_FUNC_INFO(cc_get_NC_info),
- MAKE_FUNC_INFO(cc_free_NC_info),
- END_FUNC_INFO
-};
-
-FUNC_INFO leash_fi[] = {
- MAKE_FUNC_INFO(Leash_get_default_lifetime),
- MAKE_FUNC_INFO(Leash_get_default_renew_till),
- MAKE_FUNC_INFO(Leash_get_default_forwardable),
- MAKE_FUNC_INFO(Leash_get_default_noaddresses),
- MAKE_FUNC_INFO(Leash_get_default_proxiable),
- MAKE_FUNC_INFO(Leash_get_default_publicip),
- MAKE_FUNC_INFO(Leash_get_default_use_krb4),
- MAKE_FUNC_INFO(Leash_get_default_life_min),
- MAKE_FUNC_INFO(Leash_get_default_life_max),
- MAKE_FUNC_INFO(Leash_get_default_renew_min),
- MAKE_FUNC_INFO(Leash_get_default_renew_max),
- MAKE_FUNC_INFO(Leash_get_default_renewable),
- END_FUNC_INFO
-};
-
-FUNC_INFO k5_fi[] = {
- MAKE_FUNC_INFO(krb5_change_password),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
- MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
- MAKE_FUNC_INFO(krb5_get_init_creds_password),
- MAKE_FUNC_INFO(krb5_build_principal_ext),
- MAKE_FUNC_INFO(krb5_cc_get_name),
- MAKE_FUNC_INFO(krb5_cc_resolve),
- MAKE_FUNC_INFO(krb5_cc_default),
- MAKE_FUNC_INFO(krb5_cc_default_name),
- MAKE_FUNC_INFO(krb5_cc_set_default_name),
- MAKE_FUNC_INFO(krb5_cc_initialize),
- MAKE_FUNC_INFO(krb5_cc_destroy),
- MAKE_FUNC_INFO(krb5_cc_close),
- MAKE_FUNC_INFO(krb5_cc_copy_creds),
- MAKE_FUNC_INFO(krb5_cc_store_cred),
- MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
- MAKE_FUNC_INFO(krb5_cc_get_principal),
- MAKE_FUNC_INFO(krb5_cc_start_seq_get),
- MAKE_FUNC_INFO(krb5_cc_next_cred),
- MAKE_FUNC_INFO(krb5_cc_end_seq_get),
- MAKE_FUNC_INFO(krb5_cc_remove_cred),
- MAKE_FUNC_INFO(krb5_cc_set_flags),
- MAKE_FUNC_INFO(krb5_cc_get_type),
- MAKE_FUNC_INFO(krb5_free_context),
- MAKE_FUNC_INFO(krb5_free_cred_contents),
- MAKE_FUNC_INFO(krb5_free_principal),
- MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
- MAKE_FUNC_INFO(krb5_init_context),
- MAKE_FUNC_INFO(krb5_parse_name),
- MAKE_FUNC_INFO(krb5_timeofday),
- MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
- MAKE_FUNC_INFO(krb5_unparse_name),
- MAKE_FUNC_INFO(krb5_get_credentials),
- MAKE_FUNC_INFO(krb5_mk_req),
- MAKE_FUNC_INFO(krb5_sname_to_principal),
- MAKE_FUNC_INFO(krb5_get_credentials_renew),
- MAKE_FUNC_INFO(krb5_free_data),
- MAKE_FUNC_INFO(krb5_free_data_contents),
- MAKE_FUNC_INFO(krb5_free_unparsed_name),
- MAKE_FUNC_INFO(krb5_os_localaddr),
- MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
- MAKE_FUNC_INFO(krb5_copy_data),
- MAKE_FUNC_INFO(krb5_free_creds),
- MAKE_FUNC_INFO(krb5_build_principal),
- MAKE_FUNC_INFO(krb5_get_renewed_creds),
- MAKE_FUNC_INFO(krb5_free_addresses),
- MAKE_FUNC_INFO(krb5_get_default_config_files),
- MAKE_FUNC_INFO(krb5_free_config_files),
- MAKE_FUNC_INFO(krb5_get_default_realm),
- MAKE_FUNC_INFO(krb5_free_ticket),
- MAKE_FUNC_INFO(krb5_decode_ticket),
- MAKE_FUNC_INFO(krb5_get_host_realm),
- MAKE_FUNC_INFO(krb5_free_host_realm),
- MAKE_FUNC_INFO(krb5_free_addresses),
- MAKE_FUNC_INFO(krb5_c_random_make_octets),
- END_FUNC_INFO
-};
-
-FUNC_INFO k4_fi[] = {
- MAKE_FUNC_INFO(krb_get_cred),
- MAKE_FUNC_INFO(krb_get_tf_realm),
- MAKE_FUNC_INFO(krb_mk_req),
- MAKE_FUNC_INFO(tkt_string),
- END_FUNC_INFO
-};
-
-FUNC_INFO k524_fi[] = {
- MAKE_FUNC_INFO(krb524_init_ets),
- MAKE_FUNC_INFO(krb524_convert_creds_kdc),
- END_FUNC_INFO
-};
-
-FUNC_INFO profile_fi[] = {
- MAKE_FUNC_INFO(profile_init),
- MAKE_FUNC_INFO(profile_release),
- MAKE_FUNC_INFO(profile_get_subsection_names),
- MAKE_FUNC_INFO(profile_free_list),
- MAKE_FUNC_INFO(profile_get_string),
- MAKE_FUNC_INFO(profile_release_string),
- END_FUNC_INFO
-};
-
-FUNC_INFO ce_fi[] = {
- MAKE_FUNC_INFO(com_err),
- MAKE_FUNC_INFO(error_message),
- END_FUNC_INFO
-};
-
-FUNC_INFO service_fi[] = {
- MAKE_FUNC_INFO(OpenSCManagerA),
- MAKE_FUNC_INFO(OpenServiceA),
- MAKE_FUNC_INFO(QueryServiceStatus),
- MAKE_FUNC_INFO(CloseServiceHandle),
-#ifdef USE_MS2MIT
- MAKE_FUNC_INFO(LsaNtStatusToWinError),
-#endif /* USE_MS2MIT */
- END_FUNC_INFO
-};
-
-#ifdef USE_MS2MIT
-FUNC_INFO lsa_fi[] = {
- MAKE_FUNC_INFO(LsaConnectUntrusted),
- MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
- MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
- MAKE_FUNC_INFO(LsaFreeReturnBuffer),
- MAKE_FUNC_INFO(LsaGetLogonSessionData),
- END_FUNC_INFO
-};
-#endif /* USE_MS2MIT */
-
-FUNC_INFO afst_fi[] = {
- MAKE_FUNC_INFO(ktc_ListTokens),
- MAKE_FUNC_INFO(ktc_GetToken),
- MAKE_FUNC_INFO(ktc_SetToken),
- MAKE_FUNC_INFO(ktc_ForgetAllTokens),
- END_FUNC_INFO
-};
-
-FUNC_INFO afsc_fi[] = {
- MAKE_FUNC_INFO(cm_SearchCellFile),
- MAKE_FUNC_INFO(cm_GetRootCellName),
- END_FUNC_INFO
-};
-
-/* Static Prototypes */
-static char *afs_realm_of_cell(afsconf_cell *);
-static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
-static int get_cellconfig(char *, afsconf_cell *, char *);
-static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
- void *data, const char *name, const char *banner, int num_prompts,
- krb5_prompt prompts[]);
-
-
-/* Static Declarations */
-static int inited = 0;
-static int mid_cnt = 0;
-static struct textField * mid_tb = NULL;
-static HINSTANCE hKrb5 = 0;
-static HINSTANCE hKrb4 = 0;
-static HINSTANCE hKrb524 = 0;
-#ifdef USE_MS2MIT
-static HINSTANCE hSecur32 = 0;
-#endif /* USE_MS2MIT */
-static HINSTANCE hAdvApi32 = 0;
-static HINSTANCE hAfsTokens = 0;
-static HINSTANCE hAfsConf = 0;
-static HINSTANCE hComErr = 0;
-static HINSTANCE hService = 0;
-static HINSTANCE hProfile = 0;
-static HINSTANCE hLeash = 0;
-static HINSTANCE hCCAPI = 0;
-static struct principal_ccache_data * princ_cc_data = NULL;
-static struct cell_principal_map * cell_princ_map = NULL;
-
-void
-KFW_initialize(void)
-{
- static int inited = 0;
-
- if ( !inited ) {
- char mutexName[MAX_PATH];
- HANDLE hMutex = NULL;
-
- sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
-
- hMutex = CreateMutex( NULL, TRUE, mutexName );
- if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
- if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
- return;
- }
- }
- if ( !inited ) {
- inited = 1;
- LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
- LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
- LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
-#ifdef USE_MS2MIT
- LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
-#endif /* USE_MS2MIT */
- LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
- LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
- LoadFuncs(AFSTOKENS_DLL, afst_fi, &hAfsTokens, 0, 1, 0, 0);
- LoadFuncs(AFSCONF_DLL, afsc_fi, &hAfsConf, 0, 1, 0, 0);
- LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
- LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
-
- if ( KFW_is_available() ) {
- char rootcell[MAXCELLCHARS+1];
-#ifdef USE_MS2MIT
- KFW_import_windows_lsa();
-#endif /* USE_MS2MIT */
- KFW_import_ccache_data();
- KFW_AFS_renew_expiring_tokens();
-
- /* WIN32 NOTE: no way to get max chars */
- if (!pcm_GetRootCellName(rootcell))
- KFW_AFS_renew_token_for_cell(rootcell);
- }
- }
- ReleaseMutex(hMutex);
- CloseHandle(hMutex);
- }
-}
-
-void
-KFW_cleanup(void)
-{
- if (hKrb5)
- FreeLibrary(hKrb5);
- if (hKrb4)
- FreeLibrary(hKrb4);
- if (hProfile)
- FreeLibrary(hProfile);
- if (hAfsTokens)
- FreeLibrary(hAfsTokens);
- if (hAfsConf)
- FreeLibrary(hAfsConf);
- if (hComErr)
- FreeLibrary(hComErr);
- if (hService)
- FreeLibrary(hService);
-#ifdef USE_MS2MIT
- if (hSecur32)
- FreeLibrary(hSecur32);
-#endif /* USE_MS2MIT */
- if (hKrb524)
- FreeLibrary(hKrb524);
- if (hLeash)
- FreeLibrary(hLeash);
- if (hCCAPI)
- FreeLibrary(hCCAPI);
-}
-
-static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
-
-int
-KFW_is_available(void)
-{
- HKEY parmKey;
- DWORD code, len;
- DWORD enableKFW = 1;
-
- code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
- if (code != ERROR_SUCCESS)
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
- if (code == ERROR_SUCCESS) {
- len = sizeof(enableKFW);
- code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
- (BYTE *) &enableKFW, &len);
- if (code != ERROR_SUCCESS) {
- enableKFW = 1;
- }
- RegCloseKey (parmKey);
- }
-
- if ( !enableKFW )
- return FALSE;
-
- KFW_initialize();
- if ( hKrb5 && hComErr && hService &&
-#ifdef USE_MS2MIT
- hSecur32 &&
-#endif /* USE_MS2MIT */
- hKrb524 &&
- hProfile && hAfsTokens && hAfsConf && hLeash && hCCAPI )
- return TRUE;
- return FALSE;
-}
-
-int
-KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
- int FreeContextFlag, krb5_context * ctx,
- krb5_ccache * cache)
-{
- char message[256];
- const char *errText;
- int krb5Error = ((int)(rc & 255));
-
- /*
- switch (krb5Error)
- {
- // Wrong password
- case 31:
- case 8:
- return;
- }
- */
-
- errText = perror_message(rc);
- _snprintf(message, sizeof(message),
- "%s\n(Kerberos error %ld)\n\n%s failed",
- errText,
- krb5Error,
- FailedFunctionName);
-
- if ( IsDebuggerPresent() )
- OutputDebugString(message);
-
- MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
- MB_TASKMODAL |
- MB_SETFOREGROUND);
- if (FreeContextFlag == 1)
- {
- if (ctx && *ctx != NULL)
- {
- if (cache && *cache != NULL) {
- pkrb5_cc_close(*ctx, *cache);
- *cache = NULL;
- }
-
- pkrb5_free_context(*ctx);
- *ctx = NULL;
- }
- }
-
- return rc;
-}
-
-void
-KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
-{
- struct principal_ccache_data * next = princ_cc_data;
- krb5_principal principal = 0;
- char * pname = NULL;
- const char * ccname = NULL;
- krb5_error_code code = 0;
- krb5_error_code cc_code = 0;
- krb5_cc_cursor cur;
- krb5_creds creds;
- krb5_flags flags=0;
- krb5_timestamp now;
-
- if (ctx == 0 || cc == 0)
- return;
-
- code = pkrb5_cc_get_principal(ctx, cc, &principal);
- if ( code ) return;
-
- code = pkrb5_unparse_name(ctx, principal, &pname);
- if ( code ) goto cleanup;
-
- ccname = pkrb5_cc_get_name(ctx, cc);
- if (!ccname) goto cleanup;
-
- // Search the existing list to see if we have a match
- if ( next ) {
- for ( ; next ; next = next->next ) {
- if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccname) )
- break;
- }
- }
-
- // If not, match add a new node to the beginning of the list and assign init it
- if ( !next ) {
- next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
- next->next = princ_cc_data;
- princ_cc_data = next;
- next->principal = _strdup(pname);
- next->ccache_name = _strdup(ccname);
- next->from_lsa = lsa;
- next->expired = 1;
- next->expiration_time = 0;
- next->renew = 0;
- }
-
- flags = 0; // turn off OPENCLOSE mode
- code = pkrb5_cc_set_flags(ctx, cc, flags);
- if ( code ) goto cleanup;
-
- code = pkrb5_timeofday(ctx, &now);
-
- cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
-
- while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
- if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
- int valid;
- // we found the ticket we are looking for
- // check validity of timestamp
- // We add a 5 minutes fudge factor to compensate for potential
- // clock skew errors between the KDC and client OS
-
- valid = ((creds.times.starttime > 0) &&
- now >= (creds.times.starttime - 300) &&
- now < (creds.times.endtime + 300) &&
- !(creds.ticket_flags & TKT_FLG_INVALID));
-
- if ( next->from_lsa) {
- next->expired = 0;
- next->expiration_time = creds.times.endtime;
- next->renew = 1;
- } else if ( valid ) {
- next->expired = 0;
- next->expiration_time = creds.times.endtime;
- next->renew = (creds.times.renew_till > creds.times.endtime) &&
- (creds.ticket_flags & TKT_FLG_RENEWABLE);
- } else {
- next->expired = 1;
- next->expiration_time = 0;
- next->renew = 0;
- }
-
- pkrb5_free_cred_contents(ctx, &creds);
- cc_code = KRB5_CC_END;
- break;
- }
- pkrb5_free_cred_contents(ctx, &creds);
- }
-
- if (cc_code == KRB5_CC_END) {
- code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
- if (code) goto cleanup;
- }
-
- cleanup:
- flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
- code = pkrb5_cc_set_flags(ctx, cc, flags);
-
- if ( pname )
- pkrb5_free_unparsed_name(ctx,pname);
- if ( principal )
- pkrb5_free_principal(ctx,principal);
-}
-
-int
-KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
-{
- struct principal_ccache_data * next = princ_cc_data;
- char * response = NULL;
-
- if ( !principal || !ccache )
- return 0;
-
- while ( next ) {
- if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
- if (response) {
- // we always want to prefer the MS Kerberos LSA cache or
- // the cache afscreds created specifically for the principal
- // if the current entry is either one, drop the previous find
- if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
- free(response);
- }
- response = _strdup(next->ccache_name);
- // MS Kerberos LSA is our best option so use it and quit
- if ( next->from_lsa )
- break;
- }
- next = next->next;
- }
-
- if ( response ) {
- *ccache = response;
- return 1;
- }
- return 0;
-}
-
-void
-KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
-{
- struct principal_ccache_data ** next = &princ_cc_data;
-
- if ( !pname && !ccname )
- return;
-
- while ( (*next) ) {
- if ( !strcmp((*next)->principal,pname) ||
- !strcmp((*next)->ccache_name,ccname) ) {
- void * temp;
- free((*next)->principal);
- free((*next)->ccache_name);
- temp = (*next);
- (*next) = (*next)->next;
- free(temp);
- }
- }
-}
-
-void
-KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
-{
- struct cell_principal_map * next = cell_princ_map;
-
- // Search the existing list to see if we have a match
- if ( next ) {
- for ( ; next ; next = next->next ) {
- if ( !strcmp(next->cell, cell) ) {
- if ( !strcmp(next->principal,pname) ) {
- next->active = active;
- break;
- } else {
- // OpenAFS currently has a restriction of one active token per cell
- // Therefore, whenever we update the table with a new active cell we
- // must mark all of the other principal to cell entries as inactive.
- if (active)
- next->active = 0;
- }
- }
- }
- }
-
- // If not, match add a new node to the beginning of the list and assign init it
- if ( !next ) {
- next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
- next->next = cell_princ_map;
- cell_princ_map = next;
- next->principal = _strdup(pname);
- next->cell = _strdup(cell);
- next->active = active;
- }
-}
-
-void
-KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
-{
- struct cell_principal_map ** next = &cell_princ_map;
-
- if ( !pname && !cell )
- return;
-
- while ( (*next) ) {
- if ( !strcmp((*next)->principal,pname) ||
- !strcmp((*next)->cell,cell) ) {
- void * temp;
- free((*next)->principal);
- free((*next)->cell);
- temp = (*next);
- (*next) = (*next)->next;
- free(temp);
- }
- }
-}
-
-// Returns (if possible) a principal which has been known in
-// the past to have been used to obtain tokens for the specified
-// cell.
-// TODO: Attempt to return one which has not yet expired by checking
-// the principal/ccache data
-int
-KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
-{
- struct cell_principal_map * next_map = cell_princ_map;
- const char * princ = NULL;
- int count = 0, i;
-
- if ( !cell )
- return 0;
-
- while ( next_map ) {
- if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
- count++;
- }
- next_map = next_map->next;
- }
-
- if ( !principals || !count )
- return count;
-
- *principals = (char **) malloc(sizeof(char *) * count);
- for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
- {
- if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
- (*principals)[i++] = _strdup(next_map->principal);
- }
- }
- return count;
-}
-
-int
-KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
-{
- int count = 0, i;
- struct cell_principal_map * next_map = cell_princ_map;
- const char * princ = NULL;
-
- if ( !pname )
- return 0;
-
- while ( next_map ) {
- if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
- count++;
- }
- next_map = next_map->next;
- }
-
- if ( !cells )
- return count;
-
- *cells = (char **) malloc(sizeof(char *) * count);
- for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
- {
- if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
- (*cells)[i++] = _strdup(next_map->cell);
- }
- }
- return count;
-}
-
-/* Given a principal return an existing ccache or create one and return */
-int
-KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
-{
- krb5_context ctx;
- char * pname = 0;
- char * ccname = 0;
- krb5_error_code code;
-
- if (!pkrb5_init_context)
- return 0;
-
- if ( alt_ctx ) {
- ctx = alt_ctx;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( principal ) {
- code = pkrb5_unparse_name(ctx, principal, &pname);
- if (code) goto cleanup;
-
- if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
- !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
- ccname = (char *)malloc(strlen(pname) + 5);
- sprintf(ccname,"API:%s",pname);
- }
- code = pkrb5_cc_resolve(ctx, ccname, cc);
- } else {
- code = pkrb5_cc_default(ctx, cc);
- if (code) goto cleanup;
- }
-
- cleanup:
- if (ccname)
- free(ccname);
- if (pname)
- pkrb5_free_unparsed_name(ctx,pname);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
- return(code);
-}
-
-#ifdef USE_MS2MIT
-// Import Microsoft Credentials into a new MIT ccache
-void
-KFW_import_windows_lsa(void)
-{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal princ = 0;
- char * pname = NULL;
- krb5_data * realm;
- krb5_error_code code;
- char cell[128]="";
- int i;
-
- if (!pkrb5_init_context)
- return;
-
-#ifdef COMMENT
- if ( !MSLSA_IsKerberosLogon() )
- return;
-#endif
-
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
-
- code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
- if (code) goto cleanup;
-
- KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if ( code ) goto cleanup;
-
- code = pkrb5_unparse_name(ctx,princ,&pname);
- if ( code ) goto cleanup;
-
- realm = krb5_princ_realm(ctx, princ);
- for ( i=0; i<realm->length; i++ ) {
- cell[i] = tolower(realm->data[i]);
- }
- cell[i] = '\0';
-
- code = KFW_AFS_klog(ctx, cc, "afs", cell, realm->data, pLeash_get_default_lifetime());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
- OutputDebugString(message);
- }
- if ( code ) goto cleanup;
-
- KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
-
- cleanup:
- if (pname)
- pkrb5_free_unparsed_name(ctx,pname);
- if (princ)
- pkrb5_free_principal(ctx,princ);
- if (cc)
- pkrb5_cc_close(ctx,cc);
- if (ctx)
- pkrb5_free_context(ctx);
-}
-#endif /* USE_MS2MIT */
-
-// If there are existing MIT credentials, copy them to a new
-// ccache named after the principal
-
-// Enumerate all existing MIT ccaches and construct entries
-// in the principal_ccache table
-
-// Enumerate all existing AFS Tokens and construct entries
-// in the cell_principal table
-void
-KFW_import_ccache_data(void)
-{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal principal = 0;
- krb5_creds creds;
- krb5_error_code code;
- krb5_error_code cc_code;
- krb5_cc_cursor cur;
- apiCB * cc_ctx = 0;
- struct _infoNC ** pNCi = NULL;
- int i, j, flags;
-
- if ( !pcc_initialize )
- return;
-
- if ( IsDebuggerPresent() )
- OutputDebugString("KFW_import_ccache_data()\n");
-
- code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
- if (code) goto cleanup;
-
- code = pcc_get_NC_info(cc_ctx, &pNCi);
- if (code) goto cleanup;
-
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
-
- for ( i=0; pNCi[i]; i++ ) {
- if ( pNCi[i]->vers != CC_CRED_V5 )
- continue;
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Principal: ");
- OutputDebugString(pNCi[i]->principal);
- OutputDebugString(" in ccache ");
- OutputDebugString(pNCi[i]->name);
- OutputDebugString("\n");
- }
- if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
- && strcmp(pNCi[i]->name,LSA_CCNAME)
- ) {
- int found = 0;
- for ( j=0; pNCi[j]; j++ ) {
- if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
- found = 1;
- break;
- }
- }
-
- code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
- if (code) goto loop_cleanup;
-
- if (!found) {
- krb5_ccache oldcc = 0;
-
- if ( IsDebuggerPresent() )
- OutputDebugString("copying ccache data to new ccache\n");
-
- code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
- if (code) goto loop_cleanup;
- code = pkrb5_cc_initialize(ctx, cc, principal);
- if (code) goto loop_cleanup;
-
- code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
- if (code) goto loop_cleanup;
- code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
- if (code) {
- code = pkrb5_cc_close(ctx,cc);
- cc = 0;
- code = pkrb5_cc_close(ctx,oldcc);
- cc = 0;
- KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
- continue;
- }
- code = pkrb5_cc_close(ctx,oldcc);
- }
- } else {
- code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
- if (code) goto loop_cleanup;
- }
-
- flags = 0; // turn off OPENCLOSE mode
- code = pkrb5_cc_set_flags(ctx, cc, flags);
- if ( code ) goto cleanup;
-
- KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
-
- cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
-
- while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
- krb5_data * sname = krb5_princ_name(ctx, creds.server);
- krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
- krb5_data * realm = krb5_princ_realm(ctx, creds.server);
- if ( sname && cell && !strcmp("afs",sname->data) ) {
- struct ktc_principal aserver;
- struct ktc_principal aclient;
- struct ktc_token atoken;
- int active = TRUE;
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Found AFS ticket: ");
- OutputDebugString(sname->data);
- if ( cell->data ) {
- OutputDebugString("/");
- OutputDebugString(cell->data);
- }
- OutputDebugString("@");
- OutputDebugString(realm->data);
- OutputDebugString("\n");
- }
-
- memset(&aserver, '\0', sizeof(aserver));
- strcpy(aserver.name, sname->data);
- strcpy(aserver.cell, cell->data);
-
- code = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
- if (!code) {
- // Found a token in AFS Client Server which matches
- char pname[128], *p, *q;
- for ( p=pname, q=aclient.name; *q; p++, q++)
- *p = *q;
- for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
- *p = toupper(*q);
- *p = '\0';
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Found AFS token: ");
- OutputDebugString(pname);
- OutputDebugString("\n");
- }
-
- if ( strcmp(pname,pNCi[i]->principal) )
- active = FALSE;
- KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
- } else {
- // Attempt to import it
- KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
- }
-
- code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, pLeash_get_default_lifetime());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
- OutputDebugString(message);
- }
- }
- } else if ( IsDebuggerPresent() ) {
- OutputDebugString("Found ticket: ");
- OutputDebugString(sname->data);
- if ( cell && cell->data ) {
- OutputDebugString("/");
- OutputDebugString(cell->data);
- }
- OutputDebugString("@");
- OutputDebugString(realm->data);
- OutputDebugString("\n");
- }
- pkrb5_free_cred_contents(ctx, &creds);
- }
-
- if (cc_code == KRB5_CC_END) {
- cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
- if (cc_code) goto loop_cleanup;
- }
-
- loop_cleanup:
- flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
- code = pkrb5_cc_set_flags(ctx, cc, flags);
- if (cc) {
- pkrb5_cc_close(ctx,cc);
- cc = 0;
- }
- if (principal) {
- pkrb5_free_principal(ctx,principal);
- principal = 0;
- }
- }
-
- cleanup:
- if (ctx)
- pkrb5_free_context(ctx);
- if (pNCi)
- pcc_free_NC_info(cc_ctx, &pNCi);
- if (cc_ctx)
- pcc_shutdown(&cc_ctx);
-}
-
-
-int
-KFW_AFS_get_cred(char * username,
- char * instance,
- char * cell,
- char * password,
- int lifetime,
- char ** reasonP )
-{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- char * realm = 0;
- char ** realmlist = 0;
- krb5_principal principal = 0;
- char * pname = 0;
- krb5_error_code code;
- char local_cell[MAXCELLCHARS+1];
- char **cells = NULL;
- int cell_count=0;
- afsconf_cell cellconfig;
-
- if (!pkrb5_init_context)
- return 0;
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("KFW_AFS_get_cred for token ");
- OutputDebugString(username);
- if ( instance ) {
- OutputDebugString("/");
- OutputDebugString(instance);
- }
- OutputDebugString("@");
- OutputDebugString(cell);
- OutputDebugString("\n");
- }
-
- code = pkrb5_init_context(&ctx);
- if ( code ) goto cleanup;
-
- code = get_cellconfig( cell, (void*)&cellconfig, local_cell);
- if ( code ) goto cleanup;
-
- realm = strchr(username,'@');
- if (realm) {
- *realm = '\0';
- realm++;
- }
- if ( !realm || !realm[0] )
- realm = afs_realm_of_cell(&cellconfig); // do not free
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Realm: ");
- OutputDebugString(realm);
- OutputDebugString("\n");
- }
-
- code = pkrb5_build_principal(ctx, &principal, strlen(realm),
- realm, username,
- (instance && instance[0]) ? instance : NULL,
- NULL);
-
- code = KFW_get_ccache(ctx, principal, &cc);
- if ( code ) goto cleanup;
-
- code = pkrb5_unparse_name(ctx, principal, &pname);
- if ( code ) goto cleanup;
-
- if ( lifetime == 0 )
- lifetime = pLeash_get_default_lifetime();
-
- code = KFW_kinit(ctx, cc, HWND_DESKTOP,
- pname,
- password,
- lifetime,
- pLeash_get_default_forwardable(),
- pLeash_get_default_proxiable(),
- pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
- pLeash_get_default_noaddresses(),
- pLeash_get_default_publicip());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_kinit() returns: %d\n",code);
- OutputDebugString(message);
- }
- if ( code ) goto cleanup;
-
- KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
-
- code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime);
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
- OutputDebugString(message);
- }
- if ( code ) goto cleanup;
-
- KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
-
- // Attempt to obtain new tokens for other cells supported by the same
- // principal
- cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
- if ( cell_count > 1 ) {
- while ( cell_count-- ) {
- if ( strcmp(cells[cell_count],cell) ) {
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"found another cell for the same principal: %s\n",cell);
- OutputDebugString(message);
- }
- code = get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
- if ( code ) continue;
-
- realm = afs_realm_of_cell(&cellconfig); // do not free
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Realm: ");
- OutputDebugString(realm);
- OutputDebugString("\n");
- }
-
- code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime);
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
- OutputDebugString(message);
- }
- }
- free(cells[cell_count]);
- }
- free(cells);
- } else if ( cell_count == 1 ) {
- free(cells[0]);
- free(cells);
- }
-
- cleanup:
- if ( pname )
- pkrb5_free_unparsed_name(ctx,pname);
- if ( cc )
- pkrb5_cc_close(ctx, cc);
-
- if ( code && reasonP ) {
- *reasonP = (char *)perror_message(code);
- }
- return(code);
-}
-
-int
-KFW_AFS_destroy_tickets_for_cell(char * cell)
-{
- krb5_context ctx = 0;
- krb5_error_code code;
- int count;
- char ** principals = NULL;
-
- if (!pkrb5_init_context)
- return 0;
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
- OutputDebugString(cell);
- OutputDebugString("\n");
- }
-
- code = pkrb5_init_context(&ctx);
- if (code) ctx = 0;
-
- count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
- if ( count > 0 ) {
- krb5_principal princ = 0;
- krb5_ccache cc = 0;
-
- while ( count-- ) {
- int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
- if ( cell_count > 1 ) {
- // TODO - What we really should do here is verify whether or not any of the
- // other cells which use this principal to obtain its credentials actually
- // have valid tokens or not. If they are currently using these credentials
- // we will skip them. For the time being we assume that if there is an active
- // map in the table that they are actively being used.
- goto loop_cleanup;
- }
-
- code = pkrb5_parse_name(ctx, principals[count], &princ);
- if (code) goto loop_cleanup;
-
- code = KFW_get_ccache(ctx, princ, &cc);
- if (code) goto loop_cleanup;
-
- code = pkrb5_cc_destroy(ctx, cc);
- if (!code) cc = 0;
-
- loop_cleanup:
- if ( cc ) {
- pkrb5_cc_close(ctx, cc);
- cc = 0;
- }
- if ( princ ) {
- pkrb5_free_principal(ctx, princ);
- princ = 0;
- }
-
- KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
- free(principals[count]);
- }
- free(principals);
- }
- pkrb5_free_context(ctx);
- return 0;
-}
-
-int
-KFW_AFS_renew_expiring_tokens(void)
-{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_timestamp now;
- struct principal_ccache_data * pcc_next = princ_cc_data;
- int cell_count;
- char ** cells=NULL;
- const char * realm = NULL;
- char local_cell[MAXCELLCHARS+1]="";
- afsconf_cell cellconfig;
-
- if (!pkrb5_init_context)
- return 0;
-
- if ( pcc_next == NULL ) // nothing to do
- return 0;
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
- }
-
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
-
- code = pkrb5_timeofday(ctx, &now);
- if (code) goto cleanup;
-
- for ( ; pcc_next ; pcc_next = pcc_next->next ) {
- if ( pcc_next->expired )
- continue;
-
- if ( now >= (pcc_next->expiration_time) ) {
- if ( !pcc_next->from_lsa ) {
- pcc_next->expired = 1;
- continue;
- }
- }
-
- if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
- code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
- if ( code )
- goto loop_cleanup;
- code = KFW_renew(ctx,cc);
-#ifdef USE_MS2MIT
- if ( code && pcc_next->from_lsa)
- goto loop_cleanup;
-#endif /* USE_MS2MIT */
-
-
- KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
- if (code) goto loop_cleanup;
-
- // Attempt to obtain new tokens for other cells supported by the same
- // principal
- cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
- if ( cell_count > 0 ) {
- while ( cell_count-- ) {
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Cell: ");
- OutputDebugString(cells[cell_count]);
- OutputDebugString("\n");
- }
- code = get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
- if ( code ) continue;
- realm = afs_realm_of_cell(&cellconfig); // do not free
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Realm: ");
- OutputDebugString(realm);
- OutputDebugString("\n");
- }
- code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
- OutputDebugString(message);
- }
- free(cells[cell_count]);
- }
- free(cells);
- }
- }
-
- loop_cleanup:
- if ( cc ) {
- pkrb5_cc_close(ctx,cc);
- cc = 0;
- }
- }
-
- cleanup:
- if ( cc )
- pkrb5_cc_close(ctx,cc);
- if ( ctx )
- pkrb5_free_context(ctx);
-
- return 0;
-}
-
-
-BOOL
-KFW_AFS_renew_token_for_cell(char * cell)
-{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- int count;
- char ** principals = NULL;
-
- if (!pkrb5_init_context)
- return 0;
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString("KFW_AFS_renew_token_for_cell:");
- OutputDebugString(cell);
- OutputDebugString("\n");
- }
-
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
-
- count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
- if ( count == 0 ) {
- // We know we must have a credential somewhere since we are
- // trying to renew a token
-
- KFW_import_ccache_data();
- count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
- }
- if ( count > 0 ) {
- krb5_principal princ = 0;
- krb5_principal service = 0;
-#ifdef COMMENT
- krb5_creds mcreds, creds;
-#endif /* COMMENT */
- krb5_ccache cc = 0;
- const char * realm = NULL;
- afsconf_cell cellconfig;
- char local_cell[MAXCELLCHARS+1];
-
- while ( count-- ) {
- code = pkrb5_parse_name(ctx, principals[count], &princ);
- if (code) goto loop_cleanup;
-
- code = KFW_get_ccache(ctx, princ, &cc);
- if (code) goto loop_cleanup;
-
- code = get_cellconfig( cell, (void*)&cellconfig, local_cell);
- if ( code ) goto loop_cleanup;
-
- realm = afs_realm_of_cell(&cellconfig); // do not free
- if ( IsDebuggerPresent() ) {
- OutputDebugString("Realm: ");
- OutputDebugString(realm);
- OutputDebugString("\n");
- }
-
-#ifdef COMMENT
- /* krb5_cc_remove_cred() is not implemented
- * for a single cred
- */
- code = pkrb5_build_principal(ctx, &service, strlen(realm),
- realm, "afs", cell, NULL);
- if (!code) {
- memset(&mcreds, 0, sizeof(krb5_creds));
- mcreds.client = princ;
- mcreds.server = service;
-
- code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
- if (!code) {
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, creds.client, &cname);
- pkrb5_unparse_name(ctx, creds.server, &sname);
- OutputDebugString("Removing credential for client \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- }
-
- code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
- pkrb5_free_principal(ctx, creds.client);
- pkrb5_free_principal(ctx, creds.server);
- }
- }
-#endif /* COMMENT */
-
- code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
- OutputDebugString(message);
- }
-
- loop_cleanup:
- if (cc) {
- pkrb5_cc_close(ctx, cc);
- cc = 0;
- }
- if (princ) {
- pkrb5_free_principal(ctx, princ);
- princ = 0;
- }
- if (service) {
- pkrb5_free_principal(ctx, service);
- princ = 0;
- }
-
- KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
- free(principals[count]);
- }
- free(principals);
- } else
- code = -1; // we did not renew the tokens
-
- cleanup:
- pkrb5_free_context(ctx);
- return (code ? FALSE : TRUE);
-
-}
-
-int
-KFW_AFS_renew_tokens_for_all_cells(void)
-{
- struct cell_principal_map * next = cell_princ_map;
-
- if ( IsDebuggerPresent() )
- OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
-
- if ( !next )
- return 0;
-
- for ( ; next ; next = next->next ) {
- if ( next->active )
- KFW_AFS_renew_token_for_cell(next->cell);
- }
- return 0;
-}
-
-int
-KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
-{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal me = 0;
- krb5_principal server = 0;
- krb5_creds my_creds;
- krb5_data *realm = 0;
-
- if (!pkrb5_init_context)
- return 0;
-
- memset(&my_creds, 0, sizeof(krb5_creds));
-
- if ( alt_ctx ) {
- ctx = alt_ctx;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( alt_cc ) {
- cc = alt_cc;
- } else {
- code = pkrb5_cc_default(ctx, &cc);
- if (code) goto cleanup;
- }
-
- code = pkrb5_cc_get_principal(ctx, cc, &me);
- if (code) goto cleanup;
-
- realm = krb5_princ_realm(ctx, me);
-
- code = pkrb5_build_principal_ext(ctx, &server,
- realm->length,realm->data,
- KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
- realm->length,realm->data,
- 0);
- if ( code )
- goto cleanup;
-
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, me, &cname);
- pkrb5_unparse_name(ctx, server, &sname);
- OutputDebugString("Renewing credential for client \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- }
-
- my_creds.client = me;
- my_creds.server = server;
-
- code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
- if (code) {
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
- OutputDebugString(message);
- }
- goto cleanup;
- }
-
- code = pkrb5_cc_initialize(ctx, cc, me);
- if (code) {
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
- OutputDebugString(message);
- }
- goto cleanup;
- }
-
- code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- if (code) {
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
- OutputDebugString(message);
- }
- goto cleanup;
- }
-
- cleanup:
- if (my_creds.client == me)
- my_creds.client = 0;
- if (my_creds.server == server)
- my_creds.server = 0;
- pkrb5_free_cred_contents(ctx, &my_creds);
- if (me)
- pkrb5_free_principal(ctx, me);
- if (server)
- pkrb5_free_principal(ctx, server);
- if (cc && (cc != alt_cc))
- pkrb5_cc_close(ctx, cc);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
- return(code);
-}
-
-int
-KFW_kinit( krb5_context alt_ctx,
- krb5_ccache alt_cc,
- HWND hParent,
- char *principal_name,
- char *password,
- krb5_deltat lifetime,
- DWORD forwardable,
- DWORD proxiable,
- krb5_deltat renew_life,
- DWORD addressless,
- DWORD publicIP
- )
-{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal me = 0;
- char* name = 0;
- krb5_creds my_creds;
- krb5_get_init_creds_opt options;
- krb5_address ** addrs = NULL;
- int i = 0, addr_count = 0;
-
- if (!pkrb5_init_context)
- return 0;
-
- pkrb5_get_init_creds_opt_init(&options);
- memset(&my_creds, 0, sizeof(my_creds));
-
- if (alt_ctx)
- {
- ctx = alt_ctx;
- }
- else
- {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( alt_cc ) {
- cc = alt_cc;
- } else {
- code = pkrb5_cc_default(ctx, &cc);
- if (code) goto cleanup;
- }
-
- code = pkrb5_parse_name(ctx, principal_name, &me);
- if (code)
- goto cleanup;
-
- code = pkrb5_unparse_name(ctx, me, &name);
- if (code)
- goto cleanup;
-
- if (lifetime == 0)
- lifetime = pLeash_get_default_lifetime();
- else
- lifetime *= 5*60;
-
- if (renew_life > 0)
- renew_life *= 5*60;
-
- if (lifetime)
- pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
- pkrb5_get_init_creds_opt_set_forwardable(&options,
- forwardable ? 1 : 0);
- pkrb5_get_init_creds_opt_set_proxiable(&options,
- proxiable ? 1 : 0);
- pkrb5_get_init_creds_opt_set_renew_life(&options,
- renew_life);
- if (addressless)
- pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
- else {
- if (publicIP)
- {
- // we are going to add the public IP address specified by the user
- // to the list provided by the operating system
- krb5_address ** local_addrs=NULL;
- DWORD netIPAddr;
-
- pkrb5_os_localaddr(ctx, &local_addrs);
- while ( local_addrs[i++] );
- addr_count = i + 1;
-
- addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
- if ( !addrs ) {
- pkrb5_free_addresses(ctx, local_addrs);
- goto cleanup;
- }
- memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
- i = 0;
- while ( local_addrs[i] ) {
- addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
- if (addrs[i] == NULL) {
- pkrb5_free_addresses(ctx, local_addrs);
- goto cleanup;
- }
-
- addrs[i]->magic = local_addrs[i]->magic;
- addrs[i]->addrtype = local_addrs[i]->addrtype;
- addrs[i]->length = local_addrs[i]->length;
- addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
- if (!addrs[i]->contents) {
- pkrb5_free_addresses(ctx, local_addrs);
- goto cleanup;
- }
-
- memcpy(addrs[i]->contents,local_addrs[i]->contents,
- local_addrs[i]->length); /* safe */
- i++;
- }
- pkrb5_free_addresses(ctx, local_addrs);
-
- addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
- if (addrs[i] == NULL)
- goto cleanup;
-
- addrs[i]->magic = KV5M_ADDRESS;
- addrs[i]->addrtype = AF_INET;
- addrs[i]->length = 4;
- addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
- if (!addrs[i]->contents)
- goto cleanup;
-
- netIPAddr = htonl(publicIP);
- memcpy(addrs[i]->contents,&netIPAddr,4);
-
- pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
-
- }
- }
-
- code = pkrb5_get_init_creds_password(ctx,
- &my_creds,
- me,
- password, // password
- KRB5_prompter, // prompter
- hParent, // prompter data
- 0, // start time
- 0, // service name
- &options);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_initialize(ctx, cc, me);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- if (code)
- goto cleanup;
-
- cleanup:
- if ( addrs ) {
- for ( i=0;i<addr_count;i++ ) {
- if ( addrs[i] ) {
- if ( addrs[i]->contents )
- free(addrs[i]->contents);
- free(addrs[i]);
- }
- }
- }
- if (my_creds.client == me)
- my_creds.client = 0;
- pkrb5_free_cred_contents(ctx, &my_creds);
- if (name)
- pkrb5_free_unparsed_name(ctx, name);
- if (me)
- pkrb5_free_principal(ctx, me);
- if (cc && (cc != alt_cc))
- pkrb5_cc_close(ctx, cc);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
- return(code);
-}
-
-
-int
-KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
-{
- krb5_context ctx;
- krb5_ccache cc;
- krb5_error_code code;
-
- if (!pkrb5_init_context)
- return 0;
-
- if (alt_ctx)
- {
- ctx = alt_ctx;
- }
- else
- {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( alt_cc ) {
- cc = alt_cc;
- } else {
- code = pkrb5_cc_default(ctx, &cc);
- if (code) goto cleanup;
- }
-
- code = pkrb5_cc_destroy(ctx, cc);
- if ( !code ) cc = 0;
-
- cleanup:
- if (cc && (cc != alt_cc))
- pkrb5_cc_close(ctx, cc);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
-
- return(code);
-}
-
-
-#ifdef USE_MS2MIT
-static BOOL
-GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
-{
- NTSTATUS Status = 0;
- HANDLE TokenHandle;
- TOKEN_STATISTICS Stats;
- DWORD ReqLen;
- BOOL Success;
-
- if (!ppSessionData)
- return FALSE;
- *ppSessionData = NULL;
-
- Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
- if ( !Success )
- return FALSE;
-
- Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
- CloseHandle( TokenHandle );
- if ( !Success )
- return FALSE;
-
- Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
- if ( FAILED(Status) || !ppSessionData )
- return FALSE;
-
- return TRUE;
-}
-
-//
-// MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
-// cache. It validates whether or not it is reasonable to assume that if we
-// attempted to retrieve valid tickets we could do so. Microsoft does not
-// automatically renew expired tickets. Therefore, the cache could contain
-// expired or invalid tickets. Microsoft also caches the user's password
-// and will use it to retrieve new TGTs if the cache is empty and tickets
-// are requested.
-
-static BOOL
-MSLSA_IsKerberosLogon(VOID)
-{
- PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
- BOOL Success = FALSE;
-
- if ( GetSecurityLogonSessionData(&pSessionData) ) {
- if ( pSessionData->AuthenticationPackage.Buffer ) {
- WCHAR buffer[256];
- WCHAR *usBuffer;
- int usLength;
-
- Success = FALSE;
- usBuffer = (pSessionData->AuthenticationPackage).Buffer;
- usLength = (pSessionData->AuthenticationPackage).Length;
- if (usLength < 256)
- {
- lstrcpynW (buffer, usBuffer, usLength);
- lstrcatW (buffer,L"");
- if ( !lstrcmpW(L"Kerberos",buffer) )
- Success = TRUE;
- }
- }
- pLsaFreeReturnBuffer(pSessionData);
- }
- return Success;
-}
-#endif /* USE_MS2MIT */
-
-static BOOL CALLBACK
-MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
-{
- int i;
-
- switch ( message ) {
- case WM_INITDIALOG:
- if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
- {
- SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
- return FALSE;
- }
- for ( i=0; i < mid_cnt ; i++ ) {
- if (mid_tb[i].echo == 0)
- SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
- else if (mid_tb[i].echo == 2)
- SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
- }
- return TRUE;
-
- case WM_COMMAND:
- switch ( LOWORD(wParam) ) {
- case IDOK:
- for ( i=0; i < mid_cnt ; i++ ) {
- if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
- *mid_tb[i].buf = '\0';
- }
- /* fallthrough */
- case IDCANCEL:
- EndDialog(hDialog, LOWORD(wParam));
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static LPWORD
-lpwAlign( LPWORD lpIn )
-{
- ULONG ul;
-
- ul = (ULONG) lpIn;
- ul += 3;
- ul >>=2;
- ul <<=2;
- return (LPWORD) ul;;
-}
-
-/*
- * dialog widths are measured in 1/4 character widths
- * dialog height are measured in 1/8 character heights
- */
-
-static LRESULT
-MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
- char * ptext[], int numlines, int width,
- int tb_cnt, struct textField * tb)
-{
- HGLOBAL hgbl;
- LPDLGTEMPLATE lpdt;
- LPDLGITEMTEMPLATE lpdit;
- LPWORD lpw;
- LPWSTR lpwsz;
- LRESULT ret;
- int nchar, i, pwid;
-
- hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
- if (!hgbl)
- return -1;
-
- mid_cnt = tb_cnt;
- mid_tb = tb;
-
- lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
-
- // Define a dialog box.
-
- lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
- | DS_MODALFRAME | WS_CAPTION | DS_CENTER
- | DS_SETFOREGROUND | DS_3DLOOK
- | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
- lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
- lpdt->x = 10;
- lpdt->y = 10;
- lpdt->cx = 20 + width * 4;
- lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
-
- lpw = (LPWORD) (lpdt + 1);
- *lpw++ = 0; // no menu
- *lpw++ = 0; // predefined dialog box class (by default)
-
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
- lpw += nchar;
- *lpw++ = 8; // font size (points)
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
- -1, lpwsz, 128);
- lpw += nchar;
-
- //-----------------------
- // Define an OK button.
- //-----------------------
- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
- lpdit = (LPDLGITEMTEMPLATE) lpw;
- lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
- lpdit->dwExtendedStyle = 0;
- lpdit->x = (lpdt->cx - 14)/4 - 20;
- lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
- lpdit->cx = 40;
- lpdit->cy = 14;
- lpdit->id = IDOK; // OK button identifier
-
- lpw = (LPWORD) (lpdit + 1);
- *lpw++ = 0xFFFF;
- *lpw++ = 0x0080; // button class
-
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
- lpw += nchar;
- *lpw++ = 0; // no creation data
-
- //-----------------------
- // Define an Cancel button.
- //-----------------------
- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
- lpdit = (LPDLGITEMTEMPLATE) lpw;
- lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
- lpdit->dwExtendedStyle = 0;
- lpdit->x = (lpdt->cx - 14)*3/4 - 20;
- lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
- lpdit->cx = 40;
- lpdit->cy = 14;
- lpdit->id = IDCANCEL; // CANCEL button identifier
-
- lpw = (LPWORD) (lpdit + 1);
- *lpw++ = 0xFFFF;
- *lpw++ = 0x0080; // button class
-
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
- lpw += nchar;
- *lpw++ = 0; // no creation data
-
- /* Add controls for preface data */
- for ( i=0; i<numlines; i++) {
- /*-----------------------
- * Define a static text control.
- *-----------------------*/
- lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
- lpdit = (LPDLGITEMTEMPLATE) lpw;
- lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
- lpdit->dwExtendedStyle = 0;
- lpdit->x = 10;
- lpdit->y = 10 + i * 14;
- lpdit->cx = strlen(ptext[i]) * 4 + 10;
- lpdit->cy = 14;
- lpdit->id = ID_TEXT + i; // text identifier
-
- lpw = (LPWORD) (lpdit + 1);
- *lpw++ = 0xFFFF;
- *lpw++ = 0x0082; // static class
-
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
- -1, lpwsz, 2*width);
- lpw += nchar;
- *lpw++ = 0; // no creation data
- }
-
- for ( i=0, pwid = 0; i<tb_cnt; i++) {
- if ( pwid < strlen(tb[i].label) )
- pwid = strlen(tb[i].label);
- }
-
- for ( i=0; i<tb_cnt; i++) {
- /* Prompt */
- /*-----------------------
- * Define a static text control.
- *-----------------------*/
- lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
- lpdit = (LPDLGITEMTEMPLATE) lpw;
- lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
- lpdit->dwExtendedStyle = 0;
- lpdit->x = 10;
- lpdit->y = 10 + (numlines + i + 1) * 14;
- lpdit->cx = pwid * 4;
- lpdit->cy = 14;
- lpdit->id = ID_TEXT + numlines + i; // text identifier
-
- lpw = (LPWORD) (lpdit + 1);
- *lpw++ = 0xFFFF;
- *lpw++ = 0x0082; // static class
-
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
- -1, lpwsz, 128);
- lpw += nchar;
- *lpw++ = 0; // no creation data
-
- /*-----------------------
- * Define an edit control.
- *-----------------------*/
- lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
- lpdit = (LPDLGITEMTEMPLATE) lpw;
- lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
- lpdit->dwExtendedStyle = 0;
- lpdit->x = 10 + (pwid + 1) * 4;
- lpdit->y = 10 + (numlines + i + 1) * 14;
- lpdit->cx = (width - (pwid + 1)) * 4;
- lpdit->cy = 14;
- lpdit->id = ID_MID_TEXT + i; // identifier
-
- lpw = (LPWORD) (lpdit + 1);
- *lpw++ = 0xFFFF;
- *lpw++ = 0x0081; // edit class
-
- lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
- -1, lpwsz, 128);
- lpw += nchar;
- *lpw++ = 0; // no creation data
- }
-
- GlobalUnlock(hgbl);
- ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
- hwndOwner, (DLGPROC) MultiInputDialogProc);
- GlobalFree(hgbl);
-
- switch ( ret ) {
- case 0: /* Timeout */
- return -1;
- case IDOK:
- return 1;
- case IDCANCEL:
- return 0;
- default: {
- char buf[256];
- sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
- MessageBox(hwndOwner,
- buf,
- "GetLastError()",
- MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
- return -1;
- }
- }
-}
-
-static int
-multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
-{
- HINSTANCE hInst = 0;
- int maxwidth = 0;
- int numlines = 0;
- int len;
- char * plines[16], *p = preface ? preface : "";
- int i;
-
- for ( i=0; i<16; i++ )
- plines[i] = NULL;
-
- while (*p && numlines < 16) {
- plines[numlines++] = p;
- for ( ;*p && *p != '\r' && *p != '\n'; p++ );
- if ( *p == '\r' && *(p+1) == '\n' ) {
- *p++ = '\0';
- p++;
- } else if ( *p == '\n' ) {
- *p++ = '\0';
- }
- if ( strlen(plines[numlines-1]) > maxwidth )
- maxwidth = strlen(plines[numlines-1]);
- }
-
- for ( i=0;i<n;i++ ) {
- len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
- if ( maxwidth < len )
- maxwidth = len;
- }
-
- return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb));
-}
-
-static krb5_error_code KRB5_CALLCONV
-KRB5_prompter( krb5_context context,
- void *data,
- const char *name,
- const char *banner,
- int num_prompts,
- krb5_prompt prompts[])
-{
- krb5_error_code errcode = 0;
- int i;
- struct textField * tb = NULL;
- int len = 0, blen=0, nlen=0;
- HWND hParent = (HWND)data;
-
- if (name)
- nlen = strlen(name)+2;
-
- if (banner)
- blen = strlen(banner)+2;
-
- tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
- if ( tb != NULL ) {
- int ok;
- memset(tb,0,sizeof(struct textField) * num_prompts);
- for ( i=0; i < num_prompts; i++ ) {
- tb[i].buf = prompts[i].reply->data;
- tb[i].len = prompts[i].reply->length;
- tb[i].label = prompts[i].prompt;
- tb[i].def = NULL;
- tb[i].echo = (prompts[i].hidden ? 2 : 1);
- }
-
- ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
- if ( ok ) {
- for ( i=0; i < num_prompts; i++ )
- prompts[i].reply->length = strlen(prompts[i].reply->data);
- } else
- errcode = -2;
- }
-
- if ( tb )
- free(tb);
- if (errcode) {
- for (i = 0; i < num_prompts; i++) {
- memset(prompts[i].reply->data, 0, prompts[i].reply->length);
- }
- }
- return errcode;
-}
-
-BOOL
-KFW_AFS_wait_for_service_start(void)
-{
- char HostName[64];
- DWORD CurrentState;
-
- CurrentState = SERVICE_START_PENDING;
- memset(HostName, '\0', sizeof(HostName));
- gethostname(HostName, sizeof(HostName));
-
- while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
- {
- if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
- return(0);
- if ( IsDebuggerPresent() ) {
- switch ( CurrentState ) {
- case SERVICE_STOPPED:
- OutputDebugString("SERVICE_STOPPED\n");
- break;
- case SERVICE_START_PENDING:
- OutputDebugString("SERVICE_START_PENDING\n");
- break;
- case SERVICE_STOP_PENDING:
- OutputDebugString("SERVICE_STOP_PENDING\n");
- break;
- case SERVICE_RUNNING:
- OutputDebugString("SERVICE_RUNNING\n");
- break;
- case SERVICE_CONTINUE_PENDING:
- OutputDebugString("SERVICE_CONTINUE_PENDING\n");
- break;
- case SERVICE_PAUSE_PENDING:
- OutputDebugString("SERVICE_PAUSE_PENDING\n");
- break;
- case SERVICE_PAUSED:
- OutputDebugString("SERVICE_PAUSED\n");
- break;
- default:
- OutputDebugString("UNKNOWN Service State\n");
- }
- }
- if (CurrentState == SERVICE_STOPPED)
- return(0);
- if (CurrentState == SERVICE_RUNNING)
- return(1);
- Sleep(500);
- }
- return(0);
-}
-
-
-int
-KFW_AFS_unlog(void)
-{
- long rc;
- char HostName[64];
- DWORD CurrentState;
-
- CurrentState = 0;
- memset(HostName, '\0', sizeof(HostName));
- gethostname(HostName, sizeof(HostName));
- if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
- return(0);
- if (CurrentState != SERVICE_RUNNING)
- return(0);
-
- rc = pktc_ForgetAllTokens();
-
- return(0);
-}
-
-int
-KFW_AFS_klog(
- krb5_context alt_ctx,
- krb5_ccache alt_cc,
- char *service,
- char *cell,
- char *realm,
- int LifeTime
- )
-{
- long rc = 0;
- CREDENTIALS creds;
- KTEXT_ST ticket;
- struct ktc_principal aserver;
- struct ktc_principal aclient;
- char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
- char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
- char local_cell[MAXCELLCHARS+1];
- char Dmycell[MAXCELLCHARS+1];
- struct ktc_token atoken;
- struct ktc_token btoken;
- afsconf_cell ak_cellconfig; /* General information about the cell */
- char RealmName[128];
- char CellName[128];
- char ServiceName[128];
- DWORD CurrentState;
- char HostName[64];
- BOOL try_krb5 = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_creds increds;
- krb5_creds * k5creds = 0;
- krb5_error_code code;
- krb5_principal client_principal = 0;
- char * cname = 0, *sname = 0;
- int i, retry = 0;
-
- CurrentState = 0;
- memset(HostName, '\0', sizeof(HostName));
- gethostname(HostName, sizeof(HostName));
- if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
- if ( IsDebuggerPresent() )
- OutputDebugString("Unable to retrieve AFSD Service Status\n");
- return(-1);
- }
- if (CurrentState != SERVICE_RUNNING) {
- if ( IsDebuggerPresent() )
- OutputDebugString("AFSD Service NOT RUNNING\n");
- return(-2);
- }
-
- if (!pkrb5_init_context)
- return 0;
-
- memset(RealmName, '\0', sizeof(RealmName));
- memset(CellName, '\0', sizeof(CellName));
- memset(ServiceName, '\0', sizeof(ServiceName));
- memset(realm_of_user, '\0', sizeof(realm_of_user));
- memset(realm_of_cell, '\0', sizeof(realm_of_cell));
- if (cell && cell[0])
- strcpy(Dmycell, cell);
- else
- memset(Dmycell, '\0', sizeof(Dmycell));
-
- // NULL or empty cell returns information on local cell
- if (rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
- {
- // KFW_AFS_error(rc, "get_cellconfig()");
- return(rc);
- }
-
- if ( alt_ctx ) {
- ctx = alt_ctx;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
- }
-
- if ( alt_cc ) {
- cc = alt_cc;
- } else {
- code = pkrb5_cc_default(ctx, &cc);
- if (code) goto skip_krb5_init;
- }
-
- memset((char *)&increds, 0, sizeof(increds));
-
- code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
- if (code) {
- if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
- {
- OutputDebugString("Principal Not Found for ccache\n");
- }
- goto skip_krb5_init;
- }
- i = krb5_princ_realm(ctx, client_principal)->length;
- if (i > REALM_SZ-1)
- i = REALM_SZ-1;
- strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
- realm_of_user[i] = 0;
- try_krb5 = 1;
-
- skip_krb5_init:
-#ifdef USE_KRB4
- if ( !try_krb5 || !realm_of_user[0] ) {
- if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
- {
- goto cleanup;
- }
- }
-#else
- goto cleanup;
-#endif
- strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
-
- if (strlen(service) == 0)
- strcpy(ServiceName, "afs");
- else
- strcpy(ServiceName, service);
-
- if (strlen(cell) == 0)
- strcpy(CellName, local_cell);
- else
- strcpy(CellName, cell);
-
- if (strlen(realm) == 0)
- strcpy(RealmName, realm_of_cell);
- else
- strcpy(RealmName, realm);
-
- memset(&creds, '\0', sizeof(creds));
-
- if ( try_krb5 ) {
- int i, len;
- char *p;
-
- /* First try service/cell@REALM */
- if (code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0))
- {
- goto cleanup;
- }
-
- increds.client = client_principal;
- increds.times.endtime = 0;
- /* Ask for DES since that is what V4 understands */
- increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-
-
- if ( IsDebuggerPresent() ) {
- pkrb5_unparse_name(ctx, increds.client, &cname);
- pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("Getting tickets for \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- cname = sname = 0;
- }
-
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
- if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) {
- /* Or service@REALM */
- pkrb5_free_principal(ctx,increds.server);
- increds.server = 0;
- code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
- ServiceName,
- 0);
-
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, increds.client, &cname);
- pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- cname = sname = 0;
- }
-
- if (!code)
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
- }
-
- if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) &&
- strcmp(RealmName, realm_of_cell)) {
- /* Or service/cell@REALM_OF_CELL */
- strcpy(RealmName, realm_of_cell);
- pkrb5_free_principal(ctx,increds.server);
- increds.server = 0;
- code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0);
-
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, increds.client, &cname);
- pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- cname = sname = 0;
- }
-
- if (!code)
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
-
-
- if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
- code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) {
- /* Or service@REALM_OF_CELL */
- pkrb5_free_principal(ctx,increds.server);
- increds.server = 0;
- code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
- ServiceName,
- 0);
-
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, increds.client, &cname);
- pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- cname = sname = 0;
- }
-
- if (!code)
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
- }
- }
-
- if (code) {
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"krb5_get_credentials returns: %d\n",code);
- OutputDebugString(message);
- }
- try_krb5 = 0;
- goto use_krb4;
- }
-
- /* This code inserts the entire K5 ticket into the token
- * No need to perform a krb524 translation which is
- * commented out in the code below
- */
- if (k5creds->ticket.length > MAXKTCTICKETLEN)
- goto try_krb524d;
-
- memset(&aserver, '\0', sizeof(aserver));
- strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
- strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
-
- memset(&atoken, '\0', sizeof(atoken));
- atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
- atoken.startTime = k5creds->times.starttime;
- atoken.endTime = k5creds->times.endtime;
- memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
- atoken.ticketLen = k5creds->ticket.length;
- memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
-
- retry_gettoken5:
- rc = pktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
- if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
- if ( rc == KTC_NOCM && retry < 20 ) {
- Sleep(500);
- retry++;
- goto retry_gettoken5;
- }
- goto try_krb524d;
- }
-
- if (atoken.kvno == btoken.kvno &&
- atoken.ticketLen == btoken.ticketLen &&
- !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
- !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
- {
- /* Success - Nothing to do */
- goto cleanup;
- }
-
- // * Reset the "aclient" structure before we call ktc_SetToken.
- // * This structure was first set by the ktc_GetToken call when
- // * we were comparing whether identical tokens already existed.
-
- len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
- strncpy(aclient.name, k5creds->client->data[0].data, len);
- aclient.name[len] = '\0';
-
- if ( k5creds->client->length > 1 ) {
- char * p;
- strcat(aclient.name, ".");
- p = aclient.name + strlen(aclient.name);
- len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
- strncpy(p, k5creds->client->data[1].data, len);
- p[len] = '\0';
- }
- aclient.instance[0] = '\0';
-
- strcpy(aclient.cell, realm_of_cell);
-
- len = min(k5creds->client->realm.length,strlen(realm_of_cell));
- if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
- char * p;
- strcat(aclient.name, "@");
- p = aclient.name + strlen(aclient.name);
- len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
- strncpy(p, k5creds->client->realm.data, len);
- p[len] = '\0';
- }
-
- aclient.smbname[0] = '\0';
-
- rc = pktc_SetToken(&aserver, &atoken, &aclient, 0);
- if (!rc)
- goto cleanup; /* We have successfully inserted the token */
-
- try_krb524d:
- /* Otherwise, the ticket could have been too large so try to
- * convert using the krb524d running with the KDC
- */
- code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
- pkrb5_free_creds(ctx, k5creds);
- if (code) {
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
- OutputDebugString(message);
- }
- try_krb5 = 0;
- goto use_krb4;
- }
- } else {
- use_krb4:
-#ifdef USE_KRB4
- code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
- if (code == NO_TKT_FIL) {
- // if the problem is that we have no krb4 tickets
- // do not attempt to continue
- goto cleanup;
- }
- if (code != KSUCCESS)
- code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
-
- if (code != KSUCCESS)
- {
- if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
- {
- if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
- {
- goto cleanup;
- }
- }
- else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
- {
- if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
- {
- goto cleanup;
- }
- }
- else
- {
- goto cleanup;
- }
- }
-#else
- goto cleanup;
-#endif
- }
-
- memset(&aserver, '\0', sizeof(aserver));
- strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
- strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
-
- memset(&atoken, '\0', sizeof(atoken));
- atoken.kvno = creds.kvno;
- atoken.startTime = creds.issue_date;
- atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
- memcpy(&atoken.sessionKey, creds.session, 8);
- atoken.ticketLen = creds.ticket_st.length;
- memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
-
- retry_gettoken:
- rc = pktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
- if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
- if ( rc == KTC_NOCM && retry < 20 ) {
- Sleep(500);
- retry++;
- goto retry_gettoken;
- }
- KFW_AFS_error(rc, "ktc_GetToken()");
- code = rc;
- goto cleanup;
- }
-
- if (atoken.kvno == btoken.kvno &&
- atoken.ticketLen == btoken.ticketLen &&
- !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
- !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
- {
- goto cleanup;
- }
-
- // * Reset the "aclient" structure before we call ktc_SetToken.
- // * This structure was first set by the ktc_GetToken call when
- // * we were comparing whether identical tokens already existed.
-
- strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
- if (creds.pinst[0])
- {
- strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
- strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
- }
- strcpy(aclient.instance, "");
-
- if ( strcmp(realm_of_cell, creds.realm) )
- {
- char * p;
- strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
- strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
- }
- aclient.name[MAXKTCREALMLEN-1] = '\0';
-
- strcpy(aclient.cell, CellName);
-
- if (rc = pktc_SetToken(&aserver, &atoken, &aclient, 0))
- {
- KFW_AFS_error(rc, "ktc_SetToken()");
- code = rc;
- goto cleanup;
- }
-
- cleanup:
- if (cname)
- pkrb5_free_unparsed_name(ctx,cname);
- if (sname)
- pkrb5_free_unparsed_name(ctx,sname);
- if (client_principal)
- pkrb5_free_principal(ctx,client_principal);
- /* increds.client == client_principal */
- if (increds.server)
- pkrb5_free_principal(ctx,increds.server);
- if (cc && (cc != alt_cc))
- pkrb5_cc_close(ctx, cc);
- if (ctx && (ctx != alt_ctx))
- pkrb5_free_context(ctx);
-
- return(rc? rc : code);
-}
-
-/**************************************/
-/* afs_realm_of_cell(): */
-/**************************************/
-static char *
-afs_realm_of_cell(afsconf_cell *cellconfig)
-{
- static char krbrlm[REALM_SZ+1]="";
- krb5_context ctx = 0;
- char ** realmlist=NULL;
- krb5_error_code r;
-
- if (!cellconfig)
- return 0;
-
- if (!pkrb5_init_context)
- return 0;
-
- r = pkrb5_init_context(&ctx);
- if ( !r )
- r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
- if ( !r && realmlist && realmlist[0] ) {
- strcpy(krbrlm, realmlist[0]);
- pkrb5_free_host_realm(ctx, realmlist);
- }
- if (ctx)
- pkrb5_free_context(ctx);
-
- if ( !krbrlm[0] )
- {
- char *s = krbrlm;
- char *t = cellconfig->name;
- int c;
-
- while (c = *t++)
- {
- if (islower(c)) c=toupper(c);
- *s++ = c;
- }
- *s++ = 0;
- }
- return(krbrlm);
-}
-
-/**************************************/
-/* get_cellconfig(): */
-/**************************************/
-static int
-get_cellconfig(char *cell, afsconf_cell *cellconfig, char *local_cell)
-{
- int rc;
- char newcell[MAXCELLCHARS+1];
-
- local_cell[0] = (char)0;
- memset(cellconfig, 0, sizeof(*cellconfig));
-
- /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
- if (rc = pcm_GetRootCellName(local_cell))
- {
- return(rc);
- }
-
- if (strlen(cell) == 0)
- strcpy(cell, local_cell);
-
- /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
- strcpy(cellconfig->name, cell);
-
- return pcm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
-}
-
-/**************************************/
-/* get_cellconfig_callback(): */
-/**************************************/
-static long
-get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
-{
- afsconf_cell *cc = (afsconf_cell *)cellconfig;
-
- cc->hostAddr[cc->numServers] = *addrp;
- strcpy(cc->hostName[cc->numServers], namep);
- cc->numServers++;
- return(0);
-}
-
-
-/**************************************/
-/* KFW_AFS_error(): */
-/**************************************/
-void
-KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
-{
- char message[256];
- const char *errText;
-
- // Using AFS defines as error messages for now, until Transarc
- // gets back to me with "string" translations of each of these
- // const. defines.
- if (rc == KTC_ERROR)
- errText = "KTC_ERROR";
- else if (rc == KTC_TOOBIG)
- errText = "KTC_TOOBIG";
- else if (rc == KTC_INVAL)
- errText = "KTC_INVAL";
- else if (rc == KTC_NOENT)
- errText = "KTC_NOENT";
- else if (rc == KTC_PIOCTLFAIL)
- errText = "KTC_PIOCTLFAIL";
- else if (rc == KTC_NOPIOCTL)
- errText = "KTC_NOPIOCTL";
- else if (rc == KTC_NOCELL)
- errText = "KTC_NOCELL";
- else if (rc == KTC_NOCM)
- errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
- else
- errText = "Unknown error!";
-
- sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
-
- if ( IsDebuggerPresent() ) {
- OutputDebugString(message);
- OutputDebugString("\n");
- }
- MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
- return;
-}
-
-static DWORD
-GetServiceStatus(
- LPSTR lpszMachineName,
- LPSTR lpszServiceName,
- DWORD *lpdwCurrentState)
-{
- DWORD hr = NOERROR;
- SC_HANDLE schSCManager = NULL;
- SC_HANDLE schService = NULL;
- DWORD fdwDesiredAccess = 0;
- SERVICE_STATUS ssServiceStatus = {0};
- BOOL fRet = FALSE;
-
- *lpdwCurrentState = 0;
-
- fdwDesiredAccess = GENERIC_READ;
-
- schSCManager = OpenSCManager(lpszMachineName,
- NULL,
- fdwDesiredAccess);
-
- if(schSCManager == NULL)
- {
- hr = GetLastError();
- goto cleanup;
- }
-
- schService = OpenService(schSCManager,
- lpszServiceName,
- fdwDesiredAccess);
-
- if(schService == NULL)
- {
- hr = GetLastError();
- goto cleanup;
- }
-
- fRet = QueryServiceStatus(schService,
- &ssServiceStatus);
-
- if(fRet == FALSE)
- {
- hr = GetLastError();
- goto cleanup;
- }
-
- *lpdwCurrentState = ssServiceStatus.dwCurrentState;
-
-cleanup:
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
-
- return(hr);
-}
-
-void
-UnloadFuncs(
- FUNC_INFO fi[],
- HINSTANCE h
- )
-{
- int n;
- if (fi)
- for (n = 0; fi[n].func_ptr_var; n++)
- *(fi[n].func_ptr_var) = 0;
- if (h) FreeLibrary(h);
-}
-
-int
-LoadFuncs(
- const char* dll_name,
- FUNC_INFO fi[],
- HINSTANCE* ph, // [out, optional] - DLL handle
- int* pindex, // [out, optional] - index of last func loaded (-1 if none)
- int cleanup, // cleanup function pointers and unload on error
- int go_on, // continue loading even if some functions cannot be loaded
- int silent // do not pop-up a system dialog if DLL cannot be loaded
- )
-{
- HINSTANCE h;
- int i, n, last_i;
- int error = 0;
- UINT em;
-
- if (ph) *ph = 0;
- if (pindex) *pindex = -1;
-
- for (n = 0; fi[n].func_ptr_var; n++)
- *(fi[n].func_ptr_var) = 0;
-
- if (silent)
- em = SetErrorMode(SEM_FAILCRITICALERRORS);
- h = LoadLibrary(dll_name);
- if (silent)
- SetErrorMode(em);
-
- if (!h)
- return 0;
-
- last_i = -1;
- for (i = 0; (go_on || !error) && (i < n); i++)
- {
- void* p = (void*)GetProcAddress(h, fi[i].func_name);
- if (!p)
- error = 1;
- else
- {
- last_i = i;
- *(fi[i].func_ptr_var) = p;
- }
- }
- if (pindex) *pindex = last_i;
- if (error && cleanup && !go_on) {
- for (i = 0; i < n; i++) {
- *(fi[i].func_ptr_var) = 0;
- }
- FreeLibrary(h);
- return 0;
- }
- if (ph) *ph = h;
- if (error) return 0;
- return 1;
-}
-
-#ifdef USE_FSPROBE
-// Cell Accessibility Functions
-// based on work originally submitted to the CMU Computer Club
-// by Jeffrey Hutzelman
-//
-// These would work great if the fsProbe interface had been
-// ported to Windows
-
-static
-void probeComplete()
-{
- fsprobe_Cleanup(1);
- rx_Finalize();
-}
-
-struct ping_params {
- unsigned short port; // in
- int retry_delay; // in seconds
- int verbose; // in
- struct {
- int wait; // in seconds
- int retry; // in attempts
- } host;
- int max_hosts; // in
- int hosts_attempted; // out
-}
-
-// the fsHandler is where we receive the answer to the probe
-static
-int fsHandler(void)
-{
- ping_count = fsprobe_Results.probeNum;
- if (!*fsprobe_Results.probeOK)
- {
- ok_count++;
- if (waiting) complete();
- }
- if (ping_count == retry)
- complete();
- return 0;
-}
-
-// ping_fs is a callback routine meant to be called from within
-// cm_SearchCellFile() or cm_SearchCellDNS()
-static long
-pingFS(void *ping_params, struct sockaddr_in *addrp, char *namep)
-{
- int rc;
- struct ping_params * pp = (struct ping_params *) ping_params;
-
- if ( pp->max_hosts && pp->hosts_attempted >= pp->max_hosts )
- return 0;
-
- pp->hosts_attempted++;
-
- if (pp->port && addrp->sin_port != htons(pp->port))
- addrp->sin_port = htons(pp->port);
-
- rc = fsprobe_Init(1, addrp, pp->retry_delay, fsHandler, pp->verbose);
- if (rc)
- {
- fprintf(stderr, "fsprobe_Init failed (%d)\n", rc);
- fsprobe_Cleanup(1);
- return 0;
- }
-
- for (;;)
- {
- tv.tv_sec = pp->host.wait;
- tv.tv_usec = 0;
- if (IOMGR_Select(0, 0, 0, 0, &tv))
- break;
- }
- probeComplete();
- return(0);
-}
-
-
-static BOOL
-pingCell(char *cell)
-{
- int rc;
- char rootcell[MAXCELLCHARS+1];
- char newcell[MAXCELLCHARS+1];
- struct ping_params pp;
-
- memset(&pp, 0, sizeof(struct ping_params));
-
- if (!cell || strlen(cell) == 0) {
- /* WIN32 NOTE: no way to get max chars */
- if (rc = pcm_GetRootCellName(rootcell))
- return(FALSE);
- cell = rootcell;
- }
-
- pp.port = 7000; // AFS FileServer
- pp.retry_delay = 10;
- pp.max_hosts = 3;
- pp.host.wait = 30;
- pp.host.retry = 0;
- pp.verbose = 1;
-
- /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
- rc = pcm_SearchCellFile(cell, newcell, pingFS, (void *)&pp);
-}
-#endif /* USE_FSPROBE */
-
-// These two items are imported from afscreds.h
-// but it cannot be included without causing conflicts
-#define c100ns1SECOND (LONGLONG)10000000
-static void
-TimeToSystemTime (SYSTEMTIME *pst, time_t TimeT)
-{
- struct tm *pTime;
- memset (pst, 0x00, sizeof(SYSTEMTIME));
-
- if ((pTime = localtime (&TimeT)) != NULL)
- {
- pst->wYear = pTime->tm_year + 1900;
- pst->wMonth = pTime->tm_mon + 1;
- pst->wDayOfWeek = pTime->tm_wday;
- pst->wDay = pTime->tm_mday;
- pst->wHour = pTime->tm_hour;
- pst->wMinute = pTime->tm_min;
- pst->wSecond = pTime->tm_sec;
- pst->wMilliseconds = 0;
- }
-}
-
-void
-ObtainTokensFromUserIfNeeded(HWND hWnd)
-{
- char * rootcell = NULL;
- char cell[MAXCELLCHARS+1] = "";
- char password[PROBE_PASSWORD_LEN+1];
- krb5_data pwdata;
- afsconf_cell cellconfig;
- struct ktc_principal aserver;
- struct ktc_principal aclient;
- struct ktc_token atoken;
- krb5_context ctx = 0;
- krb5_timestamp now = 0;
- krb5_error_code code;
- int serverReachable = 0;
- int rc;
-#ifndef USE_FSPROBE
- krb5_ccache cc = 0;
- const char * realm = 0;
- krb5_principal principal = 0;
- char * pname = 0;
-#endif /* USE_FSPROBE */
- DWORD CurrentState;
- char HostName[64];
- int use_kfw = KFW_is_available();
-
- CurrentState = 0;
- memset(HostName, '\0', sizeof(HostName));
- gethostname(HostName, sizeof(HostName));
- if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
- return;
- if (CurrentState != SERVICE_RUNNING) {
- SendMessage(hWnd, WM_START_SERVICE, FALSE, 0L);
- return;
- }
-
- if (!pkrb5_init_context)
- return;
-
- if ( use_kfw ) {
- code = pkrb5_init_context(&ctx);
- if ( code ) goto cleanup;
- }
-
- rootcell = (char *)GlobalAlloc(GPTR,MAXCELLCHARS+1);
- if ( !rootcell ) goto cleanup;
-
- code = get_cellconfig(cell, (void*)&cellconfig, rootcell);
- if ( code ) goto cleanup;
-
- memset(&aserver, '\0', sizeof(aserver));
- strcpy(aserver.name, "afs");
- strcpy(aserver.cell, rootcell);
-
- rc = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
-
- if ( use_kfw ) {
- code = pkrb5_timeofday(ctx, &now);
- if ( code )
- now = 0;
-
- if (!rc && (now < atoken.endTime))
- goto cleanup;
-
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d now = %ul endTime = %ul\n",
- rc, now, atoken.endTime);
- OutputDebugString(message);
- }
- } else {
- SYSTEMTIME stNow;
- FILETIME ftNow;
- FILETIME ftExpires;
- LONGLONG llNow;
- LONGLONG llExpires;
- SYSTEMTIME stExpires;
-
- TimeToSystemTime (&stExpires, atoken.endTime);
- GetLocalTime (&stNow);
- SystemTimeToFileTime (&stNow, &ftNow);
- SystemTimeToFileTime (&stExpires, &ftExpires);
-
- llNow = (((LONGLONG)ftNow.dwHighDateTime) << 32) + (LONGLONG)(ftNow.dwLowDateTime);
- llExpires = (((LONGLONG)ftExpires.dwHighDateTime) << 32) + (LONGLONG)(ftExpires.dwLowDateTime);
-
- llNow /= c100ns1SECOND;
- llExpires /= c100ns1SECOND;
-
- if (!rc && (llNow < llExpires))
- goto cleanup;
-
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d now = %ul endTime = %ul\n",
- rc, llNow, llExpires);
- OutputDebugString(message);
- }
- }
-
-
-#ifdef USE_FSPROBE
- serverReachable = cellPing(NULL);
-#else
- if ( use_kfw ) {
- // If we can't use the FSProbe interface we can attempt to forge
- // a kinit and if we can back an invalid user error we know the
- // kdc is at least reachable
- realm = afs_realm_of_cell(&cellconfig); // do not free
-
- code = pkrb5_build_principal(ctx, &principal, strlen(realm),
- realm, PROBE_USERNAME, NULL, NULL);
- if ( code ) goto cleanup;
-
- code = KFW_get_ccache(ctx, principal, &cc);
- if ( code ) goto cleanup;
-
- code = pkrb5_unparse_name(ctx, principal, &pname);
- if ( code ) goto cleanup;
-
- pwdata.data = password;
- pwdata.length = PROBE_PASSWORD_LEN;
- code = pkrb5_c_random_make_octets(ctx, &pwdata);
- if (code) {
- int i;
- for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
- password[i] = 'x';
- }
- password[PROBE_PASSWORD_LEN] = '\0';
-
- code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
- pname,
- password,
- 5,
- 0,
- 0,
- 0,
- 1,
- 0);
- switch ( code ) {
- case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- case KRB5KDC_ERR_CLIENT_REVOKED:
- case KRB5KDC_ERR_CLIENT_NOTYET:
- case KRB5KDC_ERR_PREAUTH_FAILED:
- case KRB5KDC_ERR_PREAUTH_REQUIRED:
- case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
- serverReachable = TRUE;
- break;
- default:
- serverReachable = FALSE;
- }
- } else {
- int i;
-
- for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
- password[i] = 'x';
-
- code = ObtainNewCredentials(rootcell, PROBE_USERNAME, password, TRUE);
- switch ( code ) {
- case INTK_BADPW:
- case KERB_ERR_PRINCIPAL_UNKNOWN:
- case KERB_ERR_SERVICE_EXP:
- case RD_AP_TIME:
- serverReachable = TRUE;
- break;
- default:
- serverReachable = FALSE;
- }
- }
-#endif
- if ( !serverReachable ) {
- if ( IsDebuggerPresent() )
- OutputDebugString("Server Unreachable\n");
- goto cleanup;
- }
-
- if ( IsDebuggerPresent() )
- OutputDebugString("Server Reachable\n");
-
- if ( use_kfw ) {
-#ifdef USE_MS2MIT
- KFW_import_windows_lsa();
-#endif /* USE_MS2MIT */
- KFW_AFS_renew_expiring_tokens();
- KFW_AFS_renew_token_for_cell(rootcell);
-
- rc = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
- if (!rc && (now < atoken.endTime))
- goto cleanup;
- }
-
- SendMessage(hWnd, WM_OBTAIN_TOKENS, FALSE, (long)rootcell);
- rootcell = NULL; // rootcell freed by message receiver
-
- cleanup:
- if (rootcell)
- GlobalFree(rootcell);
-
-#ifndef USE_FSPROBE
- if (KFW_is_available()) {
- if ( pname )
- pkrb5_free_unparsed_name(ctx,pname);
- if ( principal )
- pkrb5_free_principal(ctx,principal);
- if (cc)
- pkrb5_cc_close(ctx,cc);
-#endif /* USE_FSPROBE */
- if (ctx)
- pkrb5_free_context(ctx);
- }
- return;
-}
-
-// IP Change Monitoring Functions
-#include <Iphlpapi.h>
-
-DWORD
-GetNumOfIpAddrs(void)
-{
- PMIB_IPADDRTABLE pIpAddrTable = NULL;
- ULONG dwSize;
- DWORD code;
- DWORD index;
- DWORD validAddrs = 0;
-
- dwSize = 0;
- code = GetIpAddrTable(NULL, &dwSize, 0);
- if (code == ERROR_INSUFFICIENT_BUFFER) {
- pIpAddrTable = malloc(dwSize);
- code = GetIpAddrTable(pIpAddrTable, &dwSize, 0);
- if ( code == NO_ERROR ) {
- for ( index=0; index < pIpAddrTable->dwNumEntries; index++ ) {
- if (pIpAddrTable->table[index].dwAddr != 0)
- validAddrs++;
- }
- }
- free(pIpAddrTable);
- }
- return validAddrs;
-}
-
-void
-IpAddrChangeMonitor(void * hWnd)
-{
-#ifdef USE_OVERLAPPED
- HANDLE Handle = INVALID_HANDLE_VALUE; /* Do Not Close This Handle */
- OVERLAPPED Ovlap;
-#endif /* USE_OVERLAPPED */
- DWORD Result;
- DWORD prevNumOfAddrs = GetNumOfIpAddrs();
- DWORD NumOfAddrs;
- char message[256];
-
- if ( !hWnd )
- return;
-
- while ( TRUE ) {
-#ifdef USE_OVERLAPPED
- ZeroMemory(&Ovlap, sizeof(OVERLAPPED));
-
- Result = NotifyAddrChange(&Handle,&Ovlap);
- if (Result != ERROR_IO_PENDING)
- {
- if ( IsDebuggerPresent() ) {
- sprintf(message, "NotifyAddrChange() failed with error %d \n", Result);
- OutputDebugString(message);
- }
- break;
- }
-
- if ((Result = WaitForSingleObject(Handle,INFINITE)) != WAIT_OBJECT_0)
- {
- if ( IsDebuggerPresent() ) {
- sprintf(message, "WaitForSingleObject() failed with error %d\n",
- GetLastError());
- OutputDebugString(message);
- }
- continue;
- }
-
- if (GetOverlappedResult(Handle, &Ovlap,
- &DataTransfered, TRUE) == 0)
- {
- if ( IsDebuggerPresent() ) {
- sprintf(message, "GetOverlapped result failed %d \n",
- GetLastError());
- OutputDebugString(message);
- }
- break;
- }
-#else
- Result = NotifyAddrChange(NULL,NULL);
- if (Result != NO_ERROR)
- {
- if ( IsDebuggerPresent() ) {
- sprintf(message, "NotifyAddrChange() failed with error %d \n", Result);
- OutputDebugString(message);
- }
- break;
- }
-#endif
-
- NumOfAddrs = GetNumOfIpAddrs();
-
- if ( IsDebuggerPresent() ) {
- sprintf(message,"IPAddrChangeMonitor() NumOfAddrs: now %d was %d\n",
- NumOfAddrs, prevNumOfAddrs);
- OutputDebugString(message);
- }
-
- if ( NumOfAddrs != prevNumOfAddrs ) {
- // Give AFS Client Service a chance to notice and die
- // Or for network services to startup
- Sleep(2000);
- // this call should probably be mutex protected
- ObtainTokensFromUserIfNeeded(hWnd);
- }
- prevNumOfAddrs = NumOfAddrs;
- }
-}
-
-
-DWORD
-IpAddrChangeMonitorInit(HWND hWnd)
-{
- DWORD status = ERROR_SUCCESS;
- HANDLE thread;
- ULONG threadID = 0;
-
- thread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)IpAddrChangeMonitor,
- hWnd, 0, &threadID);
-
- if (thread == NULL) {
- status = GetLastError();
- }
- CloseHandle(thread);
- return status;
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2003 SkyRope, LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of Skyrope, LLC nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission from Skyrope, LLC.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef AFSKFW_H
-#define AFSKFW_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-void KFW_initialize(void);
-void KFW_cleanup(void);
-int KFW_is_available(void);
-int KFW_AFS_destroy_tickets_for_cell(char *);
-int KFW_AFS_renew_expiring_tokens(void);
-int KFW_AFS_get_cred( char * username,
- char * instance,
- char * cell,
- char * password,
- int lifetime,
- char ** reasonP );
-int KFW_AFS_renew_token_for_cell(char * cell);
-int KFW_AFS_renew_tokens_for_all_cells(void);
-BOOL KFW_AFS_wait_for_service_start(void);
-
-#define WM_OBTAIN_TOKENS (WM_USER+77)
-#define WM_START_SERVICE (WM_USER+78)
-void ObtainTokensFromUserIfNeeded(HWND hWnd);
-DWORD IpAddrChangeMonitorInit(HWND hWnd);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* AFSKFW_H */
* directory or online at http://www.openafs.org/dl/license10.html
*/
-#include "afscreds.h"
-#include "afskfw.h"
-
extern "C" {
#include <afs\stds.h>
#include <afs\param.h>
#include <afs\auth.h>
#include <afs\kautils.h>
+#include <rxkad.h>
#include <afs\cm_config.h>
+#include <afs\afskfw.h>
+#include "ipaddrchg.h"
}
+#include "afscreds.h"
+
/*
* DEFINITIONS ________________________________________________________________
char szPasswordA[ 256 ];
CopyStringToAnsi (szPasswordA, pszPassword);
+ char szSmbNameA[ MAXRANDOMNAMELEN ];
+ CopyStringToAnsi (szSmbNameA, g.SmbName);
+
int Expiration = 0;
if ( KFW_is_available() )
- rc = KFW_AFS_get_cred(szNameA, NULL, szCellA, szPasswordA, 0, &Result);
- else
+ rc = KFW_AFS_get_cred(szNameA, NULL, szCellA, szPasswordA, 0, szSmbNameA[0] ? szSmbNameA : NULL, &Result);
+ else if ( szSmbNameA[0] )
+ rc = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
+ szNameA, "", szCellA, szPasswordA, szSmbNameA, 0, &Expiration, 0, &Result);
+ else
rc = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, szNameA, "", szCellA, szPasswordA, 0, &Expiration, 0, &Result);
}
#include <afs/stds.h>
#include <osilog.h>
#include <afs/fs_utils.h>
+#include <rxkad.h>
+#include <afs/afskfw.h>
+#include "ipaddrchg.h"
}
#include "afscreds.h"
#include "drivemap.h"
#include <stdlib.h>
#include <stdio.h>
-#include "rxkad.h"
-#include "afskfw.h"
/*
* DEFINITIONS ________________________________________________________________
BOOL fNetDetect = FALSE;
BOOL fRenewMaps = FALSE;
+ // Initialize our global variables and window classes
+ //
+ memset (&g, 0x00, sizeof(g));
+ g.fStartup = TRUE;
+
// Parse the command-line
//
while (pszCmdLineA && *pszCmdLineA)
break;
case ':':
+ CopyAnsiToString(g.SmbName,pszCmdLineA);
MapShareName(pszCmdLineA);
break;
if (fExit || fUninstall || fInstall)
return FALSE;
- // Initialize our global variables and window classes
- //
- memset (&g, 0x00, sizeof(g));
- g.fStartup = TRUE;
-
HKEY hk;
if (RegOpenKey (HKEY_CURRENT_USER, REGSTR_PATH_OPENAFS_CLIENT, &hk) == 0)
{
extern "C" {
#include <afs/param.h>
#include <afs/stds.h>
+#include <afs/afskfw.h>
+#include "ipaddrchg.h"
}
#include "afscreds.h"
-#include "afskfw.h"
-
/*
* DEFINITIONS ________________________________________________________________