DEVEL15-windows-afskfw-20080127
[openafs.git] / src / WINNT / afsd / afskfw.c
index 0279cc6..160d928 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2005 Secure Endpoints Inc.
+ * Copyright (c) 2004, 2005, 2006, 2007 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 <afs/ptserver.h>
@@ -90,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);
@@ -104,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);
@@ -166,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);
@@ -215,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),
@@ -235,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),
@@ -310,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),
@@ -371,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 */
@@ -379,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;
@@ -405,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];
@@ -440,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);
@@ -466,6 +497,36 @@ KFW_cleanup(void)
         FreeLibrary(hKrb5);
 }
 
+
+int
+KFW_accept_dotted_usernames(void)
+{
+    HKEY parmKey;
+    DWORD code, len;
+    DWORD value = 1;
+
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+                         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, 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)
 {
@@ -529,8 +590,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;
 }
@@ -591,6 +657,7 @@ 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;
     krb5_error_code code = 0;
     krb5_error_code cc_code = 0;
     krb5_cc_cursor cur;
@@ -610,6 +677,9 @@ 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;
+
     // Search the existing list to see if we have a match 
     if ( next ) {
         for ( ; next ; next = next->next ) {
@@ -624,7 +694,9 @@ 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 = malloc(strlen(ccname) + strlen(cctype) + 2);
+        if (next->ccache_name) 
+            sprintf(next->ccache_name, "%s:%s", cctype, ccname);
         next->from_lsa = lsa;
         next->expired = 1;
         next->expiration_time = 0;
@@ -867,9 +939,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)
@@ -912,9 +984,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;
@@ -925,11 +997,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;
 
@@ -1013,14 +1080,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;
 
@@ -1153,7 +1220,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);
@@ -1210,11 +1283,11 @@ 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 **cells = NULL;
@@ -1222,7 +1295,6 @@ KFW_AFS_get_cred( char * username,
     struct afsconf_cell cellconfig;
     char * dot;
 
-
     if (!pkrb5_init_context)
         return 0;
 
@@ -1245,24 +1317,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);
     }
@@ -1279,18 +1354,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);
@@ -1362,8 +1451,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;
 
@@ -1419,19 +1508,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;
@@ -1443,7 +1533,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;
@@ -1473,16 +1563,17 @@ 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;
@@ -1582,8 +1673,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;
 
@@ -1697,7 +1788,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);
 
 }
@@ -1723,13 +1815,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;
@@ -1840,12 +1932,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;
@@ -1882,7 +1974,11 @@ KFW_kinit( krb5_context alt_ctx,
        goto cleanup;
 
     if (lifetime == 0)
+#ifndef USE_LEASH
+        lifetime = 600;
+#else
         lifetime = pLeash_get_default_lifetime();
+#endif /* USE_LEASH */
     lifetime *= 60;
 
     if (renew_life > 0)
@@ -2006,8 +2102,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)
@@ -2636,13 +2732,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;
@@ -2704,19 +2800,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;
@@ -2983,6 +3081,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 
          */
@@ -2997,6 +3098,7 @@ KFW_AFS_klog(
             try_krb5 = 0;
             goto use_krb4;
         }
+#endif /* USE_KRB524 */
     } else {
       use_krb4:
 #ifdef USE_KRB4
@@ -3371,13 +3473,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;
 
@@ -3448,11 +3550,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())
@@ -3492,19 +3594,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));
@@ -3523,7 +3749,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;
@@ -3537,6 +3763,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:
@@ -3558,26 +3787,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)
 {
-    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;
     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;