pr_init-fix-20050623
[openafs.git] / src / WINNT / afsd / afskfw.c
index c57dcb7..a7b78ab 100644 (file)
@@ -65,6 +65,8 @@
 #include <afs/ptserver.h>
 #include <afs/ptuser.h>
 
+#include <WINNT\afsreg.h>
+
 /*
  * TIMING _____________________________________________________________________
  *
@@ -100,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);
@@ -154,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);
@@ -226,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),
@@ -280,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),
@@ -357,7 +367,9 @@ 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;
@@ -367,6 +379,7 @@ 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;
@@ -403,6 +416,7 @@ KFW_initialize(void)
             LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 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];
@@ -425,30 +439,32 @@ KFW_initialize(void)
 void
 KFW_cleanup(void)
 {
-    if (hKrb5)
-        FreeLibrary(hKrb5);
-    if (hKrb4)
-        FreeLibrary(hKrb4);
-    if (hProfile)
-        FreeLibrary(hProfile);
-    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)
 {
@@ -456,7 +472,7 @@ KFW_use_krb524(void)
     DWORD code, len;
     DWORD use524 = 0;
 
-    code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(use524);
@@ -465,7 +481,7 @@ KFW_use_krb524(void)
         RegCloseKey(parmKey);
     }
     if (code != ERROR_SUCCESS) {
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
                              0, KEY_QUERY_VALUE, &parmKey);
         if (code == ERROR_SUCCESS) {
             len = sizeof(use524);
@@ -484,7 +500,7 @@ KFW_is_available(void)
     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) {
         len = sizeof(enableKFW);
@@ -494,7 +510,7 @@ KFW_is_available(void)
     }
     
     if (code != ERROR_SUCCESS) {
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
                              0, KEY_QUERY_VALUE, &parmKey);
         if (code == ERROR_SUCCESS) {
             len = sizeof(enableKFW);
@@ -901,8 +917,9 @@ KFW_import_windows_lsa(void)
     char * pname = NULL;
     krb5_data *  princ_realm;
     krb5_error_code code;
-    char cell[128]="", realm[128]="";
+    char cell[128]="", realm[128]="", *def_realm = 0;
     int i;
+    DWORD dwMsLsaImport;
          
     if (!pkrb5_init_context)
         return;
@@ -923,6 +940,32 @@ 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;
 
@@ -949,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)
@@ -1035,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;
                 }
@@ -1195,8 +1240,9 @@ KFW_AFS_get_cred( char * username,
     if ( code ) goto cleanup;
 
     realm = afs_realm_of_cell(ctx, &cellconfig);  // do not free
+
     userrealm = strchr(username,'@');
-    if (userrealm) {
+    if ( userrealm ) {
         pname = strdup(username);
         userrealm = strchr(pname, '@');
         *userrealm = '\0';
@@ -1219,7 +1265,6 @@ KFW_AFS_get_cred( char * username,
         strcat(pname,"@");
         strcat(pname,realm);
     }
-
     if ( IsDebuggerPresent() ) {
         OutputDebugString("Realm: ");
         OutputDebugString(realm);
@@ -1325,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");
     }
@@ -1377,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)
 {
@@ -2443,26 +2542,6 @@ ViceIDToUsername(char *username,
         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';
-        }
-    }
-
     strcpy(lastcell, aserver->cell);
 
     if (!pr_Initialize (0, confname, aserver->cell))
@@ -2503,14 +2582,6 @@ 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))
@@ -2625,7 +2696,7 @@ KFW_AFS_klog(
         goto skip_krb5_init;
     }
 
-    /* lookfor client principals which cannot be distinguished 
+    /* look for client principals which cannot be distinguished 
      * from Kerberos 4 multi-component principal names
      */
     k5data = krb5_princ_component(ctx,client_principal,0);
@@ -3364,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;
+}