Correct Heimdal conversion of libadmin/adminutil
authorJeffrey Altman <jaltman@your-file-system.com>
Sat, 8 Oct 2011 08:01:07 +0000 (10:01 +0200)
committerJeffrey Altman <jaltman@openafs.org>
Sun, 9 Oct 2011 14:39:07 +0000 (07:39 -0700)
Patchset 4251e386aa25bb3fc02fa255e92327fffc8b954d converts to
using Heimdal.  The conversion undid the introduction of the
abstraction function fetch_krb5_error_message() which is
implemented in src/util.  Restore the use of fetch_krb5_error_message()
and modify src/util/krb5_nt.c to use the Kerberos Compat SDK
interface.

Change-Id: I67fe7a309727f67a1da3705e1e485e64747c325c
Reviewed-on: http://gerrit.openafs.org/5571
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>

src/libadmin/adminutil/afs_utilAdmin.c
src/util/NTMakefile
src/util/krb5_nt.c
src/util/krb5_nt.h

index fd2ecc7..eab3c8e 100644 (file)
 #include <rx/rx.h>
 #include <rx/rxstat.h>
 
+#ifdef AFS_NT40_ENV
+# include <winsock2.h>
+# include <afs/krb5_nt.h>
+#endif
+
 #include <afs/afs_Admin.h>
 #include <afs/pthread_glock.h>
 #include <afs/cellconfig.h>
 #include <afs/volser.h>
 #include <afs/afscbint.h>
 
-#ifdef AFS_NT40_ENV
-# define EncryptionKey Krb5EncryptionKey
-#  include <krb5/krb5.h>
-# undef EncryptionKey
-#endif
-
 #include "afs_AdminInternal.h"
 #include "afs_utilAdmin.h"
 
@@ -76,9 +75,15 @@ init_once(void)
     initialize_AU_error_table();
     initialize_AV_error_table();
     initialize_VOLS_error_table();
+#ifdef AFS_KRB5_ERROR_ENV
+    initialize_krb5();
+#endif
     error_init_done = 1;
 }
 
+/*
+ * (*errorTextP) will not be freed by the caller.
+ */
 int ADMINAPI
 util_AdminErrorCodeTranslate(afs_status_t errorCode, int langId,
                             const char **errorTextP, afs_status_p st)
@@ -102,17 +107,9 @@ util_AdminErrorCodeTranslate(afs_status_t errorCode, int langId,
     *errorTextP = afs_error_message(code);
 #ifdef AFS_KRB5_ERROR_ENV
     if (strncmp(*errorTextP, "unknown", strlen("unknown")) == 0) {
-        krb5_context context;
-        if (!krb5_init_context(&context))
-        {
-            char *msg;
-            msg = krb5_get_error_message(context, code);
-            if (msg) {
-                *errorTextP = strdup(msg);
-                krb5_free_error_message(context, msg);
-            }
-            krb5_free_context(context);
-        }
+        const char *msg = fetch_krb5_error_message(code);
+        if (msg)
+            *errorTextP = msg;
     }
 #endif
     rc = 1;
index 71a068f..234c376 100644 (file)
@@ -23,6 +23,7 @@ INCFILES =\
        $(INCFILEDIR)\pthread_nosigs.h \
        $(INCFILEDIR)\errmap_nt.h \
        $(INCFILEDIR)\dirpath.h \
+        $(INCFILEDIR)\krb5_nt.h \
        $(INCFILEDIR)\ktime.h \
        $(INCFILEDIR)\fileutil.h \
        $(INCFILEDIR)\afsutil_prototypes.h \
@@ -43,6 +44,7 @@ LIBOBJS = \
        $(OUT)\base32.obj \
        $(OUT)\get_krbrlm.obj \
        $(OUT)\hostparse.obj \
+        $(OUT)\krb5_nt.obj \
        $(OUT)\kreltime.obj \
        $(OUT)\ktime.obj \
         $(OUT)\netutils.obj \
@@ -61,6 +63,7 @@ MT_LIBOBJS = \
        $(OUT)\base32.obj \
        $(OUT)\get_krbrlm.obj \
        $(OUT)\hostparse.obj \
+        $(OUT)\krb5_nt.obj \
        $(OUT)\kreltime.obj \
        $(OUT)\ktime.obj \
         $(OUT)\netutils.obj \
index ac215df..47c3f63 100644 (file)
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <roken.h>
 
 #include <windows.h>
 #include "krb5_nt.h"
 
-static char * (KRB5_CALLCONV *pkrb5_get_error_message)(krb5_context context, krb5_error_code code) = NULL;
-static void (KRB5_CALLCONV *pkrb5_free_error_message)(krb5_context context, char *s) = NULL;
-
-# ifndef _WIN64
-#  define KRB5LIB "krb5_32.dll"
-# else
-#  define KRB5LIB "krb5_64.dll"
-# endif
+# include <krb5\krb5.h>
+# include <com_err.h>
 
+static int krb5_initialized = 0;
 
 void
 initialize_krb5(void)
 {
     /*
      * On Windows, the error table will be initialized when the
-     * krb5 library is loaded into the process.  Since not all
-     * versions of krb5 contain krb5_{get,free}_error_message()
-     * we load them conditionally by function pointer.
+     * krb5 library is loaded into the process for MIT KFW but
+     * for Heimdal the error table is initialized when the
+     * krb5_init_context() call is issued.  We always build
+     * against the Kerberos Compat SDK now so we do not have
+     * load by function pointer.  Use DelayLoadHeimd
      *
      * On Unix, the MIT krb5 error table will be initialized
      * by the library on first use.
@@ -55,26 +53,29 @@ initialize_krb5(void)
      * initialize_krb5_error_table is a macro substitution to
      * nothing.
      */
-    HINSTANCE h = LoadLibrary(KRB5LIB);
-    if (h) {
-        (FARPROC)pkrb5_get_error_message = GetProcAddress(h, "krb5_get_error_message");
-        (FARPROC)pkrb5_free_error_message = GetProcAddress(h, "krb5_free_error_message");
+    if (!DelayLoadHeimdal()) {
+        fprintf(stderr, "Kerberos for Windows or Heimdal is not available.\n");
+    } else {
+        krb5_initialized = 1;
     }
 }
 
 const char *
-fetch_krb5_error_message(krb5_context context, krb5_error_code code)
+fetch_krb5_error_message(afs_uint32 code)
 {
     static char errorText[1024];
+    char *msg = NULL;
+    krb5_context context;
 
-    if (pkrb5_get_error_message) {
-        char *msg = pkrb5_get_error_message(context, code);
+    if (krb5_initialized && krb5_init_context(&context) == 0) {
+        msg = krb5_get_error_message(context, code);
         if (msg) {
             strncpy(errorText, msg, sizeof(errorText));
             errorText[sizeof(errorText)-1]='\0';
-            pkrb5_free_error_message(context, msg);
-            return errorText;
+            krb5_free_error_message(context, msg);
+            msg = errorText;
         }
+        krb5_free_context(context);
     }
-    return NULL;
+    return msg;
 }
index f1e68c3..6d68889 100644 (file)
 
 #ifdef AFS_NT40_ENV
 
-# include <krb5\krb5.h>
-# include <com_err.h>
-
 extern void initialize_krb5(void);
-extern const char * fetch_krb5_error_message(krb5_context, krb5_error_code);
+extern const char * fetch_krb5_error_message(afs_uint32);
 
 #endif /* AFS_NT40_ENV */
\ No newline at end of file