windows-cell-name-length-consistency-20080806
[openafs.git] / src / WINNT / afsd / afskfw.c
index d86ad7a..8b53df9 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
  * Copyright (c) 2003 SkyRope, LLC
  * All rights reserved.
  * 
  */
 
 
-#define USE_MS2MIT
 #undef  USE_KRB4
+#ifndef _WIN64
+#define USE_KRB524 1
+#endif
+#define USE_MS2MIT 1
+#define USE_LEASH 1
+
 #include "afskfw-int.h"
 #include "afskfw.h"
+#include <userenv.h>
+
+#include <Sddl.h>
+#include <Aclapi.h>
 
 #include <osilog.h>
-#include <rxkad_prototypes.h>   /* for life_to_time */
 #include <afs/ptserver.h>
 #include <afs/ptuser.h>
+#include <rx/rxkad.h>
 
 #include <WINNT\afsreg.h>
 
@@ -89,6 +99,7 @@ DECL_FUNC_PTR(cc_shutdown);
 DECL_FUNC_PTR(cc_get_NC_info);
 DECL_FUNC_PTR(cc_free_NC_info);
 
+#ifdef USE_LEASH
 // leash functions
 DECL_FUNC_PTR(Leash_get_default_lifetime);
 DECL_FUNC_PTR(Leash_get_default_forwardable);
@@ -103,6 +114,7 @@ DECL_FUNC_PTR(Leash_get_default_renew_min);
 DECL_FUNC_PTR(Leash_get_default_renew_max);
 DECL_FUNC_PTR(Leash_get_default_renewable);
 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
+#endif 
 
 // krb5 functions
 DECL_FUNC_PTR(krb5_change_password);
@@ -165,15 +177,19 @@ DECL_FUNC_PTR(krb5_free_host_realm);
 DECL_FUNC_PTR(krb5_free_addresses);
 DECL_FUNC_PTR(krb5_c_random_make_octets);
 
+#ifdef USE_KRB524
 // Krb524 functions
 DECL_FUNC_PTR(krb524_init_ets);
 DECL_FUNC_PTR(krb524_convert_creds_kdc);
+#endif
 
+#ifdef USE_KRB4
 // 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);
+#endif
 
 // ComErr functions
 DECL_FUNC_PTR(com_err);
@@ -214,6 +230,7 @@ FUNC_INFO ccapi_fi[] = {
     END_FUNC_INFO
 };
 
+#ifdef USE_LEASH
 FUNC_INFO leash_fi[] = {
     MAKE_FUNC_INFO(Leash_get_default_lifetime),
     MAKE_FUNC_INFO(Leash_get_default_renew_till),
@@ -234,6 +251,7 @@ FUNC_INFO leash_opt_fi[] = {
     MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
     END_FUNC_INFO
 };
+#endif
 
 FUNC_INFO k5_fi[] = {
     MAKE_FUNC_INFO(krb5_change_password),
@@ -309,11 +327,13 @@ FUNC_INFO k4_fi[] = {
 };
 #endif
 
+#ifdef USE_KRB524
 FUNC_INFO k524_fi[] = {
     MAKE_FUNC_INFO(krb524_init_ets),
     MAKE_FUNC_INFO(krb524_convert_creds_kdc),
     END_FUNC_INFO
 };
+#endif
 
 FUNC_INFO profile_fi[] = {
         MAKE_FUNC_INFO(profile_init),
@@ -370,7 +390,9 @@ static HINSTANCE hKrb5 = 0;
 #ifdef USE_KRB4
 static HINSTANCE hKrb4 = 0;
 #endif /* USE_KRB4 */
+#ifdef USE_KRB524
 static HINSTANCE hKrb524 = 0;
+#endif
 #ifdef USE_MS2MIT
 static HINSTANCE hSecur32 = 0;
 #endif /* USE_MS2MIT */
@@ -378,8 +400,10 @@ static HINSTANCE hAdvApi32 = 0;
 static HINSTANCE hComErr = 0;
 static HINSTANCE hService = 0;
 static HINSTANCE hProfile = 0;
+#ifdef USE_LEASH
 static HINSTANCE hLeash = 0;
 static HINSTANCE hLeashOpt = 0;
+#endif
 static HINSTANCE hCCAPI = 0;
 static struct principal_ccache_data * princ_cc_data = NULL;
 static struct cell_principal_map    * cell_princ_map = NULL;
@@ -404,19 +428,23 @@ KFW_initialize(void)
         if ( !inited ) {
             inited = 1;
             LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+            LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+            LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
 #ifdef USE_KRB4
             LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
 #endif /* USE_KRB4 */
-            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 */
+#ifdef USE_KRB524
             LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
-            LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+#endif
+#ifdef USE_LEASH
             LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
-            LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
             LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
+#endif
+            LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
 
             if ( KFW_is_available() ) {
                 char rootcell[MAXCELLCHARS+1];
@@ -439,14 +467,18 @@ KFW_initialize(void)
 void
 KFW_cleanup(void)
 {
+#ifdef USE_LEASH
     if (hLeashOpt)
         FreeLibrary(hLeashOpt);
-    if (hCCAPI)
-        FreeLibrary(hCCAPI);
     if (hLeash)
         FreeLibrary(hLeash);
+#endif
+#ifdef USE_KRB524
     if (hKrb524)
         FreeLibrary(hKrb524);
+#endif
+    if (hCCAPI)
+        FreeLibrary(hCCAPI);
 #ifdef USE_MS2MIT
     if (hSecur32)
         FreeLibrary(hSecur32);
@@ -465,6 +497,64 @@ KFW_cleanup(void)
         FreeLibrary(hKrb5);
 }
 
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+static int IsWow64()
+{
+    static int init = TRUE;
+    static int bIsWow64 = FALSE;
+
+    if (init) {
+        HMODULE hModule;
+        LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
+
+        hModule = GetModuleHandle(TEXT("kernel32"));
+        if (hModule) {
+            fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
+  
+            if (NULL != fnIsWow64Process)
+            {
+                if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
+                {
+                    // on error, assume FALSE.
+                    // in other words, do nothing.
+                }
+            }
+            FreeLibrary(hModule);
+        }
+        init = FALSE;
+    }
+    return bIsWow64;
+}
+
+int
+KFW_accept_dotted_usernames(void)
+{
+    HKEY parmKey;
+    DWORD code, len;
+    DWORD value = 1;
+
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+                         0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        len = sizeof(value);
+        code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
+                                (BYTE *) &value, &len);
+        RegCloseKey(parmKey);
+    }
+    if (code != ERROR_SUCCESS) {
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+                             0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
+        if (code == ERROR_SUCCESS) {
+            len = sizeof(value);
+            code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
+                                    (BYTE *) &value, &len);
+            RegCloseKey (parmKey);
+        }
+    }
+    return value;
+}
+
+
 int
 KFW_use_krb524(void)
 {
@@ -473,7 +563,7 @@ KFW_use_krb524(void)
     DWORD use524 = 0;
 
     code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
-                         0, KEY_QUERY_VALUE, &parmKey);
+                         0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(use524);
         code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
@@ -482,7 +572,7 @@ KFW_use_krb524(void)
     }
     if (code != ERROR_SUCCESS) {
         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
-                             0, KEY_QUERY_VALUE, &parmKey);
+                             0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
         if (code == ERROR_SUCCESS) {
             len = sizeof(use524);
             code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
@@ -501,7 +591,7 @@ KFW_is_available(void)
     DWORD enableKFW = 1;
 
     code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
-                         0, KEY_QUERY_VALUE, &parmKey);
+                         0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(enableKFW);
         code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
@@ -511,7 +601,7 @@ KFW_is_available(void)
     
     if (code != ERROR_SUCCESS) {
         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
-                             0, KEY_QUERY_VALUE, &parmKey);
+                             0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
         if (code == ERROR_SUCCESS) {
             len = sizeof(enableKFW);
             code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
@@ -528,8 +618,13 @@ KFW_is_available(void)
 #ifdef USE_MS2MIT
          hSecur32 && 
 #endif /* USE_MS2MIT */
+#ifdef USE_KRB524
          hKrb524 &&
-         hProfile && hLeash && hCCAPI )
+#endif
+#ifdef USE_LEASH
+         hLeash &&
+#endif
+         hProfile && hCCAPI )
         return TRUE;
     return FALSE;
 }
@@ -572,11 +667,11 @@ KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
         {
             if (cache && *cache != NULL) {
                 pkrb5_cc_close(*ctx, *cache);
-                               *cache = NULL;
-                       }
+                *cache = NULL;
+            }
        
             pkrb5_free_context(*ctx);
-                       *ctx = NULL;
+            *ctx = NULL;
         }
     }
 
@@ -590,6 +685,8 @@ KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
     krb5_principal principal = 0;
     char * pname = NULL;
     const char * ccname = NULL;
+    const char * cctype = NULL;
+    char * ccfullname = NULL;
     krb5_error_code code = 0;
     krb5_error_code cc_code = 0;
     krb5_cc_cursor cur;
@@ -609,10 +706,18 @@ KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
     ccname = pkrb5_cc_get_name(ctx, cc);
     if (!ccname) goto cleanup;
 
+    cctype = pkrb5_cc_get_type(ctx, cc);
+    if (!cctype) goto cleanup;
+
+    ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
+    if (!ccfullname) goto cleanup;
+       
+    sprintf(ccfullname, "%s:%s", cctype, ccname);
+
     // 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) )
+            if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
                 break;
         }
     } 
@@ -623,7 +728,8 @@ KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
         next->next = princ_cc_data;
         princ_cc_data = next;
         next->principal = _strdup(pname);
-        next->ccache_name = _strdup(ccname);
+        next->ccache_name = ccfullname;
+        ccfullname = NULL;
         next->from_lsa = lsa;
         next->expired = 1;
         next->expiration_time = 0;
@@ -682,6 +788,8 @@ KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
     flags = KRB5_TC_OPENCLOSE;  //turn on OPENCLOSE
     code = pkrb5_cc_set_flags(ctx, cc, flags);
 
+    if ( ccfullname)
+        free(ccfullname);
     if ( pname )
         pkrb5_free_unparsed_name(ctx,pname);
     if ( principal )
@@ -866,9 +974,9 @@ KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int
 int
 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
 {
-    krb5_context ctx;
-    char * pname = 0;
-    char * ccname = 0;
+    krb5_context ctx = NULL;
+    char * pname = NULL;
+    char * ccname = NULL;
     krb5_error_code code;
 
     if (!pkrb5_init_context)
@@ -911,9 +1019,9 @@ KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
 void
 KFW_import_windows_lsa(void)
 {
-    krb5_context ctx = 0;
-    krb5_ccache  cc = 0;
-    krb5_principal princ = 0;
+    krb5_context ctx = NULL;
+    krb5_ccache  cc = NULL;
+    krb5_principal princ = NULL;
     char * pname = NULL;
     krb5_data *  princ_realm;
     krb5_error_code code;
@@ -924,11 +1032,6 @@ KFW_import_windows_lsa(void)
     if (!pkrb5_init_context)
         return;
 
-#ifdef COMMENT
-    if ( !MSLSA_IsKerberosLogon() )
-        return;
-#endif
-
     code = pkrb5_init_context(&ctx);
     if (code) goto cleanup;
 
@@ -1012,14 +1115,14 @@ KFW_import_windows_lsa(void)
 void
 KFW_import_ccache_data(void)
 {
-    krb5_context ctx = 0;
-    krb5_ccache  cc = 0;
-    krb5_principal principal = 0;
+    krb5_context ctx = NULL;
+    krb5_ccache  cc = NULL;
+    krb5_principal principal = NULL;
     krb5_creds creds;
     krb5_error_code code;
     krb5_error_code cc_code;
     krb5_cc_cursor cur;
-    apiCB * cc_ctx = 0;
+    apiCB * cc_ctx = NULL;
     struct _infoNC ** pNCi = NULL;
     int i, j, flags;
 
@@ -1152,7 +1255,13 @@ KFW_import_ccache_data(void)
                         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);
+                    code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, 
+#ifndef USE_LEASH
+                                        600,
+#else
+                                        pLeash_get_default_lifetime(),
+#endif /* USE_LEASH */
+                                        NULL);
                     if ( IsDebuggerPresent() ) {
                         char message[256];
                         sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
@@ -1209,19 +1318,18 @@ KFW_AFS_get_cred( char * username,
                   char * smbname,
                   char ** reasonP )
 {
-    krb5_context ctx = 0;
-    krb5_ccache cc = 0;
-    char * realm = 0, * userrealm = 0;
-    krb5_principal principal = 0;
-    char * pname = 0;
+    krb5_context ctx = NULL;
+    krb5_ccache cc = NULL;
+    char * realm = NULL, * userrealm = NULL;
+    krb5_principal principal = NULL;
+    char * pname = NULL;
     krb5_error_code code;
-       char local_cell[MAXCELLCHARS+1];
+    char local_cell[CELL_MAXNAMELEN+1];
     char **cells = NULL;
     int  cell_count=0;
     struct afsconf_cell cellconfig;
     char * dot;
 
-
     if (!pkrb5_init_context)
         return 0;
 
@@ -1244,24 +1352,27 @@ KFW_AFS_get_cred( char * username,
     userrealm = strchr(username,'@');
     if ( userrealm ) {
         pname = strdup(username);
-        userrealm = strchr(pname, '@');
-        *userrealm = '\0';
+        if (!KFW_accept_dotted_usernames()) {
+            userrealm = strchr(pname, '@');
+            *userrealm = '\0';
 
-        /* handle kerberos iv notation */
-        while ( dot = strchr(pname,'.') ) {
-            *dot = '/';
+            /* handle kerberos iv notation */
+            while ( dot = strchr(pname,'.') ) {
+                *dot = '/';
+            }
+            *userrealm++ = '@';
         }
-        *userrealm++ = '@';
     } else {
         pname = malloc(strlen(username) + strlen(realm) + 2);
 
         strcpy(pname, username);
 
-        /* handle kerberos iv notation */
-        while ( dot = strchr(pname,'.') ) {
-            *dot = '/';
+        if (!KFW_accept_dotted_usernames()) {
+            /* handle kerberos iv notation */
+            while ( dot = strchr(pname,'.') ) {
+                *dot = '/';
+            }
         }
-
         strcat(pname,"@");
         strcat(pname,realm);
     }
@@ -1278,18 +1389,32 @@ KFW_AFS_get_cred( char * username,
     if ( code ) goto cleanup;
 
     if ( lifetime == 0 )
+#ifndef USE_LEASH
+        lifetime = 600;
+#else
         lifetime = pLeash_get_default_lifetime();
+#endif
 
     if ( password && password[0] ) {
         code = KFW_kinit( ctx, cc, HWND_DESKTOP, 
                           pname, 
                           password,
                           lifetime,
+#ifndef USE_LEASH
+                          1, /* forwardable */
+                          0, /* not proxiable */
+                          1, /* renewable */
+                          1, /* noaddresses */
+                          0  /* no public ip */
+#else
                           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());
+                          pLeash_get_default_publicip()
+#endif /* USE_LEASH */
+                          );
+
         if ( IsDebuggerPresent() ) {
             char message[256];
             sprintf(message,"KFW_kinit() returns: %d\n",code);
@@ -1300,7 +1425,7 @@ KFW_AFS_get_cred( char * username,
         KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
     }
 
-    code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
+    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);
@@ -1331,7 +1456,7 @@ KFW_AFS_get_cred( char * username,
                     OutputDebugString("\n");
                 }
                 
-                code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime,smbname);
+                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);
@@ -1361,8 +1486,8 @@ KFW_AFS_get_cred( char * username,
 int 
 KFW_AFS_destroy_tickets_for_cell(char * cell)
 {
-    krb5_context               ctx = 0;
-    krb5_error_code            code;
+    krb5_context       ctx = NULL;
+    krb5_error_code    code;
     int count;
     char ** principals = NULL;
 
@@ -1418,19 +1543,20 @@ KFW_AFS_destroy_tickets_for_cell(char * cell)
         }
         free(principals);
     }
-    pkrb5_free_context(ctx);
+    if (ctx)
+               pkrb5_free_context(ctx);
     return 0;
 }
 
 int 
 KFW_AFS_destroy_tickets_for_principal(char * user)
 {
-    krb5_context               ctx = 0;
-    krb5_error_code            code;
+    krb5_context       ctx = NULL;
+    krb5_error_code    code;
     int count;
     char ** cells = NULL;
-    krb5_principal      princ = 0;
-    krb5_ccache                        cc  = 0;
+    krb5_principal      princ = NULL;
+    krb5_ccache                cc  = NULL;
 
     if (!pkrb5_init_context)
         return 0;
@@ -1442,7 +1568,7 @@ KFW_AFS_destroy_tickets_for_principal(char * user)
     }
 
     code = pkrb5_init_context(&ctx);
-    if (code) ctx = 0;
+    if (code) return 0;
 
     code = pkrb5_parse_name(ctx, user, &princ);
     if (code) goto loop_cleanup;
@@ -1472,22 +1598,23 @@ KFW_AFS_destroy_tickets_for_principal(char * user)
         free(cells);
     }
 
-    pkrb5_free_context(ctx);
+    if (ctx)
+               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_error_code     code = 0;
+    krb5_context       ctx = NULL;
+    krb5_ccache                cc = NULL;
     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]="";
+    char local_cell[CELL_MAXNAMELEN+1]="";
     struct afsconf_cell cellconfig;
 
     if (!pkrb5_init_context)
@@ -1549,7 +1676,7 @@ KFW_AFS_renew_expiring_tokens(void)
                         OutputDebugString(realm);
                         OutputDebugString("\n");
                     }
-                    code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime(),NULL);
+                    code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
                     if ( IsDebuggerPresent() ) {
                         char message[256];
                         sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
@@ -1581,8 +1708,8 @@ KFW_AFS_renew_expiring_tokens(void)
 BOOL
 KFW_AFS_renew_token_for_cell(char * cell)
 {
-    krb5_error_code                    code = 0;
-    krb5_context                       ctx = 0;
+    krb5_error_code     code = 0;
+    krb5_context       ctx = NULL;
     int count;
     char ** principals = NULL;
 
@@ -1615,7 +1742,7 @@ KFW_AFS_renew_token_for_cell(char * cell)
         krb5_ccache                    cc  = 0;
         const char * realm = NULL;
         struct afsconf_cell cellconfig;
-        char local_cell[MAXCELLCHARS+1];
+        char local_cell[CELL_MAXNAMELEN+1];
 
         while ( count-- ) {
             code = pkrb5_parse_name(ctx, principals[count], &princ);
@@ -1667,7 +1794,7 @@ KFW_AFS_renew_token_for_cell(char * cell)
             }
 #endif /* COMMENT */
 
-            code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime(),NULL);
+            code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
             if ( IsDebuggerPresent() ) {
                 char message[256];
                 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
@@ -1696,7 +1823,8 @@ KFW_AFS_renew_token_for_cell(char * cell)
         code = -1;      // we did not renew the tokens 
 
   cleanup:
-    pkrb5_free_context(ctx);
+    if (ctx) 
+               pkrb5_free_context(ctx);
     return (code ? FALSE : TRUE);
 
 }
@@ -1722,13 +1850,13 @@ KFW_AFS_renew_tokens_for_all_cells(void)
 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;
+    krb5_error_code     code = 0;
+    krb5_context       ctx = NULL;
+    krb5_ccache                cc = NULL;
+    krb5_principal     me = NULL;
+    krb5_principal      server = NULL;
+    krb5_creds         my_creds;
+    krb5_data           *realm = NULL;
 
     if (!pkrb5_init_context)
         return 0;
@@ -1839,12 +1967,12 @@ KFW_kinit( krb5_context alt_ctx,
             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_error_code            code = 0;
+    krb5_context               ctx = NULL;
+    krb5_ccache                        cc = NULL;
+    krb5_principal             me = NULL;
+    char*                       name = NULL;
+    krb5_creds                 my_creds;
     krb5_get_init_creds_opt     options;
     krb5_address **             addrs = NULL;
     int                         i = 0, addr_count = 0;
@@ -1874,19 +2002,22 @@ KFW_kinit( krb5_context alt_ctx,
 
     code = pkrb5_parse_name(ctx, principal_name, &me);
     if (code) 
-               goto cleanup;
+       goto cleanup;
 
     code = pkrb5_unparse_name(ctx, me, &name);
     if (code) 
-               goto cleanup;
+       goto cleanup;
 
     if (lifetime == 0)
+#ifndef USE_LEASH
+        lifetime = 600;
+#else
         lifetime = pLeash_get_default_lifetime();
-    else
-        lifetime *= 5*60;
+#endif /* USE_LEASH */
+    lifetime *= 60;
 
-       if (renew_life > 0)
-               renew_life *= 5*60;
+    if (renew_life > 0)
+       renew_life *= 60;
 
     if (lifetime)
         pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
@@ -1899,7 +2030,7 @@ KFW_kinit( krb5_context alt_ctx,
     if (addressless)
         pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
     else {
-               if (publicIP)
+       if (publicIP)
         {
             // we are going to add the public IP address specified by the user
             // to the list provided by the operating system
@@ -1968,15 +2099,15 @@ KFW_kinit( krb5_context alt_ctx,
                                        0, // service name
                                        &options);
     if (code) 
-               goto cleanup;
+       goto cleanup;
 
     code = pkrb5_cc_initialize(ctx, cc, me);
     if (code) 
-               goto cleanup;
+       goto cleanup;
 
     code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
     if (code) 
-               goto cleanup;
+       goto cleanup;
 
  cleanup:
     if ( addrs ) {
@@ -2006,8 +2137,8 @@ KFW_kinit( krb5_context alt_ctx,
 int
 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
 {
-    krb5_context               ctx;
-    krb5_ccache                        cc;
+    krb5_context               ctx = NULL;
+    krb5_ccache                        cc = NULL;
     krb5_error_code            code;
 
     if (!pkrb5_init_context)
@@ -2150,9 +2281,9 @@ MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
 static LPWORD 
 lpwAlign( LPWORD lpIn )
 {
-    ULONG ul;
+    ULONG_PTR ul;
 
-    ul = (ULONG) lpIn;
+    ul = (ULONG_PTR) lpIn;
     ul += 3;
     ul >>=2;
     ul <<=2;
@@ -2266,7 +2397,7 @@ MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
         lpdit->dwExtendedStyle = 0;
         lpdit->x  = 10; 
         lpdit->y  = 10 + i * 14;
-        lpdit->cx = strlen(ptext[i]) * 4 + 10; 
+        lpdit->cx = (short)strlen(ptext[i]) * 4 + 10; 
         lpdit->cy = 14;
         lpdit->id = ID_TEXT + i;  // text identifier
 
@@ -2282,8 +2413,9 @@ MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
     }
     
     for ( i=0, pwid = 0; i<tb_cnt; i++) {
-        if ( pwid < strlen(tb[i].label) )
-            pwid = strlen(tb[i].label);
+       int len = (int)strlen(tb[i].label);
+        if ( pwid < len )
+            pwid = len;
     }
 
     for ( i=0; i<tb_cnt; i++) {
@@ -2362,7 +2494,7 @@ MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
 static int
 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
 {
-       HINSTANCE hInst = 0;
+    HINSTANCE hInst = 0;
     int maxwidth = 0;
     int numlines = 0;
     int len;
@@ -2382,16 +2514,16 @@ multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
             *p++ = '\0';
         } 
         if ( strlen(plines[numlines-1]) > maxwidth )
-            maxwidth = strlen(plines[numlines-1]);
+            maxwidth = (int)strlen(plines[numlines-1]);
     }
 
     for ( i=0;i<n;i++ ) {
-        len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
+        len = (int)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));
+    return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
 }
 
 static krb5_error_code KRB5_CALLCONV
@@ -2409,10 +2541,10 @@ KRB5_prompter( krb5_context context,
        HWND hParent = (HWND)data;
 
     if (name)
-        nlen = strlen(name)+2;
+        nlen = (int)strlen(name)+2;
 
     if (banner)
-        blen = strlen(banner)+2;
+        blen = (int)strlen(banner)+2;
 
     tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
     if ( tb != NULL ) {
@@ -2429,7 +2561,7 @@ KRB5_prompter( krb5_context context,
         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);
+                prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
         } else
             errcode = -2;
     }
@@ -2526,46 +2658,29 @@ ViceIDToUsername(char *username,
                  struct ktc_principal *aserver, 
                  struct ktc_token *atoken)
 {
-    static char lastcell[MAXCELLCHARS+1] = { 0 };
-    static char confname[512] = { 0 };
+    static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
+    static char confdir[512] = { 0 };
 #ifdef AFS_ID_TO_NAME
     char username_copy[BUFSIZ];
 #endif /* AFS_ID_TO_NAME */
-    long viceId;                       /* AFS uid of user */
+    long viceId = ANONYMOUSID;         /* AFS uid of user */
     int  status = 0;
 #ifdef ALLOW_REGISTER
     afs_int32 id;
 #endif /* ALLOW_REGISTER */
 
-    if (confname[0] == '\0') {
-        strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
-        confname[sizeof(confname) - 2] = '\0';
-    }
-
-    /*
-     * Talk about DUMB!  It turns out that there is a bug in
-     * pr_Initialize -- even if you give a different cell name
-     * to it, it still uses a connection to a previous AFS server
-     * if one exists.  The way to fix this is to change the
-     * _filename_ argument to pr_Initialize - that forces it to
-     * re-initialize the connection.  We do this by adding and
-     * removing a "/" on the end of the configuration directory name.
-     */
-
-    if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
-        int i = strlen(confname);
-        if (confname[i - 1] == '/') {
-            confname[i - 1] = '\0';
-        } else {
-            confname[i] = '/';
-            confname[i + 1] = '\0';
-        }
-    }
+    if (confdir[0] == '\0')
+        cm_GetConfigDir(confdir, sizeof(confdir));
 
     strcpy(lastcell, aserver->cell);
 
-    if (!pr_Initialize (0, confname, aserver->cell))
-        status = pr_SNameToId (username, &viceId);
+    if (!pr_Initialize (0, confdir, aserver->cell)) {
+        char sname[PR_MAXNAMELEN];
+        strncpy(sname, username, PR_MAXNAMELEN);
+        sname[PR_MAXNAMELEN-1] = '\0';    
+        status = pr_SNameToId (sname, &viceId);
+       pr_End();
+    }
 
     /*
      * This is a crock, but it is Transarc's crock, so
@@ -2602,18 +2717,12 @@ ViceIDToUsername(char *username,
             strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
             if (status = ktc_SetToken(aserver, atoken, aclient, 0))
                 return status;
-
-            /*                                    
-             * In case you're wondering, we don't need to change the
-             * filename here because we're still connecting to the
-             * same cell -- we're just using a different authentication
-             * level
-             */
-
-            if (status = pr_Initialize(1L, confname, aserver->cell))
-                return status;
-            if (status = pr_CreateUser(username, &id))
+            if (status = pr_Initialize(1L, confdir, aserver->cell))
                 return status;
+            status = pr_CreateUser(username, &id);
+           pr_End();
+           if (status)
+               return status;
 #ifdef AFS_ID_TO_NAME
             strncpy(username_copy, username, BUFSIZ);
             snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
@@ -2625,6 +2734,25 @@ ViceIDToUsername(char *username,
 }
 
 
+static void
+copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
+    krb5_error_code code;
+    krb5_ticket *ticket;
+    size_t len;
+
+    code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
+    if (code == 0) {
+        len = krb5_princ_realm(context, ticket->server)->length;
+        if (len > destlen - 1)
+            len = destlen - 1;
+
+        strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
+        dest[len] = '\0';
+
+        pkrb5_free_ticket(context, ticket);
+    }
+}
+
 int
 KFW_AFS_klog(
     krb5_context alt_ctx,
@@ -2632,7 +2760,7 @@ KFW_AFS_klog(
     char *service,
     char *cell,
     char *realm,
-    int LifeTime,
+    int  lifetime,     /* unused parameter */
     char *smbname
     )
 {
@@ -2645,8 +2773,8 @@ KFW_AFS_klog(
     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];
+    char       local_cell[CELL_MAXNAMELEN+1];
+    char       Dmycell[CELL_MAXNAMELEN+1];
     struct ktc_token   atoken;
     struct ktc_token   btoken;
     struct afsconf_cell        ak_cellconfig; /* General information about the cell */
@@ -2656,13 +2784,13 @@ KFW_AFS_klog(
     DWORD       CurrentState;
     char        HostName[64];
     BOOL        try_krb5 = 0;
-    krb5_context  ctx = 0;
-    krb5_ccache   cc = 0;
+    krb5_context  ctx = NULL;
+    krb5_ccache   cc = NULL;
     krb5_creds increds;
-    krb5_creds * k5creds = 0;
+    krb5_creds * k5creds = NULL;
     krb5_error_code code;
-    krb5_principal client_principal = 0;
-    krb5_data * k5data;
+    krb5_principal client_principal = NULL;
+    krb5_data * k5data = NULL;
     int i, retry = 0;
 
     CurrentState = 0;
@@ -2724,19 +2852,21 @@ KFW_AFS_klog(
         goto skip_krb5_init;
     }
 
-    /* look for client principals which cannot be distinguished 
-     * from Kerberos 4 multi-component principal names
-     */
-    k5data = krb5_princ_component(ctx,client_principal,0);
-    for ( i=0; i<k5data->length; i++ ) {
-        if ( k5data->data[i] == '.' )
-            break;
-    }
-    if (i != k5data->length)
-    {
-        OutputDebugString("Illegal Principal name contains dot in first component\n");
-        rc = KRB5KRB_ERR_GENERIC;
-        goto cleanup;
+    if (!KFW_accept_dotted_usernames()) {
+        /* look for client principals which cannot be distinguished 
+         * from Kerberos 4 multi-component principal names
+         */
+        k5data = krb5_princ_component(ctx,client_principal,0);
+        for ( i=0; i<k5data->length; i++ ) {
+            if ( k5data->data[i] == '.' )
+                break;
+        }
+        if (i != k5data->length)
+        {
+            OutputDebugString("Illegal Principal name contains dot in first component\n");
+            rc = KRB5KRB_ERR_GENERIC;
+            goto cleanup;
+        }
     }
 
     i = krb5_princ_realm(ctx, client_principal)->length;
@@ -2770,6 +2900,7 @@ KFW_AFS_klog(
     else
         strcpy(CellName, cell);
 
+    /* This is for Kerberos v4 only */
     if (strlen(realm) == 0)
         strcpy(RealmName, realm_of_cell);
     else
@@ -2779,56 +2910,31 @@ KFW_AFS_klog(
 
     if ( try_krb5 ) {
         int len;
+        code = KRB5KRB_ERR_GENERIC;
 
-        /* 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() ) {
-            char * cname, *sname;
-            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");
-            pkrb5_free_unparsed_name(ctx,cname);
-            pkrb5_free_unparsed_name(ctx,sname);
-        }
-
-        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);
+        /* If there was a specific realm we are supposed to try
+         * then use it 
+         */
+        if (strlen(realm) != 0) {
+            /* service/cell@REALM */
             increds.server = 0;
             code = pkrb5_build_principal(ctx, &increds.server,
-                                          strlen(RealmName),
-                                          RealmName,
-                                          ServiceName,
-                                          0);
-
+                                         (int)strlen(realm),
+                                         realm,
+                                         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("Getting tickets for \"");
                 OutputDebugString(cname);
                 OutputDebugString("\" and service \"");
                 OutputDebugString(sname);
@@ -2839,29 +2945,59 @@ KFW_AFS_klog(
 
             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 (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                code == KRB5_ERR_HOST_REALM_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,
+                                              (int)strlen(realm),
+                                              realm,
+                                              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);
+                }
+
+                if (!code)
+                    code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+            }
+
+            if (code == 0) {
+                /* we have a local realm for the cell */
+                strcpy(realm_of_cell, realm);
+            }
+        } else {
+            /* Otherwise, first try service/cell@CLIENT_REALM */
+            if (code = pkrb5_build_principal(ctx, &increds.server,
+                                              (int)strlen(realm_of_user),
+                                              realm_of_user,
+                                              ServiceName,
+                                              CellName,
+                                              0)) 
+            {
+                goto cleanup;
+            }
 
             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("Getting tickets for \"");
                 OutputDebugString(cname);
                 OutputDebugString("\" and service \"");
                 OutputDebugString(sname);
@@ -2870,19 +3006,60 @@ KFW_AFS_klog(
                 pkrb5_free_unparsed_name(ctx,sname);
             }
 
-            if (!code)
-                code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+            code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+            if (code == 0) {
+                /* The client's realm is a local realm for the cell.
+                 * Save it so that later the pts registration will not
+                 * be performed.
+                 */
+                strcpy(realm_of_cell, realm_of_user);
+            }
 
-        
-            if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+            if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
                  code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
-                                code == KRB5KRB_AP_ERR_MSG_TYPE) {
-                /* Or service@REALM_OF_CELL */
+                 code == KRB5KRB_AP_ERR_MSG_TYPE) && 
+                 strcmp(realm_of_user, realm_of_cell)) {
+                /* Then service/cell@CELL_REALM */
+                pkrb5_free_principal(ctx,increds.server);
+                increds.server = 0;
+                code = pkrb5_build_principal(ctx, &increds.server,
+                                              (int)strlen(realm_of_cell),
+                                              realm_of_cell,
+                                              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);
+                }
+
+                if (!code)
+                    code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+
+                if (!code && !strlen(realm_of_cell)) 
+                    copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
+            }
+
+            if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+                code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+                code == KRB5KRB_AP_ERR_MSG_TYPE) {
+                /* Finally service@CELL_REALM */
                 pkrb5_free_principal(ctx,increds.server);
                 increds.server = 0;
                 code = pkrb5_build_principal(ctx, &increds.server,
-                                              strlen(RealmName),
-                                              RealmName,
+                                              (int)strlen(realm_of_cell),
+                                              realm_of_cell,
                                               ServiceName,
                                               0);
 
@@ -2902,6 +3079,8 @@ KFW_AFS_klog(
 
                 if (!code)
                     code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+                if (!code && !strlen(realm_of_cell)) 
+                    copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
             }
         }
 
@@ -2943,7 +3122,7 @@ KFW_AFS_klog(
                 retry++;
                 goto retry_gettoken5;
             }
-            goto try_krb524d;
+            goto cleanup;
         }
 
         if (atoken.kvno == btoken.kvno &&
@@ -2967,7 +3146,7 @@ KFW_AFS_klog(
             char * p;
             strcat(aclient.name, ".");
             p = aclient.name + strlen(aclient.name);
-            len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+            len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
             strncpy(p, k5creds->client->data[1].data, len);
             p[len] = '\0';
         }
@@ -2975,18 +3154,21 @@ KFW_AFS_klog(
 
         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) ) {
+        len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
+        /* For Khimaira, always append the realm name */
+        if ( 1 /* 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);
+            len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
             strncpy(p, k5creds->client->realm.data, len);
             p[len] = '\0';
         }
 
-        ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
-                         &aclient, &aserver, &atoken);
+       GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
+       if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+           ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
+                            &aclient, &aserver, &atoken);
 
         if ( smbname ) {
             strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
@@ -3000,6 +3182,9 @@ KFW_AFS_klog(
             goto cleanup;   /* We have successfully inserted the token */
 
       try_krb524d:
+#ifndef USE_KRB524
+        goto cleanup;
+#else
         /* Otherwise, the ticket could have been too large so try to
          * convert using the krb524d running with the KDC 
          */
@@ -3014,6 +3199,7 @@ KFW_AFS_klog(
             try_krb5 = 0;
             goto use_krb4;
         }
+#endif /* USE_KRB524 */
     } else {
       use_krb4:
 #ifdef USE_KRB4
@@ -3097,17 +3283,16 @@ KFW_AFS_klog(
     }
     strcpy(aclient.instance, "");
 
-    if ( strcmp(realm_of_cell, creds.realm) ) 
-    {
-        strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
-        strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
-    }
+    strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
+    strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
     aclient.name[MAXKTCREALMLEN-1] = '\0';
 
     strcpy(aclient.cell, CellName);
 
-    ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
-                      &aclient, &aserver, &atoken);
+    GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
+    if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+       ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
+                        &aclient, &aserver, &atoken);
 
     if ( smbname ) {
         strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
@@ -3179,7 +3364,7 @@ int
 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
 {
     int        rc;
-    char newcell[MAXCELLCHARS+1];
+    char newcell[CELL_MAXNAMELEN+1];
 
     local_cell[0] = (char)0;
     memset(cellconfig, 0, sizeof(*cellconfig));
@@ -3389,13 +3574,13 @@ LoadFuncs(
 
 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
 {
-    krb5_context ctx = 0;
-    krb5_ccache cc = 0;
+    krb5_context ctx = NULL;
+    krb5_ccache cc = NULL;
     krb5_error_code code;
     krb5_data pwdata;
-    const char * realm = 0;
-    krb5_principal principal = 0;
-    char * pname = 0;
+    const char * realm = NULL;
+    krb5_principal principal = NULL;
+    char * pname = NULL;
     char   password[PROBE_PASSWORD_LEN+1];
     BOOL serverReachable = 0;
 
@@ -3408,7 +3593,7 @@ BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
 
     realm = afs_realm_of_cell(ctx, cellconfig);  // do not free
 
-    code = pkrb5_build_principal(ctx, &principal, strlen(realm),
+    code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
                                   realm, PROBE_USERNAME, NULL, NULL);
     if ( code ) goto cleanup;
 
@@ -3466,11 +3651,11 @@ BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
 BOOL
 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
 {
-    krb5_context   ctx = 0;
+    krb5_context   ctx = NULL;
     krb5_error_code code;
-    krb5_ccache mslsa_ccache=0;
-    krb5_principal princ = 0;
-    char * pname = 0;
+    krb5_ccache mslsa_ccache=NULL;
+    krb5_principal princ = NULL;
+    char * pname = NULL;
     BOOL success = 0;
 
     if (!KFW_is_available())
@@ -3493,7 +3678,7 @@ KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
         szUser[*dwSize-1] = '\0';
         success = 1;
     }
-    *dwSize = strlen(pname);
+    *dwSize = (DWORD)strlen(pname);
 
   cleanup:
     if (pname)
@@ -3510,19 +3695,143 @@ KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
     return success;
 }
 
+int 
+KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
+{
+    // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
+    PSID pSystemSID = NULL;
+    DWORD SystemSIDlength = 0, UserSIDlength = 0;
+    PACL ccacheACL = NULL;
+    DWORD ccacheACLlength = 0;
+    PTOKEN_USER pTokenUser = NULL;
+    DWORD retLen;
+    DWORD gle;
+    int ret = 0;  
+
+    if (!filename) {
+       return 1;
+    }
+
+    /* Get System SID */
+    if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
+       ret = 1;
+       goto cleanup;
+    }
+
+    /* Create ACL */
+    SystemSIDlength = GetLengthSid(pSystemSID);
+    ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
+        + SystemSIDlength - sizeof(DWORD);
+
+    if (hUserToken) {
+       if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
+       {
+           if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
+               pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
+
+               GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
+           }            
+       }
+
+       if (pTokenUser) {
+           UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
+
+           ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength 
+               - sizeof(DWORD);
+       }
+    }
+
+    ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
+    if (!ccacheACL) {
+       ret = 1;
+       goto cleanup;
+     }
+    InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
+    AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+                         STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+                         pSystemSID);
+    if (pTokenUser) {
+       AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+                            STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+                            pTokenUser->User.Sid);
+       if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+                                  DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+                                  NULL,
+                                  NULL, 
+                                  ccacheACL,
+                                  NULL)) {
+           gle = GetLastError();
+           if (gle != ERROR_NO_TOKEN)
+               ret = 1;
+       }
+       if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+                                  OWNER_SECURITY_INFORMATION,
+                                  pTokenUser->User.Sid,
+                                  NULL, 
+                                  NULL,
+                                  NULL)) {
+           gle = GetLastError();
+           if (gle != ERROR_NO_TOKEN)
+               ret = 1;
+       }
+    } else {
+       if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+                                  DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+                                  NULL,
+                                  NULL, 
+                                  ccacheACL,
+                                  NULL)) {
+           gle = GetLastError();
+           if (gle != ERROR_NO_TOKEN)
+               ret = 1;
+       }
+    }
+
+  cleanup:
+    if (pSystemSID)
+       LocalFree(pSystemSID);
+    if (pTokenUser)
+       LocalFree(pTokenUser);
+    if (ccacheACL)
+       LocalFree(ccacheACL);
+    return ret;
+}
+
+int 
+KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
+{
+    int  retval = 0;
+    DWORD dwSize = size-1;     /* leave room for nul */
+    DWORD dwLen  = 0;
+    if (!hUserToken || !newfilename || size <= 0)
+       return 1;
+     *newfilename = '\0';
+     dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
+     if ( !dwLen || dwLen > dwSize )
+       dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
+     if ( !dwLen || dwLen > dwSize )
+       return 1;
+     newfilename[dwSize] = '\0';
+    return 0;
+}
+
 void
 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
 {
-    char filename[256];
+    char filename[MAX_PATH] = "";
     DWORD count;
-    char cachename[264] = "FILE:";
-    krb5_context               ctx = 0;
+    char cachename[MAX_PATH + 8] = "FILE:";
+    krb5_context               ctx = NULL;
     krb5_error_code            code;
-    krb5_principal              princ = 0;
-    krb5_ccache                        cc  = 0;
-    krb5_ccache                 ncc = 0;
+    krb5_principal              princ = NULL;
+    krb5_ccache                        cc  = NULL;
+    krb5_ccache                 ncc = NULL;
 
-    if (!pkrb5_init_context)
+    if (!pkrb5_init_context || !user || !szLogonId)
         return;
 
     count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
@@ -3541,7 +3850,7 @@ KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
     DeleteFile(filename);
 
     code = pkrb5_init_context(&ctx);
-    if (code) ctx = 0;
+    if (code) goto cleanup;
 
     code = pkrb5_parse_name(ctx, user, &princ);
     if (code) goto cleanup;
@@ -3555,6 +3864,9 @@ KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
     code = pkrb5_cc_initialize(ctx, ncc, princ);
     if (code) goto cleanup;
 
+    code = KFW_AFS_set_file_cache_dacl(filename, NULL);
+    if (code) goto cleanup;
+
     code = pkrb5_cc_copy_creds(ctx,cc,ncc);
 
   cleanup:
@@ -3576,28 +3888,26 @@ KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
 }
 
 int
-KFW_AFS_copy_system_file_to_default_cache(char * filename)
+KFW_AFS_copy_file_cache_to_default_cache(char * filename)
 {
-    DWORD count;
-    char cachename[264] = "FILE:";
-    HANDLE hFile;
-    krb5_context               ctx = 0;
+    char cachename[MAX_PATH + 8] = "FILE:";
+    krb5_context               ctx = NULL;
     krb5_error_code            code;
-    krb5_principal              princ = 0;
-    krb5_ccache                        cc  = 0;
-    krb5_ccache                 ncc = 0;
+    krb5_principal              princ = NULL;
+    krb5_ccache                        cc  = NULL;
+    krb5_ccache                 ncc = NULL;
     int retval = 1;
 
-    if (!pkrb5_init_context)
+    if (!pkrb5_init_context || !filename)
         return 1;
 
-    if ( strlen(filename) + 6 > sizeof(cachename) )
+    if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
         return 1;
 
-    strcat(cachename, filename);
-
     code = pkrb5_init_context(&ctx);
-    if (code) ctx = 0;
+    if (code) return 1;
+
+    strcat(cachename, filename);
 
     code = pkrb5_cc_resolve(ctx, cachename, &cc);
     if (code) goto cleanup;
@@ -3636,3 +3946,154 @@ KFW_AFS_copy_system_file_to_default_cache(char * filename)
 
     return 0;
 }
+
+/* We are including this 
+
+/* Ticket lifetime.  This defines the table used to lookup lifetime for the
+   fixed part of rande of the one byte lifetime field.  Values less than 0x80
+   are intrpreted as the number of 5 minute intervals.  Values from 0x80 to
+   0xBF should be looked up in this table.  The value of 0x80 is the same using
+   both methods: 10 and two-thirds hours .  The lifetime of 0xBF is 30 days.
+   The intervening values of have a fixed ratio of roughly 1.06914.  The value
+   oxFF is defined to mean a ticket has no expiration time.  This should be
+   used advisedly since individual servers may impose defacto upperbounds on
+   ticket lifetimes. */
+
+#define TKTLIFENUMFIXED 64
+#define TKTLIFEMINFIXED 0x80
+#define TKTLIFEMAXFIXED 0xBF
+#define TKTLIFENOEXPIRE 0xFF
+#define MAXTKTLIFETIME (30*24*3600)    /* 30 days */
+
+static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
+    38400,                     /* 10.67 hours, 0.44 days */
+    41055,                     /* 11.40 hours, 0.48 days */
+    43894,                     /* 12.19 hours, 0.51 days */
+    46929,                     /* 13.04 hours, 0.54 days */
+    50174,                     /* 13.94 hours, 0.58 days */
+    53643,                     /* 14.90 hours, 0.62 days */
+    57352,                     /* 15.93 hours, 0.66 days */
+    61318,                     /* 17.03 hours, 0.71 days */
+    65558,                     /* 18.21 hours, 0.76 days */
+    70091,                     /* 19.47 hours, 0.81 days */
+    74937,                     /* 20.82 hours, 0.87 days */
+    80119,                     /* 22.26 hours, 0.93 days */
+    85658,                     /* 23.79 hours, 0.99 days */
+    91581,                     /* 25.44 hours, 1.06 days */
+    97914,                     /* 27.20 hours, 1.13 days */
+    104684,                    /* 29.08 hours, 1.21 days */
+    111922,                    /* 31.09 hours, 1.30 days */
+    119661,                    /* 33.24 hours, 1.38 days */
+    127935,                    /* 35.54 hours, 1.48 days */
+    136781,                    /* 37.99 hours, 1.58 days */
+    146239,                    /* 40.62 hours, 1.69 days */
+    156350,                    /* 43.43 hours, 1.81 days */
+    167161,                    /* 46.43 hours, 1.93 days */
+    178720,                    /* 49.64 hours, 2.07 days */
+    191077,                    /* 53.08 hours, 2.21 days */
+    204289,                    /* 56.75 hours, 2.36 days */
+    218415,                    /* 60.67 hours, 2.53 days */
+    233517,                    /* 64.87 hours, 2.70 days */
+    249664,                    /* 69.35 hours, 2.89 days */
+    266926,                    /* 74.15 hours, 3.09 days */
+    285383,                    /* 79.27 hours, 3.30 days */
+    305116,                    /* 84.75 hours, 3.53 days */
+    326213,                    /* 90.61 hours, 3.78 days */
+    348769,                    /* 96.88 hours, 4.04 days */
+    372885,                    /* 103.58 hours, 4.32 days */
+    398668,                    /* 110.74 hours, 4.61 days */
+    426234,                    /* 118.40 hours, 4.93 days */
+    455705,                    /* 126.58 hours, 5.27 days */
+    487215,                    /* 135.34 hours, 5.64 days */
+    520904,                    /* 144.70 hours, 6.03 days */
+    556921,                    /* 154.70 hours, 6.45 days */
+    595430,                    /* 165.40 hours, 6.89 days */
+    636601,                    /* 176.83 hours, 7.37 days */
+    680618,                    /* 189.06 hours, 7.88 days */
+    727680,                    /* 202.13 hours, 8.42 days */
+    777995,                    /* 216.11 hours, 9.00 days */
+    831789,                    /* 231.05 hours, 9.63 days */
+    889303,                    /* 247.03 hours, 10.29 days */
+    950794,                    /* 264.11 hours, 11.00 days */
+    1016537,                   /* 282.37 hours, 11.77 days */
+    1086825,                   /* 301.90 hours, 12.58 days */
+    1161973,                   /* 322.77 hours, 13.45 days */
+    1242318,                   /* 345.09 hours, 14.38 days */
+    1328218,                   /* 368.95 hours, 15.37 days */
+    1420057,                   /* 394.46 hours, 16.44 days */
+    1518247,                   /* 421.74 hours, 17.57 days */
+    1623226,                   /* 450.90 hours, 18.79 days */
+    1735464,                   /* 482.07 hours, 20.09 days */
+    1855462,                   /* 515.41 hours, 21.48 days */
+    1983758,                   /* 551.04 hours, 22.96 days */
+    2120925,                   /* 589.15 hours, 24.55 days */
+    2267576,                   /* 629.88 hours, 26.25 days */
+    2424367,                   /* 673.44 hours, 28.06 days */
+    2592000
+};                             /* 720.00 hours, 30.00 days */
+
+/* life_to_time - takes a start time and a Kerberos standard lifetime char and
+ * returns the corresponding end time.  There are four simple cases to be
+ * handled.  The first is a life of 0xff, meaning no expiration, and results in
+ * an end time of 0xffffffff.  The second is when life is less than the values
+ * covered by the table.  In this case, the end time is the start time plus the
+ * number of 5 minute intervals specified by life.  The third case returns
+ * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED.  The
+ * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
+ * table to extract the lifetime in seconds, which is added to start to produce
+ * the end time. */
+
+afs_uint32
+life_to_time(afs_uint32 start, unsigned char life)
+{
+    int realLife;
+
+    if (life == TKTLIFENOEXPIRE)
+       return NEVERDATE;
+    if (life < TKTLIFEMINFIXED)
+       return start + life * 5 * 60;
+    if (life > TKTLIFEMAXFIXED)
+       return start + MAXTKTLIFETIME;
+    realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
+    return start + realLife;
+}
+
+/* time_to_life - takes start and end times for the ticket and returns a
+ * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
+ * lifetimes above 127*5minutes.  First, the special case of (end ==
+ * 0xffffffff) is handled to mean no expiration.  Then negative lifetimes and
+ * those greater than the maximum ticket lifetime are rejected.  Then lifetimes
+ * less than the first table entry are handled by rounding the requested
+ * lifetime *up* to the next 5 minute interval.  The final step is to search
+ * the table for the smallest entry *greater than or equal* to the requested
+ * entry.  The actual code is prepared to handle the case where the table is
+ * unordered but that it an unnecessary frill. */
+
+static unsigned char
+time_to_life(afs_uint32 start, afs_uint32 end)
+{
+    int lifetime = end - start;
+    int best, best_i;
+    int i;
+
+    if (end == NEVERDATE)
+       return TKTLIFENOEXPIRE;
+    if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
+       return 0;
+    if (lifetime < tkt_lifetimes[0])
+       return (lifetime + 5 * 60 - 1) / (5 * 60);
+    best_i = -1;
+    best = MAXKTCTICKETLIFETIME;
+    for (i = 0; i < TKTLIFENUMFIXED; i++)
+       if (tkt_lifetimes[i] >= lifetime) {
+           int diff = tkt_lifetimes[i] - lifetime;
+           if (diff < best) {
+               best = diff;
+               best_i = i;
+           }
+       }
+    if (best_i < 0)
+       return 0;
+    return best_i + TKTLIFEMINFIXED;
+}
+