#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"
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)
*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;
#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.
* 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;
}