]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
afskfw-library-20040504
authorJeffrey Altman <jaltman@mit.edu>
Tue, 4 May 2004 23:48:15 +0000 (23:48 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 4 May 2004 23:48:15 +0000 (23:48 +0000)
Migrate KFW functionality from src/WINNT/client_creds/afskfw* into a
a new library to be shared by afslogon.dll, afscreds.exe

Add KFW support to afslogon.dll

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================

Migrate KFW functionality from src/WINNT/client_creds/afskfw* into a
a new library to be shared by afslogon.dll, afscreds.exe

Move IP Address Change Monitor into new source files.

Add smbname support to the KFW set token functionality in afscreds.exe

13 files changed:
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afskfw-int.h [new file with mode: 0644]
src/WINNT/afsd/afskfw.c [new file with mode: 0644]
src/WINNT/afsd/afskfw.h [new file with mode: 0644]
src/WINNT/afsd/afslogon.c
src/WINNT/client_creds/NTMakefile
src/WINNT/client_creds/afscreds.h
src/WINNT/client_creds/afskfw-int.h [deleted file]
src/WINNT/client_creds/afskfw.c [deleted file]
src/WINNT/client_creds/afskfw.h [deleted file]
src/WINNT/client_creds/creds.cpp
src/WINNT/client_creds/main.cpp
src/WINNT/client_creds/window.cpp

index a0c28404d095daf4190a2efbf65e87694368d220..a99b91f143b23f1befdbdf718a170e7601e9e487 100644 (file)
@@ -5,7 +5,7 @@
 # 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)
@@ -63,7 +63,8 @@ INCFILES =\
        $(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
@@ -174,6 +175,32 @@ $(CONF_DLLFILE): $(CONFOBJS) $(OUT)\libafsconf.res $(CONF_DLLLIBS)
        $(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
 
@@ -185,7 +212,10 @@ LOGON_DLLOBJS =\
 
 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
@@ -212,19 +242,6 @@ $(LOG95_DLLFILE): $(LOG95_DLLOBJS) $(LOG95_DLLLIBS)
        $(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
 
diff --git a/src/WINNT/afsd/afskfw-int.h b/src/WINNT/afsd/afskfw-int.h
new file mode 100644 (file)
index 0000000..329b836
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * 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 */
diff --git a/src/WINNT/afsd/afskfw.c b/src/WINNT/afsd/afskfw.c
new file mode 100644 (file)
index 0000000..38402c2
--- /dev/null
@@ -0,0 +1,3209 @@
+/*
+ * 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;
+}
+
diff --git a/src/WINNT/afsd/afskfw.h b/src/WINNT/afsd/afskfw.h
new file mode 100644 (file)
index 0000000..d856013
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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 */
index 9e6bac9742080076ad6acc0a1c83917f59a017a2..6fd8924f3431eefcdba9f1c3822af658fc7c8e52 100644 (file)
@@ -427,8 +427,11 @@ DWORD APIENTRY NPLogonNotify(
         /* 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);
@@ -443,7 +446,10 @@ DWORD APIENTRY NPLogonNotify(
         /* 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]",
@@ -499,6 +505,10 @@ DWORD APIENTRY NPLogonNotify(
         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);
index 461d5dcb50117630e847449db34b2fd0043d45c1..9d72cfc97810c41a9da104c9955ef335d679719a 100644 (file)
@@ -7,7 +7,7 @@
 
 # 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
@@ -35,7 +35,7 @@ EXEOBJS = \
        $(OUT)\window.obj
 
 EXECOBJS = \
-    $(OUT)\afskfw.obj
+    $(OUT)\ipaddrchg.obj
 
 EXERES = \
        $(OUT)\afscreds_stub.res
@@ -67,7 +67,10 @@ EXELIBS = \
        $(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
 
 ############################################################################
 #
index a5aad5b3c600d2ef25e40392d90b454172118ea4..524457e40a4cd7543e875a599bf8e84a21976c8a 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 #include <osithrdnt.h>
 #include <osisleep.h>
 #include <osibasel.h>
+#include <rxkad.h>
 #ifdef __cplusplus
 }
 #endif
@@ -92,6 +93,7 @@ typedef struct
    TCHAR szHelpFile[ MAX_PATH ];
    osi_mutex_t expirationCheckLock;
    osi_mutex_t credsLock;
+   TCHAR SmbName[ MAXRANDOMNAMELEN ];
    } GLOBALS;
 
 extern GLOBALS g;
diff --git a/src/WINNT/client_creds/afskfw-int.h b/src/WINNT/client_creds/afskfw-int.h
deleted file mode 100644 (file)
index 139bceb..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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 */
diff --git a/src/WINNT/client_creds/afskfw.c b/src/WINNT/client_creds/afskfw.c
deleted file mode 100644 (file)
index d64df21..0000000
+++ /dev/null
@@ -1,3597 +0,0 @@
-/*
- * 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;
-}
-
diff --git a/src/WINNT/client_creds/afskfw.h b/src/WINNT/client_creds/afskfw.h
deleted file mode 100644 (file)
index a34341b..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 */
index 930418c79f0be59ef190678a37e593e30071ae71..7cf0c594c0399b20e1263a7d0ff4624d15f2a677 100644 (file)
@@ -7,17 +7,19 @@
  * 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 ________________________________________________________________
@@ -390,11 +392,17 @@ int ObtainNewCredentials (LPCTSTR pszCell, LPCTSTR pszUser, LPCTSTR pszPassword,
       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);
       }
 
index 6a977c567ab373e5903559cd2b27e9855ca6dd59..ce24a9bf9dcf2c2c08eb32a3109cafeabd3ce40d 100644 (file)
@@ -12,6 +12,9 @@ extern "C" {
 #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"
@@ -19,8 +22,6 @@ extern "C" {
 #include "drivemap.h"
 #include <stdlib.h>
 #include <stdio.h>
-#include "rxkad.h"
-#include "afskfw.h"
 
 /*
  * DEFINITIONS ________________________________________________________________
@@ -93,6 +94,11 @@ BOOL InitApp (LPSTR pszCmdLineA)
    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)
@@ -143,6 +149,7 @@ BOOL InitApp (LPSTR pszCmdLineA)
             break;
 
                 case ':':
+             CopyAnsiToString(g.SmbName,pszCmdLineA);
                         MapShareName(pszCmdLineA);
                         break;
 
@@ -205,11 +212,6 @@ BOOL InitApp (LPSTR pszCmdLineA)
    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)
     {
index e80b0b3eacf3d37d97bacf825e18daa58e7a9a8c..73ae6daaf533ac3d860ae001f675f1ad04fe9cbc 100644 (file)
 extern "C" {
 #include <afs/param.h>
 #include <afs/stds.h>
+#include <afs/afskfw.h>
+#include "ipaddrchg.h"
 }
 
 #include "afscreds.h"
-#include "afskfw.h"
-
 
 /*
  * DEFINITIONS ________________________________________________________________