INN commit: branches/2.6 (4 files)

INN Commit rra at isc.org
Sat Mar 10 14:59:28 UTC 2018


    Date: Saturday, March 10, 2018 @ 06:59:27
  Author: iulius
Revision: 10266

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.

Also, if --with-krb5 (or the equivalent for other probes) is given and a
krb5-config was found at the install root, skip the PATH search for
krb5-config to avoid confusing output.  This results in redoing the
probe and using cached output when testing multiple krb5-config
features, but that seems better than the confusing output.

Patch from Russ Allbery.

Modified:
  branches/2.6/authprogs/auth_krb5.c
  branches/2.6/configure.ac
  branches/2.6/lib/Makefile
  branches/2.6/m4/krb5-config.m4

-----------------------+
 authprogs/auth_krb5.c |  139 ++++++++++++++++++++++++++++++++++++++++--------
 configure.ac          |   14 ----
 lib/Makefile          |    7 +-
 m4/krb5-config.m4     |    8 +-
 4 files changed, 126 insertions(+), 42 deletions(-)

Modified: authprogs/auth_krb5.c
===================================================================
--- authprogs/auth_krb5.c	2018-03-10 14:53:01 UTC (rev 10265)
+++ authprogs/auth_krb5.c	2018-03-10 14:59:27 UTC (rev 10266)
@@ -1,13 +1,13 @@
 /*  $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
-**  TGT.  With the -i <instance> command line option, appends /<instance> to
+**  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.
 **
 **  Special thanks to Von Welch <vwelch at vwelch.com> for giving me the initial
@@ -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, 4)))
+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-03-10 14:53:01 UTC (rev 10265)
+++ configure.ac	2018-03-10 14:59:27 UTC (rev 10266)
@@ -394,18 +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],
-    [AC_CHECK_HEADERS([et/com_err.h], [KRB5_AUTH=auth_krb5],
-         [AC_CHECK_HEADERS([kerberosv5/com_err.h], [KRB5_AUTH=auth_krb5],
-              [AC_CHECK_HEADERS([com_err.h], [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

Modified: lib/Makefile
===================================================================
--- lib/Makefile	2018-03-10 14:53:01 UTC (rev 10265)
+++ lib/Makefile	2018-03-10 14:59:27 UTC (rev 10266)
@@ -225,9 +225,10 @@
   ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \
   ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \
   ../include/config.h ../include/inn/macros.h \
-  ../include/portable/stdbool.h ../include/inn/libinn.h \
-  ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h \
-  ../include/inn/paths.h
+  ../include/portable/stdbool.h ../include/portable/socket.h \
+  ../include/portable/macros.h ../include/portable/getaddrinfo.h \
+  ../include/portable/getnameinfo.h ../include/inn/libinn.h \
+  ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h
 getmodaddr.o: getmodaddr.c ../include/config.h ../include/inn/defines.h \
   ../include/inn/system.h ../include/inn/macros.h \
   ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \

Modified: m4/krb5-config.m4
===================================================================
--- m4/krb5-config.m4	2018-03-10 14:53:01 UTC (rev 10265)
+++ m4/krb5-config.m4	2018-03-10 14:59:27 UTC (rev 10266)
@@ -12,7 +12,7 @@
 dnl package, available at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
 dnl Written by Russ Allbery <eagle at eyrie.org>
-dnl Copyright 2011-2012
+dnl Copyright 2011-2012, 2018
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
 dnl This file is free software; the authors give unlimited permission to copy
@@ -78,12 +78,12 @@
 dnl krb5-config didn't take an argument to specify the library type, but
 dnl always returned the flags for libkrb5.
 AC_DEFUN([INN_KRB5_CONFIG],
-[AC_REQUIRE([_INN_KRB5_CONFIG_PATH])
- inn_krb5_config_$3=
+[inn_krb5_config_$3=
  inn_krb5_config_$3[]_ok=
  AS_IF([test x"$1" != x && test -x "$1/bin/krb5-config"],
     [inn_krb5_config_$3="$1/bin/krb5-config"],
-    [inn_krb5_config_$3="$PATH_KRB5_CONFIG"])
+    [_INN_KRB5_CONFIG_PATH
+     inn_krb5_config_$3="$PATH_KRB5_CONFIG"])
  AS_IF([test x"$inn_krb5_config_$3" != x && test -x "$inn_krb5_config_$3"],
     [AC_CACHE_CHECK([for $2 support in krb5-config], [inn_cv_lib_$3[]_config],
          [AS_IF(["$inn_krb5_config_$3" 2>&1 | grep $2 >/dev/null 2>&1],



More information about the inn-committers mailing list