bin_PROGRAMS = commands/k5start commands/krenew
commands_k5start_SOURCES = commands/framework.c commands/internal.h \
commands/k5start.c
-commands_k5start_LDFLAGS = $(KRB5_LDFLAGS) $(KAFS_LDFLAGS)
+commands_k5start_CPPFLAGS = $(LIBKEYUTILS_CPPFLAGS) $(AM_CPPFLAGS)
+commands_k5start_LDFLAGS = $(KRB5_LDFLAGS) $(KAFS_LDFLAGS) \
+ $(LIBKEYUTILS_LDFLAGS)
commands_k5start_LDADD = $(LIBKAFS) util/libutil.a portable/libportable.a \
- $(K5START_LIBS)
+ $(K5START_LIBS) $(LIBKEYUTILS_LIBS)
commands_krenew_SOURCES = commands/framework.c commands/internal.h \
commands/krenew.c
-commands_krenew_LDFLAGS = $(KRB5_LDFLAGS) $(KAFS_LDFLAGS)
+commands_krenew_CPPFLAGS = $(LIBKEYUTILS_CPPFLAGS) $(AM_CPPFLAGS)
+commands_krenew_LDFLAGS = $(KRB5_LDFLAGS) $(KAFS_LDFLAGS) \
+ $(LIBKEYUTILS_LDFLAGS)
commands_krenew_LDADD = $(LIBKAFS) util/libutil.a portable/libportable.a \
- $(K5START_LIBS)
+ $(K5START_LIBS) $(LIBKEYUTILS_LIBS)
dist_man_MANS = docs/k5start.1 docs/krenew.1
DISTCLEANFILES = config.h.in~ tests/data/.placeholder
kstart 4.3 (unreleased)
+ Add support for kafs to the -t options of k5start and krenew. If AFS
+ setpag support is not compiled in or AFS is not available, but the
+ Linux kafs kernel module is available, do not error out when -t is
+ specified and continue to run the external program. If libkeyutils is
+ found at compile time and a command was specified on the command line,
+ create a new session keyring before running the external command to
+ isolate its AFS credentials from the calling process. Thanks to Bill
+ MacAllister, David Howells, and Jeffrey Altman for proposed code and
+ implementation discussion.
+
If the process run by k5start or krenew is killed by a signal, k5start
or krenew now exits with status 128 plus the killing signal rather
than zero. This avoids the caller of k5start or krenew thinking the
authentication when running a specific command and when aklog is being
run.
+ When using the Linux kafs module, the correct way to isolate kafs
+ credentials is to create a new session keyring rather than a new PAG.
+ This requires the libkeyutils library. configure will attempt to
+ discover that library automatically and link with it by default. Pass
+ the --with-libkeyutils, --with-libkeyutils-include, or
+ --with-libkeyutils-lib options to configure to specify a different path
+ to that library, or set the LIBKEYUTILS_* environment variables.
+
Normally, configure will use krb5-config to determine the flags to use
to compile with your Kerberos libraries. To specify a particular
krb5-config script to use, either set the PATH_KRB5_CONFIG environment
authentication when running a specific command and when aklog is being
run.
+When using the Linux kafs module, the correct way to isolate kafs
+credentials is to create a new session keyring rather than a new PAG.
+This requires the libkeyutils library. `configure` will attempt to
+discover that library automatically and link with it by default. Pass the
+`--with-libkeyutils`, `--with-libkeyutils-include`, or
+`--with-libkeyutils-lib` options to `configure` to specify a different
+path to that library, or set the `LIBKEYUTILS_*` environment variables.
+
Normally, configure will use `krb5-config` to determine the flags to use
to compile with your Kerberos libraries. To specify a particular
`krb5-config` script to use, either set the `PATH_KRB5_CONFIG` environment
#include <portable/system.h>
#include <errno.h>
+#ifdef HAVE_LIBKEYUTILS
+# include <keyutils.h>
+#endif
#include <signal.h>
+#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
}
+/*
+ * Probe to see if the Linux kafs subsystem is available.
+ */
+static bool
+has_kafs(void)
+{
+ struct stat st;
+ int rval, saved_errno;
+
+ saved_errno = errno;
+ rval = stat("/proc/fs/afs", &st);
+ errno = saved_errno;
+ return rval == 0;
+}
+
+
+/*
+ * Create a session keyring and link it to the user keyring. This is done
+ * when using kafs since running aklog will change the current session
+ * keyring, and we don't want to clobber the keyring of our caller because we
+ * may be using different credentials.
+ *
+ * If libkeyutils is not available, do nothing silently and the caller's
+ * keyring will get clobbered.
+ */
+#ifdef HAVE_LIBKEYUTILS
+static void
+create_keyring(krb5_context ctx, struct config *config)
+{
+ key_serial_t key;
+
+ key = keyctl_join_session_keyring(NULL);
+ if (key < 0) {
+ syswarn("cannot create new session keyring");
+ exit_cleanup(ctx, config, 1);
+ }
+ if (keyctl_link(KEY_SPEC_USER_KEYRING, key) < 0)
+ syswarn("cannot link session keyring to user keyring");
+}
+#else
+static void
+create_keyring(krb5_context ctx UNUSED, struct config *config UNUSED)
+{
+ return;
+}
+#endif
+
+
/*
* The primary entry point of the framework. Both k5start and krenew call
* this function after setting up the options and configuration to do the real
}
/*
- * If built with setpag support and we're running a command, create the
- * new PAG now before the first authentication.
+ * If built with setpag support, or if kafs is available, and we're
+ * running a command, create the new PAG now before the first
+ * authentication. This prevents us from clobbering our caller's AFS
+ * credentials.
*/
if (config->command != NULL && config->do_aklog) {
if (k_hasafs()) {
syswarn("unable to create PAG");
exit_cleanup(ctx, config, 1);
}
+ } else if (has_kafs()) {
+ create_keyring(ctx, config);
} else {
warn("cannot create PAG: AFS support is not available");
exit_cleanup(ctx, config, 1);
AM_MAINTAINER_MODE
dnl Detect unexpanded macros.
+m4_pattern_forbid([^PKG_])
m4_pattern_forbid([^_?RRA_])
AC_PROG_CC
[AS_IF([test x"$enableval" != xno], [RRA_LIB_KAFS])])
AM_CONDITIONAL([NEED_KAFS], [test x"$rra_build_kafs" = xtrue])
+dnl Check if libkeyutils is available, used for kafs support.
+RRA_LIB_KEYUTILS_OPTIONAL
+
dnl Other portability checks.
AC_HEADER_STDBOOL
AC_CHECK_HEADERS([strings.h sys/bitypes.h sys/select.h sys/time.h syslog.h])
When enabled, k5start and krenew will always create a new PAG before
authentication when running a specific command and when aklog is being
run.
+
+ When using the Linux kafs module, the correct way to isolate kafs
+ credentials is to create a new session keyring rather than a new PAG.
+ This requires the libkeyutils library. `configure` will attempt to
+ discover that library automatically and link with it by default. Pass the
+ `--with-libkeyutils`, `--with-libkeyutils-include`, or
+ `--with-libkeyutils-lib` options to `configure` to specify a different
+ path to that library, or set the `LIBKEYUTILS_*` environment variables.
reduced_depends: true
type: Autoconf
distribution:
-abFhLnPqstvx keytab username kinit LDAP aklog HUP ALRM KRB5CCNAME AFS PAG
init AKLOG kstart krenew afslog Bense Allbery Navid Golpayegani
forwardable proxiable designator Ctrl-C backoff FSFAP
-SPDX-License-Identifier
+SPDX-License-Identifier kafs keyring libkeyutils
=head1 NAME
=item B<-t>
-Run an external program after getting a ticket. The default use of this
-is to run B<aklog> to get a token. If the environment variable KINIT_PROG
-is set, it overrides the compiled-in default.
+Run an external program after getting a ticket. The intended use of this
+is to run B<aklog> to get a token. If the environment variable AKLOG (or
+KINIT_PROG for backward compatibility) is set, it overrides the
+compiled-in default.
-If B<k5start> has been built with AFS setpag() support and a command was
-given on the command line, B<k5start> will create a new PAG before
-obtaining AFS tokens. Otherwise, it will obtain tokens in the current
-PAG.
+If a command was given on the command line, B<k5start> will attempt to
+isolate the AFS credentials for that command from the invoking process.
+There are two possible ways in which this is done.
+
+First, if B<k5start> has been built with AFS setpag() support and AFS is
+available, B<k5start> will create a new PAG before running the external
+program.
+
+Otherwise, if either B<k5start> was not built with AFS setpag() support or
+AFS is not available, but the Linux kafs module is available and
+B<k5start> was built with libkeyutils support, it will create a new
+session keyring and link it to the current user keyring before running the
+external program.
+
+If neither of these conditions are true, B<k5start> will run the external
+program without doing any credential isolation, which may also affect the
+credentials of the invoking process.
=item B<-U>
=for stopwords
-abhiLstvx aklog AFS OpenSSH PAG HUP ALRM KRB5CCNAME AKLOG kstart afslog
Allbery Bense designator krenew Ctrl-C SIGHUP backoff FSFAP
-SPDX-License-Identifier
+SPDX-License-Identifier kafs keyring libkeyutils
=head1 NAME
=item B<-t>
-Run an external program after getting a ticket. The default use of this
-is to run B<aklog> to get a token. If the environment variable KINIT_PROG
-is set, it overrides the compiled-in default.
+Run an external program after getting a ticket. The intended use of this
+is to run B<aklog> to get a token. If the environment variable AKLOG (or
+KINIT_PROG for backward compatibility) is set, it overrides the
+compiled-in default.
-If B<krenew> has been built with AFS setpag() support and a command was
-given on the command line, B<krenew> will create a new PAG before
-obtaining AFS tokens. Otherwise, it will obtain tokens in the current
-PAG.
+If a command was given on the command line, B<krenew> will attempt to
+isolate the AFS credentials for that command from the invoking process.
+There are two possible ways in which this is done.
+
+First, if B<krenew> has been built with AFS setpag() support and AFS is
+available, B<krenew> will create a new PAG before running the external
+program.
+
+Otherwise, if either B<krenew> was not built with AFS setpag() support or
+AFS is not available, but the Linux kafs module is available and B<krenew>
+was built with libkeyutils support, it will create a new session keyring
+and link it to the current user keyring before running the external
+program.
+
+If neither of these conditions are true, B<krenew> will run the external
+program without doing any credential isolation, which may also affect the
+credentials of the invoking process.
=item B<-v>
--- /dev/null
+dnl Find the compiler and linker flags for libkeyutils.
+dnl
+dnl Finds the compiler and linker flags for linking with the libkeyutils
+dnl library. Provides the --with-libkeyutils, --with-libkeyutils-lib, and
+dnl --with-libkeyutils-include configure options to specify non-standard paths
+dnl to the libkeyutils libraries or header files.
+dnl
+dnl Provides the macros RRA_LIB_KEYUTILS and RRA_LIB_KEYUTILS_OPTIONAL and
+dnl sets the substitution variables LIBKEYUTILS_CPPFLAGS, LIBKEYUTILS_LDFLAGS,
+dnl and LIBKEYUTILS_LIBS. Also provides RRA_LIB_KEYUTILS_SWITCH to set
+dnl CPPFLAGS, LDFLAGS, and LIBS to include the libkeyutils libraries, saving
+dnl the current values first, and RRA_LIB_KEYUTILS_RESTORE to restore those
+dnl settings to before the last RRA_LIB_KEYUTILS_SWITCH. Defines
+dnl HAVE_LIBKEYUTILS if libkeyutils is found. If it isn't found, the
+dnl substitution variables will be empty.
+dnl
+dnl Depends on the lib-helper.m4 framework.
+dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
+dnl Copyright 2021 Russ Allbery <eagle@eyrie.org>
+dnl
+dnl This file is free software; the authors give unlimited permission to copy
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
+dnl
+dnl SPDX-License-Identifier: FSFULLR
+
+dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to
+dnl versions that include the libevent flags. Used as a wrapper, with
+dnl RRA_LIB_LIBEVENT_RESTORE, around tests.
+AC_DEFUN([RRA_LIB_KEYUTILS_SWITCH], [RRA_LIB_HELPER_SWITCH([LIBKEYUTILS])])
+
+dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values before
+dnl RRA_LIB_LIBEVENT_SWITCH was called.
+AC_DEFUN([RRA_LIB_KEYUTILS_RESTORE], [RRA_LIB_HELPER_RESTORE([LIBKEYUTILS])])
+
+dnl Checks if libkeyutils is present. The single argument, if "true", says to
+dnl fail if the libkeyutils library could not be found. Prefer probing with
+dnl pkg-config if available and the --with flags were not given.
+AC_DEFUN([_RRA_LIB_KEYUTILS_INTERNAL],
+[AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS])
+ RRA_LIB_HELPER_PATHS([LIBKEYUTILS])
+ AS_IF([test x"$LIBKEYUTILS_CPPFLAGS" = x && test x"$LIBKEYUTILS_LDFLAGS" = x],
+ [PKG_CHECK_EXISTS([libkeyutils],
+ [PKG_CHECK_MODULES([LIBKEYUTILS], [libkeyutils])
+ LIBKEYUTILS_CPPFLAGS="$LIBKEYUTILS_CFLAGS"])])
+ AS_IF([test x"$LIBKEYUTILS_LIBS" = x],
+ [RRA_LIB_KEYUTILS_SWITCH
+ LIBS=
+ AC_SEARCH_LIBS([keyctl_join_session_keyring], [keyutils],
+ [LIBKEYUTILS_LIBS="$LIBS"],
+ [AS_IF([test x"$1" = xtrue],
+ [AC_MSG_ERROR([cannot find usable libkeyutils library])])])
+ RRA_LIB_KEYUTILS_RESTORE])])
+
+dnl The main macro for packages with mandatory libkeyutils support.
+AC_DEFUN([RRA_LIB_KEYUTILS],
+[RRA_LIB_HELPER_VAR_INIT([LIBKEYUTILS])
+ RRA_LIB_HELPER_WITH([libkeyutils], [libkeyutils], [LIBKEYUTILS])
+ _RRA_LIB_KEYUTILS_INTERNAL([true])
+ rra_use_LIBKEYUTILS=true
+ AC_DEFINE([HAVE_LIBKEYUTILS], 1, [Define if libkeyutils is available.])])
+
+dnl The main macro for packages with optional libkeyutils support.
+AC_DEFUN([RRA_LIB_KEYUTILS_OPTIONAL],
+[RRA_LIB_HELPER_VAR_INIT([LIBKEYUTILS])
+ RRA_LIB_HELPER_WITH_OPTIONAL([libkeyutils], [libkeyutils], [LIBKEYUTILS])
+ AS_IF([test x"$rra_use_LIBKEYUTILS" != xfalse],
+ [AS_IF([test x"$rra_use_LIBKEYUTILS" = xtrue],
+ [_RRA_LIB_KEYUTILS_INTERNAL([true])],
+ [_RRA_LIB_KEYUTILS_INTERNAL([false])])])
+ AS_IF([test x"$LIBKEYUTILS_LIBS" != x],
+ [rra_use_LIBKEYUTILS=true
+ AC_DEFINE([HAVE_LIBKEYUTILS], 1, [Define if libkeyutils is available.])])])
--- /dev/null
+dnl Helper functions to manage compiler variables.
+dnl
+dnl These are a wide variety of helper macros to make it easier to construct
+dnl standard macros to probe for a library and to set library-specific
+dnl CPPFLAGS, LDFLAGS, and LIBS shell substitution variables. Most of them
+dnl take as one of the arguments the prefix string to use for variables, which
+dnl is usually something like "KRB5" or "GSSAPI".
+dnl
+dnl Depends on RRA_SET_LDFLAGS.
+dnl
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
+dnl Written by Russ Allbery <eagle@eyrie.org>
+dnl Copyright 2018 Russ Allbery <eagle@eyrie.org>
+dnl Copyright 2011, 2013
+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
+dnl and/or distribute it, with or without modifications, as long as this
+dnl notice is preserved.
+dnl
+dnl SPDX-License-Identifier: FSFULLR
+
+dnl Add the library flags to the default compiler flags and then remove them.
+dnl
+dnl To use these macros, pass the prefix string used for the variables as the
+dnl only argument. For example, to use these for a library with KRB5 as a
+dnl prefix, one would use:
+dnl
+dnl AC_DEFUN([RRA_LIB_KRB5_SWITCH], [RRA_LIB_HELPER_SWITCH([KRB5])])
+dnl AC_DEFUN([RRA_LIB_KRB5_RESTORE], [RRA_LIB_HELPER_RESTORE([KRB5])])
+dnl
+dnl Then, wrap checks for library features with RRA_LIB_KRB5_SWITCH and
+dnl RRA_LIB_KRB5_RESTORE.
+AC_DEFUN([RRA_LIB_HELPER_SWITCH],
+[rra_$1[]_save_CPPFLAGS="$CPPFLAGS"
+ rra_$1[]_save_LDFLAGS="$LDFLAGS"
+ rra_$1[]_save_LIBS="$LIBS"
+ CPPFLAGS="$$1[]_CPPFLAGS $CPPFLAGS"
+ LDFLAGS="$$1[]_LDFLAGS $LDFLAGS"
+ LIBS="$$1[]_LIBS $LIBS"])
+
+AC_DEFUN([RRA_LIB_HELPER_RESTORE],
+[CPPFLAGS="$rra_$1[]_save_CPPFLAGS"
+ LDFLAGS="$rra_$1[]_save_LDFLAGS"
+ LIBS="$rra_$1[]_save_LIBS"])
+
+dnl Given _root, _libdir, and _includedir variables set for a library (set by
+dnl RRA_LIB_HELPER_WITH*), set the LDFLAGS and CPPFLAGS variables for that
+dnl library accordingly. Takes the variable prefix as the only argument.
+AC_DEFUN([RRA_LIB_HELPER_PATHS],
+[AS_IF([test x"$rra_$1[]_libdir" != x],
+ [$1[]_LDFLAGS="-L$rra_$1[]_libdir"],
+ [AS_IF([test x"$rra_$1[]_root" != x],
+ [RRA_SET_LDFLAGS([$1][_LDFLAGS], [${rra_$1[]_root}])])])
+ AS_IF([test x"$rra_$1[]_includedir" != x],
+ [$1[]_CPPFLAGS="-I$rra_$1[]_includedir"],
+ [AS_IF([test x"$rra_$1[]_root" != x],
+ [AS_IF([test x"$rra_$1[]_root" != x/usr],
+ [$1[]_CPPFLAGS="-I${rra_$1[]_root}/include"])])])])
+
+dnl Check whether a library works. This is used as a sanity check on the
+dnl results of *-config shell scripts. Takes four arguments; the first, if
+dnl "true", says that a working library is mandatory and errors out if it
+dnl doesn't. The second is the variable prefix. The third is a function to
+dnl look for that should be in the libraries. The fourth is the
+dnl human-readable name of the library for error messages.
+AC_DEFUN([RRA_LIB_HELPER_CHECK],
+[RRA_LIB_HELPER_SWITCH([$2])
+ AC_CHECK_FUNC([$3], [],
+ [AS_IF([test x"$1" = xtrue],
+ [AC_MSG_FAILURE([unable to link with $4 library])])
+ $2[]_CPPFLAGS=
+ $2[]_LDFLAGS=
+ $2[]_LIBS=])
+ RRA_LIB_HELPER_RESTORE([$2])])
+
+dnl Initialize the variables used by a library probe and set the appropriate
+dnl ones as substitution variables. Takes the library variable prefix as its
+dnl only argument.
+AC_DEFUN([RRA_LIB_HELPER_VAR_INIT],
+[rra_$1[]_root=
+ rra_$1[]_libdir=
+ rra_$1[]_includedir=
+ rra_use_$1=
+ $1[]_CPPFLAGS=
+ $1[]_LDFLAGS=
+ $1[]_LIBS=
+ AC_SUBST([$1][_CPPFLAGS])
+ AC_SUBST([$1][_LDFLAGS])
+ AC_SUBST([$1][_LIBS])])
+
+dnl Unset all of the variables used by a library probe. Used with the
+dnl _OPTIONAL versions of header probes when a header or library wasn't found
+dnl and therefore the library isn't usable.
+AC_DEFUN([RRA_LIB_HELPER_VAR_CLEAR],
+[$1[]_CPPFLAGS=
+ $1[]_LDFLAGS=
+ $1[]_LIBS=])
+
+dnl Handles --with options for a non-optional library. First argument is the
+dnl base for the switch names. Second argument is the short description.
+dnl Third argument is the variable prefix. The variables set are used by
+dnl RRA_LIB_HELPER_PATHS.
+AC_DEFUN([RRA_LIB_HELPER_WITH],
+[AC_ARG_WITH([$1],
+ [AS_HELP_STRING([--with-][$1][=DIR],
+ [Location of $2 headers and libraries])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_$3[]_root="$withval"])])
+ AC_ARG_WITH([$1][-include],
+ [AS_HELP_STRING([--with-][$1][-include=DIR],
+ [Location of $2 headers])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_$3[]_includedir="$withval"])])
+ AC_ARG_WITH([$1][-lib],
+ [AS_HELP_STRING([--with-][$1][-lib=DIR],
+ [Location of $2 libraries])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_$3[]_libdir="$withval"])])])
+
+dnl Handles --with options for an optional library, so --with-<library> can
+dnl cause the checks to be skipped entirely or become mandatory. Sets an
+dnl rra_use_PREFIX variable to true or false if the library is explicitly
+dnl enabled or disabled.
+dnl
+dnl First argument is the base for the switch names. Second argument is the
+dnl short description. Third argument is the variable prefix.
+dnl
+dnl The variables set are used by RRA_LIB_HELPER_PATHS.
+AC_DEFUN([RRA_LIB_HELPER_WITH_OPTIONAL],
+[AC_ARG_WITH([$1],
+ [AS_HELP_STRING([--with-][$1][@<:@=DIR@:>@],
+ [Location of $2 headers and libraries])],
+ [AS_IF([test x"$withval" = xno],
+ [rra_use_$3=false],
+ [AS_IF([test x"$withval" != xyes], [rra_$3[]_root="$withval"])
+ rra_use_$3=true])])
+ AC_ARG_WITH([$1][-include],
+ [AS_HELP_STRING([--with-][$1][-include=DIR],
+ [Location of $2 headers])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_$3[]_includedir="$withval"])])
+ AC_ARG_WITH([$1][-lib],
+ [AS_HELP_STRING([--with-][$1][-lib=DIR],
+ [Location of $2 libraries])],
+ [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
+ [rra_$3[]_libdir="$withval"])])])