INN commit: trunk (authprogs/auth_krb5.c configure.ac)
INN Commit
rra at isc.org
Sun Mar 4 03:40:18 UTC 2018
Date: Saturday, March 3, 2018 @ 19:40:17
Author: eagle
Revision: 10252
Stop using com_err directly
com_err is an obsolete way of reporting Kerberos errors. Add some
additional Kerberos portability code from rra-c-util to allow using
krb5_get_error_message, which is the modern approach, and remove the
additional probing for com_err.h.
Modified:
trunk/authprogs/auth_krb5.c
trunk/configure.ac
-----------------------+
authprogs/auth_krb5.c | 137 ++++++++++++++++++++++++++++++++++++++++--------
configure.ac | 46 ----------------
2 files changed, 117 insertions(+), 66 deletions(-)
Modified: authprogs/auth_krb5.c
===================================================================
--- authprogs/auth_krb5.c 2018-02-26 21:06:13 UTC (rev 10251)
+++ authprogs/auth_krb5.c 2018-03-04 03:40:17 UTC (rev 10252)
@@ -1,12 +1,12 @@
/* $Id$
**
-** Check an username and password against Kerberos v5.
+** Check an username and password against Kerberos.
**
** Based on nnrpkrb5auth by Christopher P. Lindsey <lindsey at mallorn.com>
** See <http://www.mallorn.com/tools/nnrpkrb5auth>
**
** This program takes a username and password pair from nnrpd and checks
-** checks their validity against a Kerberos v5 KDC by attempting to obtain a
+** checks their validity against a Kerberos KDC by attempting to obtain a
** TGT. With the -i <instance> command line option, appends /<instance> to
** the username prior to authentication.
**
@@ -21,28 +21,123 @@
#include "config.h"
#include "clibrary.h"
#include "libauth.h"
-#ifdef HAVE_ET_COM_ERR_H
-# include <et/com_err.h>
-#elif defined(HAVE_KERBEROSV5_COM_ERR_H)
-# include <kerberosv5/com_err.h>
-#else
-# include <com_err.h>
-#endif
-#ifdef HAVE_KRB5_H
+#if defined(HAVE_KRB5_H)
# include <krb5.h>
-#elif HAVE_KERBEROSV5_KRB5_H
+#elif defined(HAVE_KERBEROSV5_KRB5_H)
# include <kerberosv5/krb5.h>
#else
# include <krb5/krb5.h>
#endif
+/* Figure out what header files to include for error reporting. */
+#if !defined(HAVE_KRB5_GET_ERROR_MESSAGE) && !defined(HAVE_KRB5_GET_ERR_TEXT)
+# if !defined(HAVE_KRB5_GET_ERROR_STRING)
+# if defined(HAVE_IBM_SVC_KRB5_SVC_H)
+# include <ibm_svc/krb5_svc.h>
+# elif defined(HAVE_ET_COM_ERR_H)
+# include <et/com_err.h>
+# elif defined(HAVE_KERBEROSV5_COM_ERR_H)
+# include <kerberosv5/com_err.h>
+# else
+# include <com_err.h>
+# endif
+# endif
+#endif
+
#include "inn/messages.h"
#include "inn/libinn.h"
+#include "inn/xmalloc.h"
/*
+ * This string is returned for unknown error messages. We use a static
+ * variable so that we can be sure not to free it.
+ */
+#if !defined(HAVE_KRB5_GET_ERROR_MESSAGE) \
+ || !defined(HAVE_KRB5_FREE_ERROR_MESSAGE)
+static const char error_unknown[] = "unknown error";
+#endif
+
+
+#ifndef HAVE_KRB5_GET_ERROR_MESSAGE
+/*
+ * Given a Kerberos error code, return the corresponding error. Prefer the
+ * Kerberos interface if available since it will provide context-specific
+ * error information, whereas the error_message() call will only provide a
+ * fixed message.
+ */
+const char *
+krb5_get_error_message(krb5_context ctx UNUSED, krb5_error_code code UNUSED)
+{
+ const char *msg;
+
+# if defined(HAVE_KRB5_GET_ERROR_STRING)
+ msg = krb5_get_error_string(ctx);
+# elif defined(HAVE_KRB5_GET_ERR_TEXT)
+ msg = krb5_get_err_text(ctx, code);
+# elif defined(HAVE_KRB5_SVC_GET_MSG)
+ krb5_svc_get_msg(code, (char **) &msg);
+# else
+ msg = error_message(code);
+# endif
+ if (msg == NULL)
+ return error_unknown;
+ else
+ return msg;
+}
+#endif /* !HAVE_KRB5_GET_ERROR_MESSAGE */
+
+
+#ifndef HAVE_KRB5_FREE_ERROR_MESSAGE
+/*
+ * Free an error string if necessary. If we returned a static string, make
+ * sure we don't free it.
+ *
+ * This code assumes that the set of implementations that have
+ * krb5_free_error_message is a subset of those with krb5_get_error_message.
+ * If this assumption ever breaks, we may call the wrong free function.
+ */
+void
+krb5_free_error_message(krb5_context ctx UNUSED, const char *msg)
+{
+ if (msg == error_unknown)
+ return;
+# if defined(HAVE_KRB5_GET_ERROR_STRING)
+ krb5_free_error_string(ctx, (char *) msg);
+# elif defined(HAVE_KRB5_SVC_GET_MSG)
+ krb5_free_string(ctx, (char *) msg);
+# endif
+}
+#endif /* !HAVE_KRB5_FREE_ERROR_MESSAGE */
+
+
+/*
+** Report a Kerberos error to standard error.
+*/
+static void __attribute__((__format__(printf, 3, 0)))
+warn_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
+{
+ const char *k5_msg;
+ char *message;
+ va_list args;
+
+ k5_msg = krb5_get_error_message(ctx, code);
+ va_start(args, format);
+ xvasprintf(&message, format, args);
+ va_end(args);
+ if (k5_msg == NULL)
+ warn("%s", message);
+ else
+ warn("%s: %s", message, k5_msg);
+ free(message);
+ if (k5_msg != NULL)
+ krb5_free_error_message(ctx, k5_msg);
+}
+
+
+/*
** Check the username and password by attempting to get a TGT. Returns 1 on
-** success and 0 on failure. Errors are reported via com_err.
+** success and 0 on failure.
*/
static int
krb5_check_password(const char *principal, const char *password)
@@ -57,13 +152,12 @@
code = krb5_init_context(&ctx);
if (code != 0) {
- com_err(message_program_name, code, "initializing krb5 context");
+ warn_krb5(NULL, code, "cannot initialize Kerberos");
return 0;
}
code = krb5_parse_name(ctx, principal, &princ);
if (code != 0) {
- com_err(message_program_name, code, "parsing principal name %.100s",
- principal);
+ warn_krb5(ctx, code, "cannot parse principal %.100s", principal);
goto cleanup;
}
memset(&opts, 0, sizeof(opts));
@@ -85,16 +179,15 @@
else {
switch (code) {
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- com_err(message_program_name, 0, "bad password for %.100s",
- principal);
+ warn("bad password for %.100s", principal);
break;
case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- com_err(message_program_name, 0, "unknown user %.100s",
- principal);
+ warn("unknown user %.100s", principal);
break;
default:
- com_err(message_program_name, code,
- "checking Kerberos password for %.100s", principal);
+ warn_krb5(ctx, code, "Kerberos authentication for %.100s failed",
+ principal);
+ break;
}
}
@@ -132,7 +225,7 @@
/* May need to prepend instance name if -i option was given. */
if (argc > 1) {
if (argc == 3 && strcmp(argv[1], "-i") == 0) {
- new_user = concat(authinfo->username, "/", argv[2], (char *) 0);
+ xasprintf(&new_user, "%s/%s", authinfo->username, argv[2]);
free(authinfo->username);
authinfo->username = new_user;
} else {
Modified: configure.ac
===================================================================
--- configure.ac 2018-02-26 21:06:13 UTC (rev 10251)
+++ configure.ac 2018-03-04 03:40:17 UTC (rev 10252)
@@ -394,50 +394,8 @@
INN_LIB_ZLIB_OPTIONAL
dnl If Kerberos is found, define KRB5_AUTH to auth_krb5 so as to build
-dnl that program. In case neither et/com_err.h nor kerberosv5/com_err.h
-dnl nor com_err.h can be found and --with-krb5 is not given, do not define
-dnl KRB5_AUTH and clear the other variables set for Kerberos support.
-AS_IF([test x"$inn_use_KRB5" = xtrue],
- [inn_KRB5_incroot=
- inn_KRB5_header_found=
- AS_IF([test x"$inn_krb5_includedir" != x],
- [inn_KRB5_incroot="$inn_krb5_includedir"],
- [AS_IF([test x"$inn_krb5_root" != x],
- [inn_KRB5_incroot="${inn_krb5_root}/include"])])
- AS_IF([test x"$inn_KRB5_incroot" = x],
- [AC_CHECK_HEADERS([et/com_err.h],
- [inn_KRB5_header_found=yes],
- [inn_KRB5_header_found=no])],
- [AS_IF([test -f "${inn_KRB5_incroot}/et/com_err.h"],
- [inn_KRB5_header_found=yes
- AC_DEFINE([HAVE_ET_COM_ERR_H], [1],
- [Define if you have the <et/com_err.h> header file.])],
- [inn_KRB5_header_found=no])])
- AS_IF([test x"$inn_KRB5_incroot" = x],
- [AC_CHECK_HEADERS([kerberosv5/com_err.h],
- [inn_KRB5_header_found=yes],
- [inn_KRB5_header_found=no])],
- [AS_IF([test -f "${inn_KRB5_incroot}/kerberosv5/com_err.h"],
- [inn_KRB5_header_found=yes
- AC_DEFINE([HAVE_KERBEROSV5_COM_ERR_H], [1],
- [Define if you have the <kerberosv5/com_err.h> header file.])],
- [inn_KRB5_header_found=no])])
- AS_IF([test x"$inn_KRB5_incroot" = x],
- [AC_CHECK_HEADERS([com_err.h],
- [inn_KRB5_header_found=yes],
- [inn_KRB5_header_found=no])],
- [AS_IF([test -f "${inn_KRB5_incroot}/com_err.h"],
- [inn_KRB5_header_found=yes
- AC_DEFINE([HAVE_COM_ERR_H], [1],
- [Define if you have the <com_err.h> header file.])],
- [inn_KRB5_header_found=no])])
- AS_IF([test x"${inn_KRB5_header_found}" = xyes],
- [KRB5_AUTH=auth_krb5],
- [AS_IF([test x"$with_krb5" = x],
- [KRB5_CPPFLAGS=
- KRB5_LDFLAGS=
- KRB5_LIBS=],
- [AC_MSG_ERROR([cannot find usable com_err header])])])])
+dnl that program.
+AS_IF([test x"$inn_use_KRB5" = xtrue], [KRB5_AUTH=auth_krb5])
AC_SUBST([KRB5_AUTH])
dnl If Berkeley DB is found, check the presence of its header and whether the
More information about the inn-committers
mailing list