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