pr_init-fix-20050623
[openafs.git] / src / WINNT / afsd / afskfw.c
index d03dc24..a7b78ab 100644 (file)
 
 
 #define USE_MS2MIT
-#define USE_KRB4
+#undef  USE_KRB4
 #include "afskfw-int.h"
 #include "afskfw.h"
 
 #include <osilog.h>
 #include <rxkad_prototypes.h>   /* for life_to_time */
+#include <afs/ptserver.h>
+#include <afs/ptuser.h>
+
+#include <WINNT\afsreg.h>
 
 /*
  * TIMING _____________________________________________________________________
@@ -98,6 +102,7 @@ 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);
+DECL_FUNC_PTR(Leash_get_default_mslsa_import);
 
 // krb5 functions
 DECL_FUNC_PTR(krb5_change_password);
@@ -152,6 +157,7 @@ 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_default_realm);
 DECL_FUNC_PTR(krb5_free_ticket);
 DECL_FUNC_PTR(krb5_decode_ticket);
 DECL_FUNC_PTR(krb5_get_host_realm);
@@ -199,16 +205,6 @@ 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),
@@ -234,6 +230,11 @@ FUNC_INFO leash_fi[] = {
     END_FUNC_INFO
 };
 
+FUNC_INFO leash_opt_fi[] = {
+    MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
+    END_FUNC_INFO
+};
+
 FUNC_INFO k5_fi[] = {
     MAKE_FUNC_INFO(krb5_change_password),
     MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
@@ -288,6 +289,7 @@ FUNC_INFO k5_fi[] = {
     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_default_realm),
     MAKE_FUNC_INFO(krb5_free_ticket),
     MAKE_FUNC_INFO(krb5_decode_ticket),
     MAKE_FUNC_INFO(krb5_get_host_realm),
@@ -297,6 +299,7 @@ FUNC_INFO k5_fi[] = {
     END_FUNC_INFO
 };
 
+#ifdef USE_KRB4
 FUNC_INFO k4_fi[] = {
     MAKE_FUNC_INFO(krb_get_cred),
     MAKE_FUNC_INFO(krb_get_tf_realm),
@@ -304,6 +307,7 @@ FUNC_INFO k4_fi[] = {
     MAKE_FUNC_INFO(tkt_string),
     END_FUNC_INFO
 };
+#endif
 
 FUNC_INFO k524_fi[] = {
     MAKE_FUNC_INFO(krb524_init_ets),
@@ -349,22 +353,8 @@ FUNC_INFO lsa_fi[] = {
 };
 #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 *);
+char *afs_realm_of_cell(krb5_context, 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,
@@ -377,18 +367,19 @@ static int                inited = 0;
 static int                mid_cnt = 0;
 static struct textField * mid_tb = NULL;
 static HINSTANCE hKrb5 = 0;
+#ifdef USE_KRB4
 static HINSTANCE hKrb4 = 0;
+#endif /* USE_KRB4 */
 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 hLeashOpt = 0;
 static HINSTANCE hCCAPI = 0;
 static struct principal_ccache_data * princ_cc_data = NULL;
 static struct cell_principal_map    * cell_princ_map = NULL;
@@ -413,7 +404,9 @@ KFW_initialize(void)
         if ( !inited ) {
             inited = 1;
             LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 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
@@ -421,10 +414,9 @@ KFW_initialize(void)
 #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);
+            LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
 
             if ( KFW_is_available() ) {
                 char rootcell[MAXCELLCHARS+1];
@@ -435,7 +427,7 @@ KFW_initialize(void)
                 KFW_AFS_renew_expiring_tokens();
 
                 /* WIN32 NOTE: no way to get max chars */
-                if (!pcm_GetRootCellName(rootcell))
+                if (!cm_GetRootCellName(rootcell))
                     KFW_AFS_renew_token_for_cell(rootcell);
             }
         }
@@ -447,55 +439,86 @@ KFW_initialize(void)
 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);
+    if (hLeashOpt)
+        FreeLibrary(hLeashOpt);
+    if (hCCAPI)
+        FreeLibrary(hCCAPI);
+    if (hLeash)
+        FreeLibrary(hLeash);
+    if (hKrb524)
+        FreeLibrary(hKrb524);
 #ifdef USE_MS2MIT
     if (hSecur32)
         FreeLibrary(hSecur32);
 #endif /* USE_MS2MIT */
-    if (hKrb524)
-        FreeLibrary(hKrb524);
-    if (hLeash)
-        FreeLibrary(hLeash);
-    if (hCCAPI)
-        FreeLibrary(hCCAPI);
+    if (hService)
+        FreeLibrary(hService);
+    if (hComErr)
+        FreeLibrary(hComErr);
+    if (hProfile)
+        FreeLibrary(hProfile);
+#ifdef USE_KRB4
+    if (hKrb4)
+        FreeLibrary(hKrb4);
+#endif /* USE_KRB4 */
+    if (hKrb5)
+        FreeLibrary(hKrb5);
 }
 
-static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
+int
+KFW_use_krb524(void)
+{
+    HKEY parmKey;
+    DWORD code, len;
+    DWORD use524 = 0;
+
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        len = sizeof(use524);
+        code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+                                (BYTE *) &use524, &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(use524);
+            code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+                                    (BYTE *) &use524, &len);
+            RegCloseKey (parmKey);
+        }
+    }
+    return use524;
+}
 
 int 
 KFW_is_available(void)
 {
     HKEY parmKey;
-       DWORD code, len;
+    DWORD code, len;
     DWORD enableKFW = 1;
 
-    code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
-    if (code != ERROR_SUCCESS)
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
-                             0, KEY_QUERY_VALUE, &parmKey);
-       if (code == ERROR_SUCCESS) {
+    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 (code != ERROR_SUCCESS) {
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+                             0, KEY_QUERY_VALUE, &parmKey);
+        if (code == ERROR_SUCCESS) {
+            len = sizeof(enableKFW);
+            code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
+                                    (BYTE *) &enableKFW, &len);
+            RegCloseKey (parmKey);
+        }
+    } 
 
     if ( !enableKFW )
         return FALSE;
@@ -506,7 +529,7 @@ KFW_is_available(void)
          hSecur32 && 
 #endif /* USE_MS2MIT */
          hKrb524 &&
-         hProfile && hAfsTokens && hAfsConf && hLeash && hCCAPI )
+         hProfile && hLeash && hCCAPI )
         return TRUE;
     return FALSE;
 }
@@ -892,10 +915,11 @@ KFW_import_windows_lsa(void)
     krb5_ccache  cc = 0;
     krb5_principal princ = 0;
     char * pname = NULL;
-    krb5_data *  realm;
+    krb5_data *  princ_realm;
     krb5_error_code code;
-    char cell[128]="";
+    char cell[128]="", realm[128]="", *def_realm = 0;
     int i;
+    DWORD dwMsLsaImport;
          
     if (!pkrb5_init_context)
         return;
@@ -916,16 +940,44 @@ KFW_import_windows_lsa(void)
     code = pkrb5_cc_get_principal(ctx, cc, &princ);
     if ( code ) goto cleanup;
 
+    dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
+    switch ( dwMsLsaImport ) {
+    case 0: /* do not import */
+        goto cleanup;
+    case 1: /* always import */
+        break;
+    case 2: { /* matching realm */
+        char ms_realm[128] = "", *r;
+        int i;
+
+        for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
+            *r = krb5_princ_realm(ctx, princ)->data[i];
+        }
+        *r = '\0';
+
+        if (code = pkrb5_get_default_realm(ctx, &def_realm))
+            goto cleanup;
+
+        if (strcmp(def_realm, ms_realm))
+            goto cleanup;
+        break;
+    }
+    default:
+        break;
+    }
+
     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]);
+    princ_realm = krb5_princ_realm(ctx, princ);
+    for ( i=0; i<princ_realm->length; i++ ) {
+        realm[i] = princ_realm->data[i];
+        cell[i] = tolower(princ_realm->data[i]);
     }
-       cell[i] = '\0';
+    cell[i] = '\0';
+    realm[i] = '\0';
 
-    code = KFW_AFS_klog(ctx, cc, "afs", cell, realm->data, pLeash_get_default_lifetime(),NULL);
+    code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
     if ( IsDebuggerPresent() ) {
         char message[256];
         sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
@@ -940,6 +992,8 @@ KFW_import_windows_lsa(void)
         pkrb5_free_unparsed_name(ctx,pname);
     if (princ)
         pkrb5_free_principal(ctx,princ);
+    if (def_realm)
+        pkrb5_free_default_realm(ctx, def_realm);
     if (cc)
         pkrb5_cc_close(ctx,cc);
     if (ctx)
@@ -1026,7 +1080,7 @@ KFW_import_ccache_data(void)
                     code = pkrb5_cc_close(ctx,cc);
                     cc = 0;
                     code = pkrb5_cc_close(ctx,oldcc);
-                    cc = 0;
+                    oldcc = 0;
                     KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
                     continue;
                 }
@@ -1071,7 +1125,7 @@ KFW_import_ccache_data(void)
                 strcpy(aserver.name, sname->data);
                 strcpy(aserver.cell, cell->data);
 
-                code = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
+                code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
                 if (!code) {
                     // Found a token in AFS Client Server which matches
                     char pname[128], *p, *q;
@@ -1148,7 +1202,7 @@ KFW_import_ccache_data(void)
 
 
 int
-KFW_AFS_get_cred(char * username, 
+KFW_AFS_get_cred( char * username, 
                   char * cell,
                   char * password,
                   int lifetime,
@@ -1157,8 +1211,7 @@ KFW_AFS_get_cred(char * username,
 {
     krb5_context ctx = 0;
     krb5_ccache cc = 0;
-    char * realm = 0;
-    char ** realmlist = 0;
+    char * realm = 0, * userrealm = 0;
     krb5_principal principal = 0;
     char * pname = 0;
     krb5_error_code code;
@@ -1166,6 +1219,8 @@ KFW_AFS_get_cred(char * username,
     char **cells = NULL;
     int  cell_count=0;
     struct afsconf_cell cellconfig;
+    char * dot;
+
 
     if (!pkrb5_init_context)
         return 0;
@@ -1184,51 +1239,66 @@ KFW_AFS_get_cred(char * username,
     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
+    realm = afs_realm_of_cell(ctx, &cellconfig);  // do not free
 
+    userrealm = strchr(username,'@');
+    if ( userrealm ) {
+        pname = strdup(username);
+        userrealm = strchr(pname, '@');
+        *userrealm = '\0';
+
+        /* handle kerberos iv notation */
+        while ( dot = strchr(pname,'.') ) {
+            *dot = '/';
+        }
+        *userrealm++ = '@';
+    } else {
+        pname = malloc(strlen(username) + strlen(realm) + 2);
+
+        strcpy(pname, username);
+
+        /* handle kerberos iv notation */
+        while ( dot = strchr(pname,'.') ) {
+            *dot = '/';
+        }
+
+        strcat(pname,"@");
+        strcat(pname,realm);
+    }
     if ( IsDebuggerPresent() ) {
         OutputDebugString("Realm: ");
         OutputDebugString(realm);
         OutputDebugString("\n");
     }
 
-    code = pkrb5_build_principal(ctx, &principal, strlen(realm),
-                                 realm, username,
-                                 NULL,
-                                 NULL);
-
-    code = KFW_get_ccache(ctx, principal, &cc);
+    code = pkrb5_parse_name(ctx, pname, &principal);
     if ( code ) goto cleanup;
 
-    code = pkrb5_unparse_name(ctx, principal, &pname);
+    code = KFW_get_ccache(ctx, principal, &cc);
     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 ( password && password[0] ) {
+        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);
     }
-    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() ) {
@@ -1254,7 +1324,7 @@ KFW_AFS_get_cred(char * username,
                 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
                 if ( code ) continue;
     
-                realm = afs_realm_of_cell(&cellconfig);  // do not free
+                realm = afs_realm_of_cell(ctx, &cellconfig);  // do not free
                 if ( IsDebuggerPresent() ) {
                     OutputDebugString("Realm: ");
                     OutputDebugString(realm);
@@ -1278,7 +1348,7 @@ KFW_AFS_get_cred(char * username,
 
   cleanup:
     if ( pname )
-        pkrb5_free_unparsed_name(ctx,pname);
+        free(pname);
     if ( cc )
         pkrb5_cc_close(ctx, cc);
 
@@ -1300,7 +1370,7 @@ KFW_AFS_destroy_tickets_for_cell(char * cell)
         return 0;
 
     if ( IsDebuggerPresent() ) {
-        OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
+        OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
         OutputDebugString(cell);
         OutputDebugString("\n");
     }
@@ -1352,6 +1422,60 @@ KFW_AFS_destroy_tickets_for_cell(char * cell)
     return 0;
 }
 
+int 
+KFW_AFS_destroy_tickets_for_principal(char * user)
+{
+    krb5_context               ctx = 0;
+    krb5_error_code            code;
+    int count;
+    char ** cells = NULL;
+    krb5_principal      princ = 0;
+    krb5_ccache                        cc  = 0;
+
+    if (!pkrb5_init_context)
+        return 0;
+
+    if ( IsDebuggerPresent() ) {
+        OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
+        OutputDebugString(user);
+        OutputDebugString("\n");
+    }
+
+    code = pkrb5_init_context(&ctx);
+    if (code) ctx = 0;
+
+    code = pkrb5_parse_name(ctx, user, &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;
+    }
+
+    count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
+    if ( count >= 1 ) {
+        while ( count-- ) {
+            KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
+            free(cells[count]);
+        }
+        free(cells);
+    }
+
+    pkrb5_free_context(ctx);
+    return 0;
+}
+
 int
 KFW_AFS_renew_expiring_tokens(void)
 {
@@ -1419,7 +1543,7 @@ KFW_AFS_renew_expiring_tokens(void)
                     }
                     code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
                     if ( code ) continue;
-                    realm = afs_realm_of_cell(&cellconfig);  // do not free
+                    realm = afs_realm_of_cell(ctx, &cellconfig);  // do not free
                     if ( IsDebuggerPresent() ) {
                         OutputDebugString("Realm: ");
                         OutputDebugString(realm);
@@ -1503,7 +1627,7 @@ KFW_AFS_renew_token_for_cell(char * cell)
             code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
             if ( code ) goto loop_cleanup;
 
-            realm = afs_realm_of_cell(&cellconfig);  // do not free
+            realm = afs_realm_of_cell(ctx, &cellconfig);  // do not free
             if ( IsDebuggerPresent() ) {
                 OutputDebugString("Realm: ");
                 OutputDebugString(realm);
@@ -2386,11 +2510,93 @@ KFW_AFS_unlog(void)
     if (CurrentState != SERVICE_RUNNING)
         return(0);
 
-    rc = pktc_ForgetAllTokens();
+    rc = ktc_ForgetAllTokens();
 
     return(0);
 }
 
+
+#define ALLOW_REGISTER 1
+static int
+ViceIDToUsername(char *username, 
+                 char *realm_of_user, 
+                 char *realm_of_cell,
+                 char * cell_to_use,
+                 struct ktc_principal *aclient, 
+                 struct ktc_principal *aserver, 
+                 struct ktc_token *atoken)
+{
+    static char lastcell[MAXCELLCHARS+1] = { 0 };
+    static char confname[512] = { 0 };
+#ifdef AFS_ID_TO_NAME
+    char username_copy[BUFSIZ];
+#endif /* AFS_ID_TO_NAME */
+    long viceId;                       /* 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';
+    }
+
+    strcpy(lastcell, aserver->cell);
+
+    if (!pr_Initialize (0, confname, aserver->cell))
+        status = pr_SNameToId (username, &viceId);
+
+    /*
+     * This is a crock, but it is Transarc's crock, so
+     * we have to play along in order to get the
+     * functionality.  The way the afs id is stored is
+     * as a string in the username field of the token.
+     * Contrary to what you may think by looking at
+     * the code for tokens, this hack (AFS ID %d) will
+     * not work if you change %d to something else.
+     */
+
+    /*
+     * This code is taken from cklog -- it lets people
+     * automatically register with the ptserver in foreign cells
+     */
+
+#ifdef ALLOW_REGISTER
+    if (status == 0) {
+        if (viceId != ANONYMOUSID) {
+#else /* ALLOW_REGISTER */
+            if ((status == 0) && (viceId != ANONYMOUSID))
+#endif /* ALLOW_REGISTER */
+            {
+#ifdef AFS_ID_TO_NAME
+                strncpy(username_copy, username, BUFSIZ);
+                snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
+#endif /* AFS_ID_TO_NAME */
+            }
+#ifdef ALLOW_REGISTER
+        } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
+            id = 0;
+            strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
+            strcpy(aclient->instance, "");
+            strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
+            if (status = ktc_SetToken(aserver, atoken, aclient, 0))
+                return status;
+            if (status = pr_Initialize(1L, confname, aserver->cell))
+                return status;
+            if (status = pr_CreateUser(username, &id))
+                return status;
+#ifdef AFS_ID_TO_NAME
+            strncpy(username_copy, username, BUFSIZ);
+            snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
+#endif /* AFS_ID_TO_NAME */
+        }
+    }
+#endif /* ALLOW_REGISTER */
+    return status;
+}
+
+
 int
 KFW_AFS_klog(
     krb5_context alt_ctx,
@@ -2404,7 +2610,9 @@ KFW_AFS_klog(
 {
     long       rc = 0;
     CREDENTIALS        creds;
+#ifdef USE_KRB4
     KTEXT_ST    ticket;
+#endif /* USE_KRB4 */
     struct ktc_principal       aserver;
     struct ktc_principal       aclient;
     char       realm_of_user[REALM_SZ]; /* Kerberos realm of user */
@@ -2426,7 +2634,7 @@ KFW_AFS_klog(
     krb5_creds * k5creds = 0;
     krb5_error_code code;
     krb5_principal client_principal = 0;
-    char * cname = 0, *sname = 0;
+    krb5_data * k5data;
     int i, retry = 0;
 
     CurrentState = 0;
@@ -2451,10 +2659,10 @@ KFW_AFS_klog(
     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));
+    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))
@@ -2480,13 +2688,29 @@ KFW_AFS_klog(
     memset((char *)&increds, 0, sizeof(increds));
 
     code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
-       if (code) {
+    if (code) {
         if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() ) 
         {
             OutputDebugString("Principal Not Found for ccache\n");
         }
         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;
+    }
+
     i = krb5_princ_realm(ctx, client_principal)->length;
     if (i > REALM_SZ-1) 
         i = REALM_SZ-1;
@@ -2503,9 +2727,10 @@ KFW_AFS_klog(
         }       
     }
 #else
-    goto cleanup;
+    if (!try_krb5)
+        goto cleanup;
 #endif
-    strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
+    strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
 
     if (strlen(service) == 0)
         strcpy(ServiceName, "afs");
@@ -2545,6 +2770,7 @@ KFW_AFS_klog(
 
 
         if ( IsDebuggerPresent() ) {
+            char * cname, *sname;
             pkrb5_unparse_name(ctx, increds.client, &cname);
             pkrb5_unparse_name(ctx, increds.server, &sname);
             OutputDebugString("Getting tickets for \"");
@@ -2552,13 +2778,14 @@ KFW_AFS_klog(
             OutputDebugString("\" and service \"");
             OutputDebugString(sname);
             OutputDebugString("\"\n");
-            cname = sname = 0;
+            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) {
+             code == KRB5KRB_AP_ERR_MSG_TYPE) {
             /* Or service@REALM */
             pkrb5_free_principal(ctx,increds.server);
             increds.server = 0;
@@ -2580,7 +2807,6 @@ KFW_AFS_klog(
                 OutputDebugString("\"\n");
                 pkrb5_free_unparsed_name(ctx,cname);
                 pkrb5_free_unparsed_name(ctx,sname);
-                cname = sname = 0;
             }
 
             if (!code)
@@ -2589,7 +2815,7 @@ KFW_AFS_klog(
 
         if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
               code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
-                         code == KRB5KRB_AP_ERR_MSG_TYPE) &&
+              code == KRB5KRB_AP_ERR_MSG_TYPE) &&
              strcmp(RealmName, realm_of_cell)) {
             /* Or service/cell@REALM_OF_CELL */
             strcpy(RealmName, realm_of_cell);
@@ -2614,7 +2840,6 @@ KFW_AFS_klog(
                 OutputDebugString("\"\n");
                 pkrb5_free_unparsed_name(ctx,cname);
                 pkrb5_free_unparsed_name(ctx,sname);
-                cname = sname = 0;
             }
 
             if (!code)
@@ -2645,7 +2870,6 @@ KFW_AFS_klog(
                     OutputDebugString("\"\n");
                     pkrb5_free_unparsed_name(ctx,cname);
                     pkrb5_free_unparsed_name(ctx,sname);
-                    cname = sname = 0;
                 }
 
                 if (!code)
@@ -2667,7 +2891,8 @@ KFW_AFS_klog(
          * No need to perform a krb524 translation which is 
          * commented out in the code below
          */
-        if (k5creds->ticket.length > MAXKTCTICKETLEN)
+        if (KFW_use_krb524() ||
+            k5creds->ticket.length > MAXKTCTICKETLEN)
             goto try_krb524d;
 
         memset(&aserver, '\0', sizeof(aserver));
@@ -2683,7 +2908,7 @@ KFW_AFS_klog(
         memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
 
       retry_gettoken5:
-        rc = pktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
+        rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
         if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
             if ( rc == KTC_NOCM && retry < 20 ) {
                 Sleep(500);
@@ -2732,14 +2957,17 @@ KFW_AFS_klog(
             p[len] = '\0';
         }
 
+        ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
+                         &aclient, &aserver, &atoken);
+
         if ( smbname ) {
-            strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
-            aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+            strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+            aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
         } else {
             aclient.smbname[0] = '\0';
         }
 
-        rc = pktc_SetToken(&aserver, &atoken, &aclient, 0);
+        rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
         if (!rc)
             goto cleanup;   /* We have successfully inserted the token */
 
@@ -2809,7 +3037,7 @@ KFW_AFS_klog(
     memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
 
   retry_gettoken:
-    rc = pktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
+    rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
     if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
         if ( rc == KTC_NOCM && retry < 20 ) {
             Sleep(500);
@@ -2850,14 +3078,17 @@ KFW_AFS_klog(
 
     strcpy(aclient.cell, CellName);
 
+    ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
+                      &aclient, &aserver, &atoken);
+
     if ( smbname ) {
-        strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
-        aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+        strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+        aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
     } else {
         aclient.smbname[0] = '\0';
     }
 
-    if (rc = pktc_SetToken(&aserver, &atoken, &aclient, 0))
+    if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
     {
         KFW_AFS_error(rc, "ktc_SetToken()");
         code = rc;
@@ -2865,10 +3096,6 @@ KFW_AFS_klog(
     }
 
   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 */
@@ -2879,35 +3106,27 @@ KFW_AFS_klog(
     if (ctx && (ctx != alt_ctx))
         pkrb5_free_context(ctx);
 
-       return(rc? rc : code);
+    return(rc? rc : code);
 }
 
 /**************************************/
 /* afs_realm_of_cell():               */
 /**************************************/
 static char *
-afs_realm_of_cell(struct afsconf_cell *cellconfig)
+afs_realm_of_cell(krb5_context ctx, 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);
+    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] )
     {
@@ -2926,7 +3145,7 @@ afs_realm_of_cell(struct afsconf_cell *cellconfig)
 }
 
 /**************************************/
-/* KFW_AFS_get_cellconfig():                  */
+/* KFW_AFS_get_cellconfig():          */
 /**************************************/
 int 
 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
@@ -2938,7 +3157,7 @@ KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_
     memset(cellconfig, 0, sizeof(*cellconfig));
 
     /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
-    if (rc = pcm_GetRootCellName(local_cell))
+    if (rc = cm_GetRootCellName(local_cell))
     {
         return(rc);
     }
@@ -2949,7 +3168,14 @@ KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_
     /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
     strcpy(cellconfig->name, cell);
 
-    return pcm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
+    rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
+#ifdef AFS_AFSDB_ENV
+    if (rc != 0) {
+        int ttl;
+        rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
+    }
+#endif
+    return rc;
 }
 
 /**************************************/
@@ -3145,7 +3371,14 @@ BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
     char   password[PROBE_PASSWORD_LEN+1];
     BOOL serverReachable = 0;
 
-    realm = afs_realm_of_cell(cellconfig);  // do not free
+    if (!pkrb5_init_context)
+        return 0;
+
+    code = pkrb5_init_context(&ctx);
+    if (code) goto cleanup;
+
+
+    realm = afs_realm_of_cell(ctx, cellconfig);  // do not free
 
     code = pkrb5_build_principal(ctx, &principal, strlen(realm),
                                   realm, PROBE_USERNAME, NULL, NULL);
@@ -3202,3 +3435,176 @@ BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
     return serverReachable;
 }
 
+BOOL
+KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
+{
+    krb5_context   ctx = 0;
+    krb5_error_code code;
+    krb5_ccache mslsa_ccache=0;
+    krb5_principal princ = 0;
+    char * pname = 0;
+    BOOL success = 0;
+
+    if (!KFW_is_available())
+        return FALSE;
+
+    if (code = pkrb5_init_context(&ctx))
+        goto cleanup;
+
+    if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
+        goto cleanup;
+
+    if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
+        goto cleanup;
+
+    if (code = pkrb5_unparse_name(ctx, princ, &pname))
+        goto cleanup;
+
+    if ( strlen(pname) < *dwSize ) {
+        strncpy(szUser, pname, *dwSize);
+        szUser[*dwSize-1] = '\0';
+        success = 1;
+    }
+    *dwSize = strlen(pname);
+
+  cleanup:
+    if (pname)
+        pkrb5_free_unparsed_name(ctx, pname);
+
+    if (princ)
+        pkrb5_free_principal(ctx, princ);
+
+    if (mslsa_ccache)
+        pkrb5_cc_close(ctx, mslsa_ccache);
+
+    if (ctx)
+        pkrb5_free_context(ctx);
+    return success;
+}
+
+void
+KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
+{
+    char filename[256];
+    DWORD count;
+    char cachename[264] = "FILE:";
+    krb5_context               ctx = 0;
+    krb5_error_code            code;
+    krb5_principal              princ = 0;
+    krb5_ccache                        cc  = 0;
+    krb5_ccache                 ncc = 0;
+
+    if (!pkrb5_init_context)
+        return;
+
+    count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
+    if ( count > sizeof(filename) || count == 0 ) {
+        GetWindowsDirectory(filename, sizeof(filename));
+    }
+
+    if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
+        return;
+
+    strcat(filename, "\\");
+    strcat(filename, szLogonId);    
+
+    strcat(cachename, filename);
+
+    DeleteFile(filename);
+
+    code = pkrb5_init_context(&ctx);
+    if (code) ctx = 0;
+
+    code = pkrb5_parse_name(ctx, user, &princ);
+    if (code) goto cleanup;
+
+    code = KFW_get_ccache(ctx, princ, &cc);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_resolve(ctx, cachename, &ncc);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_initialize(ctx, ncc, princ);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+
+  cleanup:
+    if ( cc ) {
+        pkrb5_cc_close(ctx, cc);
+        cc = 0;
+    }
+    if ( ncc ) {
+        pkrb5_cc_close(ctx, ncc);
+        ncc = 0;
+    }
+    if ( princ ) {
+        pkrb5_free_principal(ctx, princ);
+        princ = 0;
+    }
+
+    if (ctx)
+        pkrb5_free_context(ctx);
+}
+
+int
+KFW_AFS_copy_system_file_to_default_cache(char * filename)
+{
+    DWORD count;
+    char cachename[264] = "FILE:";
+    HANDLE hFile;
+    krb5_context               ctx = 0;
+    krb5_error_code            code;
+    krb5_principal              princ = 0;
+    krb5_ccache                        cc  = 0;
+    krb5_ccache                 ncc = 0;
+    int retval = 1;
+
+    if (!pkrb5_init_context)
+        return 1;
+
+    if ( strlen(filename) + 6 > sizeof(cachename) )
+        return 1;
+
+    strcat(cachename, filename);
+
+    code = pkrb5_init_context(&ctx);
+    if (code) ctx = 0;
+
+    code = pkrb5_cc_resolve(ctx, cachename, &cc);
+    if (code) goto cleanup;
+    
+    code = pkrb5_cc_get_principal(ctx, cc, &princ);
+
+    code = pkrb5_cc_default(ctx, &ncc);
+    if (!code) {
+        code = pkrb5_cc_initialize(ctx, ncc, princ);
+
+        if (!code)
+            code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+    }
+    if ( ncc ) {
+        pkrb5_cc_close(ctx, ncc);
+        ncc = 0;
+    }
+
+    retval=0;   /* success */
+
+  cleanup:
+    if ( cc ) {
+        pkrb5_cc_close(ctx, cc);
+        cc = 0;
+    }
+
+    DeleteFile(filename);
+
+    if ( princ ) {
+        pkrb5_free_principal(ctx, princ);
+        princ = 0;
+    }
+
+    if (ctx)
+        pkrb5_free_context(ctx);
+
+    return 0;
+}