1 /* 2 * Interface to PAM option parsing. 3 * 4 * This interface defines a lot of macros and types with very short names, and 5 * hence without a lot of namespace protection. It should be included only in 6 * the file that's doing the option parsing and not elsewhere to remove the 7 * risk of clashes. 8 * 9 * The canonical version of this file is maintained in the rra-c-util package, 10 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>. 11 * 12 * Written by Russ Allbery <eagle@eyrie.org> 13 * Copyright 2020 Russ Allbery <eagle@eyrie.org> 14 * Copyright 2010-2011, 2013 15 * The Board of Trustees of the Leland Stanford Junior University 16 * 17 * Permission is hereby granted, free of charge, to any person obtaining a 18 * copy of this software and associated documentation files (the "Software"), 19 * to deal in the Software without restriction, including without limitation 20 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 21 * and/or sell copies of the Software, and to permit persons to whom the 22 * Software is furnished to do so, subject to the following conditions: 23 * 24 * The above copyright notice and this permission notice shall be included in 25 * all copies or substantial portions of the Software. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 33 * DEALINGS IN THE SOFTWARE. 34 * 35 * SPDX-License-Identifier: MIT 36 */ 37 38 #ifndef PAM_UTIL_OPTIONS_H 39 #define PAM_UTIL_OPTIONS_H 1 40 41 #include <config.h> 42 #ifdef HAVE_KRB5 43 # include <portable/krb5.h> 44 #endif 45 #include <portable/macros.h> 46 #include <portable/stdbool.h> 47 48 #include <stddef.h> 49 50 /* Forward declarations to avoid additional includes. */ 51 struct vector; 52 53 /* 54 * The types of configuration values possible. STRLIST is a list data type 55 * that takes its default from a string value instead of a vector. For 56 * STRLIST, the default string value will be turned into a vector by splitting 57 * on comma, space, and tab. (This is the same as would be done with the 58 * value of a PAM setting when the target variable type is a list.) 59 */ 60 enum type 61 { 62 TYPE_BOOLEAN, 63 TYPE_NUMBER, 64 TYPE_TIME, 65 TYPE_STRING, 66 TYPE_LIST, 67 TYPE_STRLIST 68 }; 69 70 /* 71 * Each configuration option is defined by a struct option. This specifies 72 * the name of the option, its offset into the configuration struct, whether 73 * it can be specified in a krb5.conf file, its type, and its default value if 74 * not set. Note that PAM configuration options are specified as strings, so 75 * there's no native way of representing a list argument. List values are 76 * always initialized by splitting a string on whitespace or commas. 77 * 78 * The default value should really be a union, but you can't initialize unions 79 * properly in C in a static initializer without C99 named initializer 80 * support, which we can't (yet) assume. So use a struct instead, and 81 * initialize all the members, even though we'll only care about one of them. 82 * 83 * Note that numbers set in the configuration struct created by this interface 84 * must be longs, not ints. There is currently no provision for unsigned 85 * numbers. 86 * 87 * Times take their default from defaults.number. The difference between time 88 * and number is in the parsing of a user-supplied value and the type of the 89 * stored attribute. 90 */ 91 struct option { 92 const char *name; 93 size_t location; 94 bool krb5_config; 95 enum type type; 96 struct { 97 bool boolean; 98 long number; 99 const char *string; 100 const struct vector *list; 101 } defaults; 102 }; 103 104 /* 105 * The following macros are helpers to make it easier to define the table that 106 * specifies how to convert the configuration into a struct. They provide an 107 * initializer for the type and default fields. 108 */ 109 /* clang-format off */ 110 #define BOOL(def) TYPE_BOOLEAN, { (def), 0, NULL, NULL } 111 #define NUMBER(def) TYPE_NUMBER, { 0, (def), NULL, NULL } 112 #define TIME(def) TYPE_TIME, { 0, (def), NULL, NULL } 113 #define STRING(def) TYPE_STRING, { 0, 0, (def), NULL } 114 #define LIST(def) TYPE_LIST, { 0, 0, NULL, (def) } 115 #define STRLIST(def) TYPE_STRLIST, { 0, 0, (def), NULL } 116 /* clang-format on */ 117 118 /* 119 * The user of this file should also define a macro of the following form: 120 * 121 * #define K(name) (#name), offsetof(struct pam_config, name) 122 * 123 * Then, the definition of the necessary table for building the configuration 124 * will look something like this: 125 * 126 * const struct option options[] = { 127 * { K(aklog_homedir), true, BOOL (false) }, 128 * { K(cells), true, LIST (NULL) }, 129 * { K(debug), false, BOOL (false) }, 130 * { K(minimum_uid), true, NUMBER (0) }, 131 * { K(program), true, STRING (NULL) }, 132 * }; 133 * 134 * which provides a nice, succinct syntax for creating the table. The options 135 * MUST be in sorted order, since the options parsing code does a binary 136 * search. 137 */ 138 139 BEGIN_DECLS 140 141 /* Default to a hidden visibility for all internal functions. */ 142 #pragma GCC visibility push(hidden) 143 144 /* 145 * Set the defaults for the PAM configuration. Takes the PAM arguments, an 146 * option table defined as above, and the number of entries in the table. The 147 * config member of the args struct must already be allocated. Returns true 148 * on success and false on error (generally out of memory). Errors will 149 * already be reported using putil_crit(). 150 * 151 * This function must be called before either putil_args_krb5() or 152 * putil_args_parse(), since neither of those functions set defaults. 153 */ 154 bool putil_args_defaults(struct pam_args *, const struct option options[], 155 size_t optlen) __attribute__((__nonnull__)); 156 157 /* 158 * Fill out options from krb5.conf. Takes the PAM args structure, the name of 159 * the section for the software being configured, an option table defined as 160 * above, and the number of entries in the table. The config member of the 161 * args struct must already be allocated. Only those options whose 162 * krb5_config attribute is true will be considered. 163 * 164 * This code automatically checks for configuration settings scoped to the 165 * local realm, so the default realm should be set before calling this 166 * function. If that's done based on a configuration option, one may need to 167 * pre-parse the configuration options. 168 * 169 * Returns true on success and false on an error. An error return should be 170 * considered fatal. Errors will already be reported using putil_crit*() or 171 * putil_err*() as appropriate. If Kerberos is not available, returns without 172 * doing anything. 173 * 174 * putil_args_defaults() should be called before this function. 175 */ 176 bool putil_args_krb5(struct pam_args *, const char *section, 177 const struct option options[], size_t optlen) 178 __attribute__((__nonnull__)); 179 180 /* 181 * Parse the PAM arguments and fill out the provided struct. Takes the PAM 182 * arguments, the argument count and vector, an option table defined as above, 183 * and the number of entries in the table. The config member of the args 184 * struct must already be allocated. Returns true on success and false on 185 * error. An error return should be considered fatal. Errors will already be 186 * reported using putil_crit(). Unknown options will also be diagnosed (to 187 * syslog at LOG_ERR using putil_err()), but are not considered fatal errors 188 * and will still return true. 189 * 190 * The krb5_config option of the option configuration is ignored by this 191 * function. If options should be retrieved from krb5.conf, call 192 * putil_args_krb5() first, before calling this function. 193 * 194 * putil_args_defaults() should be called before this function. 195 */ 196 bool putil_args_parse(struct pam_args *, int argc, const char *argv[], 197 const struct option options[], size_t optlen) 198 __attribute__((__nonnull__)); 199 200 /* Undo default visibility change. */ 201 #pragma GCC visibility pop 202 203 END_DECLS 204 205 #endif /* !PAM_UTIL_OPTIONS_H */ 206