From 24f0b4ca2d565cdbb4fe7839ff28320706bf2386 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Wed, 16 Apr 2025 19:13:41 -0700 Subject: pam-krb5: Import/add pam-krb5 from eyeire.org From https://www.eyrie.org/~eagle/software/pam-krb5/: pam-krb5 provides a Kerberos PAM module that supports authentication, user ticket cache handling, simple authorization (via .k5login or checking Kerberos principals against local usernames), and password changing. It can be configured through either options in the PAM configuration itself or through entries in the system krb5.conf file, and it tries to work around PAM implementation flaws in commonly-used PAM-enabled applications such as OpenSSH and xdm. It supports both PKINIT and FAST to the extent that the underlying Kerberos libraries support these features. The reason for this import is to provide an MIT KRB5 compatible pam_krb5 PAM module. The existing pam_krb5 in FreeBS only works with Heimdal. Sponsored by: The FreeBSD Foundation --- pam-util/options.h | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 pam-util/options.h (limited to 'pam-util/options.h') diff --git a/pam-util/options.h b/pam-util/options.h new file mode 100644 index 000000000000..062d095e8e7e --- /dev/null +++ b/pam-util/options.h @@ -0,0 +1,205 @@ +/* + * Interface to PAM option parsing. + * + * This interface defines a lot of macros and types with very short names, and + * hence without a lot of namespace protection. It should be included only in + * the file that's doing the option parsing and not elsewhere to remove the + * risk of clashes. + * + * The canonical version of this file is maintained in the rra-c-util package, + * which can be found at . + * + * Written by Russ Allbery + * Copyright 2020 Russ Allbery + * Copyright 2010-2011, 2013 + * The Board of Trustees of the Leland Stanford Junior University + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef PAM_UTIL_OPTIONS_H +#define PAM_UTIL_OPTIONS_H 1 + +#include +#ifdef HAVE_KRB5 +# include +#endif +#include +#include + +#include + +/* Forward declarations to avoid additional includes. */ +struct vector; + +/* + * The types of configuration values possible. STRLIST is a list data type + * that takes its default from a string value instead of a vector. For + * STRLIST, the default string value will be turned into a vector by splitting + * on comma, space, and tab. (This is the same as would be done with the + * value of a PAM setting when the target variable type is a list.) + */ +enum type +{ + TYPE_BOOLEAN, + TYPE_NUMBER, + TYPE_TIME, + TYPE_STRING, + TYPE_LIST, + TYPE_STRLIST +}; + +/* + * Each configuration option is defined by a struct option. This specifies + * the name of the option, its offset into the configuration struct, whether + * it can be specified in a krb5.conf file, its type, and its default value if + * not set. Note that PAM configuration options are specified as strings, so + * there's no native way of representing a list argument. List values are + * always initialized by splitting a string on whitespace or commas. + * + * The default value should really be a union, but you can't initialize unions + * properly in C in a static initializer without C99 named initializer + * support, which we can't (yet) assume. So use a struct instead, and + * initialize all the members, even though we'll only care about one of them. + * + * Note that numbers set in the configuration struct created by this interface + * must be longs, not ints. There is currently no provision for unsigned + * numbers. + * + * Times take their default from defaults.number. The difference between time + * and number is in the parsing of a user-supplied value and the type of the + * stored attribute. + */ +struct option { + const char *name; + size_t location; + bool krb5_config; + enum type type; + struct { + bool boolean; + long number; + const char *string; + const struct vector *list; + } defaults; +}; + +/* + * The following macros are helpers to make it easier to define the table that + * specifies how to convert the configuration into a struct. They provide an + * initializer for the type and default fields. + */ +/* clang-format off */ +#define BOOL(def) TYPE_BOOLEAN, { (def), 0, NULL, NULL } +#define NUMBER(def) TYPE_NUMBER, { 0, (def), NULL, NULL } +#define TIME(def) TYPE_TIME, { 0, (def), NULL, NULL } +#define STRING(def) TYPE_STRING, { 0, 0, (def), NULL } +#define LIST(def) TYPE_LIST, { 0, 0, NULL, (def) } +#define STRLIST(def) TYPE_STRLIST, { 0, 0, (def), NULL } +/* clang-format on */ + +/* + * The user of this file should also define a macro of the following form: + * + * #define K(name) (#name), offsetof(struct pam_config, name) + * + * Then, the definition of the necessary table for building the configuration + * will look something like this: + * + * const struct option options[] = { + * { K(aklog_homedir), true, BOOL (false) }, + * { K(cells), true, LIST (NULL) }, + * { K(debug), false, BOOL (false) }, + * { K(minimum_uid), true, NUMBER (0) }, + * { K(program), true, STRING (NULL) }, + * }; + * + * which provides a nice, succinct syntax for creating the table. The options + * MUST be in sorted order, since the options parsing code does a binary + * search. + */ + +BEGIN_DECLS + +/* Default to a hidden visibility for all internal functions. */ +#pragma GCC visibility push(hidden) + +/* + * Set the defaults for the PAM configuration. Takes the PAM arguments, an + * option table defined as above, and the number of entries in the table. The + * config member of the args struct must already be allocated. Returns true + * on success and false on error (generally out of memory). Errors will + * already be reported using putil_crit(). + * + * This function must be called before either putil_args_krb5() or + * putil_args_parse(), since neither of those functions set defaults. + */ +bool putil_args_defaults(struct pam_args *, const struct option options[], + size_t optlen) __attribute__((__nonnull__)); + +/* + * Fill out options from krb5.conf. Takes the PAM args structure, the name of + * the section for the software being configured, an option table defined as + * above, and the number of entries in the table. The config member of the + * args struct must already be allocated. Only those options whose + * krb5_config attribute is true will be considered. + * + * This code automatically checks for configuration settings scoped to the + * local realm, so the default realm should be set before calling this + * function. If that's done based on a configuration option, one may need to + * pre-parse the configuration options. + * + * Returns true on success and false on an error. An error return should be + * considered fatal. Errors will already be reported using putil_crit*() or + * putil_err*() as appropriate. If Kerberos is not available, returns without + * doing anything. + * + * putil_args_defaults() should be called before this function. + */ +bool putil_args_krb5(struct pam_args *, const char *section, + const struct option options[], size_t optlen) + __attribute__((__nonnull__)); + +/* + * Parse the PAM arguments and fill out the provided struct. Takes the PAM + * arguments, the argument count and vector, an option table defined as above, + * and the number of entries in the table. The config member of the args + * struct must already be allocated. Returns true on success and false on + * error. An error return should be considered fatal. Errors will already be + * reported using putil_crit(). Unknown options will also be diagnosed (to + * syslog at LOG_ERR using putil_err()), but are not considered fatal errors + * and will still return true. + * + * The krb5_config option of the option configuration is ignored by this + * function. If options should be retrieved from krb5.conf, call + * putil_args_krb5() first, before calling this function. + * + * putil_args_defaults() should be called before this function. + */ +bool putil_args_parse(struct pam_args *, int argc, const char *argv[], + const struct option options[], size_t optlen) + __attribute__((__nonnull__)); + +/* Undo default visibility change. */ +#pragma GCC visibility pop + +END_DECLS + +#endif /* !PAM_UTIL_OPTIONS_H */ -- cgit v1.2.3