xref: /freebsd/contrib/pam-krb5/pam-util/options.h (revision bf6873c5786e333d679a7838d28812febf479a8a)
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