xref: /freebsd/contrib/pam-krb5/tests/pam-util/options-t.c (revision bf6873c5786e333d679a7838d28812febf479a8a)
1*bf6873c5SCy Schubert /*
2*bf6873c5SCy Schubert  * PAM option parsing test suite.
3*bf6873c5SCy Schubert  *
4*bf6873c5SCy Schubert  * The canonical version of this file is maintained in the rra-c-util package,
5*bf6873c5SCy Schubert  * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
6*bf6873c5SCy Schubert  *
7*bf6873c5SCy Schubert  * Written by Russ Allbery <eagle@eyrie.org>
8*bf6873c5SCy Schubert  * Copyright 2020 Russ Allbery <eagle@eyrie.org>
9*bf6873c5SCy Schubert  * Copyright 2010-2014
10*bf6873c5SCy Schubert  *     The Board of Trustees of the Leland Stanford Junior University
11*bf6873c5SCy Schubert  *
12*bf6873c5SCy Schubert  * Permission is hereby granted, free of charge, to any person obtaining a
13*bf6873c5SCy Schubert  * copy of this software and associated documentation files (the "Software"),
14*bf6873c5SCy Schubert  * to deal in the Software without restriction, including without limitation
15*bf6873c5SCy Schubert  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16*bf6873c5SCy Schubert  * and/or sell copies of the Software, and to permit persons to whom the
17*bf6873c5SCy Schubert  * Software is furnished to do so, subject to the following conditions:
18*bf6873c5SCy Schubert  *
19*bf6873c5SCy Schubert  * The above copyright notice and this permission notice shall be included in
20*bf6873c5SCy Schubert  * all copies or substantial portions of the Software.
21*bf6873c5SCy Schubert  *
22*bf6873c5SCy Schubert  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23*bf6873c5SCy Schubert  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24*bf6873c5SCy Schubert  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25*bf6873c5SCy Schubert  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26*bf6873c5SCy Schubert  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27*bf6873c5SCy Schubert  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28*bf6873c5SCy Schubert  * DEALINGS IN THE SOFTWARE.
29*bf6873c5SCy Schubert  *
30*bf6873c5SCy Schubert  * SPDX-License-Identifier: MIT
31*bf6873c5SCy Schubert  */
32*bf6873c5SCy Schubert 
33*bf6873c5SCy Schubert #include <config.h>
34*bf6873c5SCy Schubert #include <portable/pam.h>
35*bf6873c5SCy Schubert #include <portable/system.h>
36*bf6873c5SCy Schubert 
37*bf6873c5SCy Schubert #include <syslog.h>
38*bf6873c5SCy Schubert 
39*bf6873c5SCy Schubert #include <pam-util/args.h>
40*bf6873c5SCy Schubert #include <pam-util/options.h>
41*bf6873c5SCy Schubert #include <pam-util/vector.h>
42*bf6873c5SCy Schubert #include <tests/fakepam/pam.h>
43*bf6873c5SCy Schubert #include <tests/tap/basic.h>
44*bf6873c5SCy Schubert #include <tests/tap/string.h>
45*bf6873c5SCy Schubert 
46*bf6873c5SCy Schubert /* The configuration struct we will use for testing. */
47*bf6873c5SCy Schubert struct pam_config {
48*bf6873c5SCy Schubert     struct vector *cells;
49*bf6873c5SCy Schubert     bool debug;
50*bf6873c5SCy Schubert #ifdef HAVE_KRB5
51*bf6873c5SCy Schubert     krb5_deltat expires;
52*bf6873c5SCy Schubert #else
53*bf6873c5SCy Schubert     long expires;
54*bf6873c5SCy Schubert #endif
55*bf6873c5SCy Schubert     bool ignore_root;
56*bf6873c5SCy Schubert     long minimum_uid;
57*bf6873c5SCy Schubert     char *program;
58*bf6873c5SCy Schubert };
59*bf6873c5SCy Schubert 
60*bf6873c5SCy Schubert #define K(name) (#name), offsetof(struct pam_config, name)
61*bf6873c5SCy Schubert 
62*bf6873c5SCy Schubert /* The rules specifying the configuration options. */
63*bf6873c5SCy Schubert static struct option options[] = {
64*bf6873c5SCy Schubert     /* clang-format off */
65*bf6873c5SCy Schubert     { K(cells),       true,  LIST   (NULL)  },
66*bf6873c5SCy Schubert     { K(debug),       true,  BOOL   (false) },
67*bf6873c5SCy Schubert     { K(expires),     true,  TIME   (10)    },
68*bf6873c5SCy Schubert     { K(ignore_root), false, BOOL   (true)  },
69*bf6873c5SCy Schubert     { K(minimum_uid), true,  NUMBER (0)     },
70*bf6873c5SCy Schubert     { K(program),     true,  STRING (NULL)  },
71*bf6873c5SCy Schubert     /* clang-format on */
72*bf6873c5SCy Schubert };
73*bf6873c5SCy Schubert static const size_t optlen = sizeof(options) / sizeof(options[0]);
74*bf6873c5SCy Schubert 
75*bf6873c5SCy Schubert /*
76*bf6873c5SCy Schubert  * A macro used to parse the various ways of spelling booleans.  This reuses
77*bf6873c5SCy Schubert  * the argv_bool variable, setting it to the first value provided and then
78*bf6873c5SCy Schubert  * calling putil_args_parse() on it.  It then checks whether the provided
79*bf6873c5SCy Schubert  * config option is set to the expected value.
80*bf6873c5SCy Schubert  */
81*bf6873c5SCy Schubert #define TEST_BOOL(a, c, v)                                              \
82*bf6873c5SCy Schubert     do {                                                                \
83*bf6873c5SCy Schubert         argv_bool[0] = (a);                                             \
84*bf6873c5SCy Schubert         status = putil_args_parse(args, 1, argv_bool, options, optlen); \
85*bf6873c5SCy Schubert         ok(status, "Parse of %s", (a));                                 \
86*bf6873c5SCy Schubert         is_int((v), (c), "...and value is correct");                    \
87*bf6873c5SCy Schubert         ok(pam_output() == NULL, "...and no output");                   \
88*bf6873c5SCy Schubert     } while (0)
89*bf6873c5SCy Schubert 
90*bf6873c5SCy Schubert /*
91*bf6873c5SCy Schubert  * A macro used to test error reporting from putil_args_parse().  This reuses
92*bf6873c5SCy Schubert  * the argv_err variable, setting it to the first value provided and then
93*bf6873c5SCy Schubert  * calling putil_args_parse() on it.  It then recovers the error message and
94*bf6873c5SCy Schubert  * expects it to match the severity and error message given.
95*bf6873c5SCy Schubert  */
96*bf6873c5SCy Schubert #define TEST_ERROR(a, p, e)                                                  \
97*bf6873c5SCy Schubert     do {                                                                     \
98*bf6873c5SCy Schubert         argv_err[0] = (a);                                                   \
99*bf6873c5SCy Schubert         status = putil_args_parse(args, 1, argv_err, options, optlen);       \
100*bf6873c5SCy Schubert         ok(status, "Parse of %s", (a));                                      \
101*bf6873c5SCy Schubert         seen = pam_output();                                                 \
102*bf6873c5SCy Schubert         if (seen == NULL)                                                    \
103*bf6873c5SCy Schubert             ok_block(2, false, "...no error output");                        \
104*bf6873c5SCy Schubert         else {                                                               \
105*bf6873c5SCy Schubert             is_int((p), seen->lines[0].priority, "...priority for %s", (a)); \
106*bf6873c5SCy Schubert             is_string((e), seen->lines[0].line, "...error for %s", (a));     \
107*bf6873c5SCy Schubert         }                                                                    \
108*bf6873c5SCy Schubert         pam_output_free(seen);                                               \
109*bf6873c5SCy Schubert     } while (0)
110*bf6873c5SCy Schubert 
111*bf6873c5SCy Schubert 
112*bf6873c5SCy Schubert /*
113*bf6873c5SCy Schubert  * Allocate and initialize a new struct config.
114*bf6873c5SCy Schubert  */
115*bf6873c5SCy Schubert static struct pam_config *
config_new(void)116*bf6873c5SCy Schubert config_new(void)
117*bf6873c5SCy Schubert {
118*bf6873c5SCy Schubert     return bcalloc(1, sizeof(struct pam_config));
119*bf6873c5SCy Schubert }
120*bf6873c5SCy Schubert 
121*bf6873c5SCy Schubert 
122*bf6873c5SCy Schubert /*
123*bf6873c5SCy Schubert  * Free a struct config and all of its members.
124*bf6873c5SCy Schubert  */
125*bf6873c5SCy Schubert static void
config_free(struct pam_config * config)126*bf6873c5SCy Schubert config_free(struct pam_config *config)
127*bf6873c5SCy Schubert {
128*bf6873c5SCy Schubert     if (config == NULL)
129*bf6873c5SCy Schubert         return;
130*bf6873c5SCy Schubert     vector_free(config->cells);
131*bf6873c5SCy Schubert     free(config->program);
132*bf6873c5SCy Schubert     free(config);
133*bf6873c5SCy Schubert }
134*bf6873c5SCy Schubert 
135*bf6873c5SCy Schubert 
136*bf6873c5SCy Schubert int
main(void)137*bf6873c5SCy Schubert main(void)
138*bf6873c5SCy Schubert {
139*bf6873c5SCy Schubert     pam_handle_t *pamh;
140*bf6873c5SCy Schubert     struct pam_args *args;
141*bf6873c5SCy Schubert     struct pam_conv conv = {NULL, NULL};
142*bf6873c5SCy Schubert     bool status;
143*bf6873c5SCy Schubert     struct vector *cells;
144*bf6873c5SCy Schubert     char *program;
145*bf6873c5SCy Schubert     struct output *seen;
146*bf6873c5SCy Schubert     const char *argv_bool[2] = {NULL, NULL};
147*bf6873c5SCy Schubert     const char *argv_err[2] = {NULL, NULL};
148*bf6873c5SCy Schubert     const char *argv_empty[] = {NULL};
149*bf6873c5SCy Schubert #ifdef HAVE_KRB5
150*bf6873c5SCy Schubert     const char *argv_all[] = {"cells=stanford.edu,ir.stanford.edu",
151*bf6873c5SCy Schubert                               "debug",
152*bf6873c5SCy Schubert                               "expires=1d",
153*bf6873c5SCy Schubert                               "ignore_root",
154*bf6873c5SCy Schubert                               "minimum_uid=1000",
155*bf6873c5SCy Schubert                               "program=/bin/true"};
156*bf6873c5SCy Schubert     char *krb5conf;
157*bf6873c5SCy Schubert #else
158*bf6873c5SCy Schubert     const char *argv_all[] = {"cells=stanford.edu,ir.stanford.edu",
159*bf6873c5SCy Schubert                               "debug",
160*bf6873c5SCy Schubert                               "expires=86400",
161*bf6873c5SCy Schubert                               "ignore_root",
162*bf6873c5SCy Schubert                               "minimum_uid=1000",
163*bf6873c5SCy Schubert                               "program=/bin/true"};
164*bf6873c5SCy Schubert #endif
165*bf6873c5SCy Schubert 
166*bf6873c5SCy Schubert     if (pam_start("test", NULL, &conv, &pamh) != PAM_SUCCESS)
167*bf6873c5SCy Schubert         sysbail("cannot create pam_handle_t");
168*bf6873c5SCy Schubert     args = putil_args_new(pamh, 0);
169*bf6873c5SCy Schubert     if (args == NULL)
170*bf6873c5SCy Schubert         bail("cannot create PAM argument struct");
171*bf6873c5SCy Schubert 
172*bf6873c5SCy Schubert     plan(161);
173*bf6873c5SCy Schubert 
174*bf6873c5SCy Schubert     /* First, check just the defaults. */
175*bf6873c5SCy Schubert     args->config = config_new();
176*bf6873c5SCy Schubert     status = putil_args_defaults(args, options, optlen);
177*bf6873c5SCy Schubert     ok(status, "Setting the defaults");
178*bf6873c5SCy Schubert     ok(args->config->cells == NULL, "...cells default");
179*bf6873c5SCy Schubert     is_int(false, args->config->debug, "...debug default");
180*bf6873c5SCy Schubert     is_int(10, args->config->expires, "...expires default");
181*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root default");
182*bf6873c5SCy Schubert     is_int(0, args->config->minimum_uid, "...minimum_uid default");
183*bf6873c5SCy Schubert     ok(args->config->program == NULL, "...program default");
184*bf6873c5SCy Schubert 
185*bf6873c5SCy Schubert     /* Now parse an empty set of PAM arguments.  Nothing should change. */
186*bf6873c5SCy Schubert     status = putil_args_parse(args, 0, argv_empty, options, optlen);
187*bf6873c5SCy Schubert     ok(status, "Parse of empty argv");
188*bf6873c5SCy Schubert     ok(args->config->cells == NULL, "...cells still default");
189*bf6873c5SCy Schubert     is_int(false, args->config->debug, "...debug still default");
190*bf6873c5SCy Schubert     is_int(10, args->config->expires, "...expires default");
191*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root still default");
192*bf6873c5SCy Schubert     is_int(0, args->config->minimum_uid, "...minimum_uid still default");
193*bf6873c5SCy Schubert     ok(args->config->program == NULL, "...program still default");
194*bf6873c5SCy Schubert 
195*bf6873c5SCy Schubert     /* Now, check setting everything. */
196*bf6873c5SCy Schubert     status = putil_args_parse(args, 6, argv_all, options, optlen);
197*bf6873c5SCy Schubert     ok(status, "Parse of full argv");
198*bf6873c5SCy Schubert     if (args->config->cells == NULL)
199*bf6873c5SCy Schubert         ok_block(4, false, "...cells is set");
200*bf6873c5SCy Schubert     else {
201*bf6873c5SCy Schubert         ok(args->config->cells != NULL, "...cells is set");
202*bf6873c5SCy Schubert         is_int(2, args->config->cells->count, "...with two cells");
203*bf6873c5SCy Schubert         is_string("stanford.edu", args->config->cells->strings[0],
204*bf6873c5SCy Schubert                   "...first is stanford.edu");
205*bf6873c5SCy Schubert         is_string("ir.stanford.edu", args->config->cells->strings[1],
206*bf6873c5SCy Schubert                   "...second is ir.stanford.edu");
207*bf6873c5SCy Schubert     }
208*bf6873c5SCy Schubert     is_int(true, args->config->debug, "...debug is set");
209*bf6873c5SCy Schubert     is_int(86400, args->config->expires, "...expires is set");
210*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root is set");
211*bf6873c5SCy Schubert     is_int(1000, args->config->minimum_uid, "...minimum_uid is set");
212*bf6873c5SCy Schubert     is_string("/bin/true", args->config->program, "...program is set");
213*bf6873c5SCy Schubert     config_free(args->config);
214*bf6873c5SCy Schubert     args->config = NULL;
215*bf6873c5SCy Schubert 
216*bf6873c5SCy Schubert     /* Test deep copying of defaults. */
217*bf6873c5SCy Schubert     cells = vector_new();
218*bf6873c5SCy Schubert     if (cells == NULL)
219*bf6873c5SCy Schubert         sysbail("cannot allocate memory");
220*bf6873c5SCy Schubert     vector_add(cells, "foo.com");
221*bf6873c5SCy Schubert     vector_add(cells, "bar.com");
222*bf6873c5SCy Schubert     options[0].defaults.list = cells;
223*bf6873c5SCy Schubert     program = strdup("/bin/false");
224*bf6873c5SCy Schubert     if (program == NULL)
225*bf6873c5SCy Schubert         sysbail("cannot allocate memory");
226*bf6873c5SCy Schubert     options[5].defaults.string = program;
227*bf6873c5SCy Schubert     args->config = config_new();
228*bf6873c5SCy Schubert     status = putil_args_defaults(args, options, optlen);
229*bf6873c5SCy Schubert     ok(status, "Setting defaults with new defaults");
230*bf6873c5SCy Schubert     if (args->config->cells == NULL)
231*bf6873c5SCy Schubert         ok_block(4, false, "...cells is set");
232*bf6873c5SCy Schubert     else {
233*bf6873c5SCy Schubert         ok(args->config->cells != NULL, "...cells is set");
234*bf6873c5SCy Schubert         is_int(2, args->config->cells->count, "...with two cells");
235*bf6873c5SCy Schubert         is_string("foo.com", args->config->cells->strings[0],
236*bf6873c5SCy Schubert                   "...first is foo.com");
237*bf6873c5SCy Schubert         is_string("bar.com", args->config->cells->strings[1],
238*bf6873c5SCy Schubert                   "...second is bar.com");
239*bf6873c5SCy Schubert     }
240*bf6873c5SCy Schubert     is_string("/bin/false", args->config->program, "...program is /bin/false");
241*bf6873c5SCy Schubert     status = putil_args_parse(args, 6, argv_all, options, optlen);
242*bf6873c5SCy Schubert     ok(status, "Parse of full argv after defaults");
243*bf6873c5SCy Schubert     if (args->config->cells == NULL)
244*bf6873c5SCy Schubert         ok_block(4, false, "...cells is set");
245*bf6873c5SCy Schubert     else {
246*bf6873c5SCy Schubert         ok(args->config->cells != NULL, "...cells is set");
247*bf6873c5SCy Schubert         is_int(2, args->config->cells->count, "...with two cells");
248*bf6873c5SCy Schubert         is_string("stanford.edu", args->config->cells->strings[0],
249*bf6873c5SCy Schubert                   "...first is stanford.edu");
250*bf6873c5SCy Schubert         is_string("ir.stanford.edu", args->config->cells->strings[1],
251*bf6873c5SCy Schubert                   "...second is ir.stanford.edu");
252*bf6873c5SCy Schubert     }
253*bf6873c5SCy Schubert     is_int(true, args->config->debug, "...debug is set");
254*bf6873c5SCy Schubert     is_int(86400, args->config->expires, "...expires is set");
255*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root is set");
256*bf6873c5SCy Schubert     is_int(1000, args->config->minimum_uid, "...minimum_uid is set");
257*bf6873c5SCy Schubert     is_string("/bin/true", args->config->program, "...program is set");
258*bf6873c5SCy Schubert     is_string("foo.com", cells->strings[0], "...first cell after parse");
259*bf6873c5SCy Schubert     is_string("bar.com", cells->strings[1], "...second cell after parse");
260*bf6873c5SCy Schubert     is_string("/bin/false", program, "...string after parse");
261*bf6873c5SCy Schubert     config_free(args->config);
262*bf6873c5SCy Schubert     args->config = NULL;
263*bf6873c5SCy Schubert     is_string("foo.com", cells->strings[0], "...first cell after free");
264*bf6873c5SCy Schubert     is_string("bar.com", cells->strings[1], "...second cell after free");
265*bf6873c5SCy Schubert     is_string("/bin/false", program, "...string after free");
266*bf6873c5SCy Schubert     options[0].defaults.list = NULL;
267*bf6873c5SCy Schubert     options[5].defaults.string = NULL;
268*bf6873c5SCy Schubert     vector_free(cells);
269*bf6873c5SCy Schubert     free(program);
270*bf6873c5SCy Schubert 
271*bf6873c5SCy Schubert     /* Test specifying the default for a vector parameter as a string. */
272*bf6873c5SCy Schubert     options[0].type = TYPE_STRLIST;
273*bf6873c5SCy Schubert     options[0].defaults.string = "foo.com,bar.com";
274*bf6873c5SCy Schubert     args->config = config_new();
275*bf6873c5SCy Schubert     status = putil_args_defaults(args, options, optlen);
276*bf6873c5SCy Schubert     ok(status, "Setting defaults with string default for vector");
277*bf6873c5SCy Schubert     if (args->config->cells == NULL)
278*bf6873c5SCy Schubert         ok_block(4, false, "...cells is set");
279*bf6873c5SCy Schubert     else {
280*bf6873c5SCy Schubert         ok(args->config->cells != NULL, "...cells is set");
281*bf6873c5SCy Schubert         is_int(2, args->config->cells->count, "...with two cells");
282*bf6873c5SCy Schubert         is_string("foo.com", args->config->cells->strings[0],
283*bf6873c5SCy Schubert                   "...first is foo.com");
284*bf6873c5SCy Schubert         is_string("bar.com", args->config->cells->strings[1],
285*bf6873c5SCy Schubert                   "...second is bar.com");
286*bf6873c5SCy Schubert     }
287*bf6873c5SCy Schubert     config_free(args->config);
288*bf6873c5SCy Schubert     args->config = NULL;
289*bf6873c5SCy Schubert     options[0].type = TYPE_LIST;
290*bf6873c5SCy Schubert     options[0].defaults.string = NULL;
291*bf6873c5SCy Schubert 
292*bf6873c5SCy Schubert     /* Should be no errors so far. */
293*bf6873c5SCy Schubert     ok(pam_output() == NULL, "No errors so far");
294*bf6873c5SCy Schubert 
295*bf6873c5SCy Schubert     /* Test various ways of spelling booleans. */
296*bf6873c5SCy Schubert     args->config = config_new();
297*bf6873c5SCy Schubert     TEST_BOOL("debug", args->config->debug, true);
298*bf6873c5SCy Schubert     TEST_BOOL("debug=false", args->config->debug, false);
299*bf6873c5SCy Schubert     TEST_BOOL("debug=true", args->config->debug, true);
300*bf6873c5SCy Schubert     TEST_BOOL("debug=no", args->config->debug, false);
301*bf6873c5SCy Schubert     TEST_BOOL("debug=yes", args->config->debug, true);
302*bf6873c5SCy Schubert     TEST_BOOL("debug=off", args->config->debug, false);
303*bf6873c5SCy Schubert     TEST_BOOL("debug=on", args->config->debug, true);
304*bf6873c5SCy Schubert     TEST_BOOL("debug=0", args->config->debug, false);
305*bf6873c5SCy Schubert     TEST_BOOL("debug=1", args->config->debug, true);
306*bf6873c5SCy Schubert     TEST_BOOL("debug=False", args->config->debug, false);
307*bf6873c5SCy Schubert     TEST_BOOL("debug=trUe", args->config->debug, true);
308*bf6873c5SCy Schubert     TEST_BOOL("debug=No", args->config->debug, false);
309*bf6873c5SCy Schubert     TEST_BOOL("debug=Yes", args->config->debug, true);
310*bf6873c5SCy Schubert     TEST_BOOL("debug=OFF", args->config->debug, false);
311*bf6873c5SCy Schubert     TEST_BOOL("debug=ON", args->config->debug, true);
312*bf6873c5SCy Schubert     config_free(args->config);
313*bf6873c5SCy Schubert     args->config = NULL;
314*bf6873c5SCy Schubert 
315*bf6873c5SCy Schubert     /* Test for various parsing errors. */
316*bf6873c5SCy Schubert     args->config = config_new();
317*bf6873c5SCy Schubert     TEST_ERROR("debug=", LOG_ERR, "invalid boolean in setting: debug=");
318*bf6873c5SCy Schubert     TEST_ERROR("debug=truth", LOG_ERR,
319*bf6873c5SCy Schubert                "invalid boolean in setting: debug=truth");
320*bf6873c5SCy Schubert     TEST_ERROR("minimum_uid", LOG_ERR, "value missing for option minimum_uid");
321*bf6873c5SCy Schubert     TEST_ERROR("minimum_uid=", LOG_ERR,
322*bf6873c5SCy Schubert                "value missing for option minimum_uid=");
323*bf6873c5SCy Schubert     TEST_ERROR("minimum_uid=foo", LOG_ERR,
324*bf6873c5SCy Schubert                "invalid number in setting: minimum_uid=foo");
325*bf6873c5SCy Schubert     TEST_ERROR("minimum_uid=1000foo", LOG_ERR,
326*bf6873c5SCy Schubert                "invalid number in setting: minimum_uid=1000foo");
327*bf6873c5SCy Schubert     TEST_ERROR("program", LOG_ERR, "value missing for option program");
328*bf6873c5SCy Schubert     TEST_ERROR("cells", LOG_ERR, "value missing for option cells");
329*bf6873c5SCy Schubert     config_free(args->config);
330*bf6873c5SCy Schubert     args->config = NULL;
331*bf6873c5SCy Schubert 
332*bf6873c5SCy Schubert #ifdef HAVE_KRB5
333*bf6873c5SCy Schubert 
334*bf6873c5SCy Schubert     /* Test for Kerberos krb5.conf option parsing. */
335*bf6873c5SCy Schubert     krb5conf = test_file_path("data/krb5-pam.conf");
336*bf6873c5SCy Schubert     if (krb5conf == NULL)
337*bf6873c5SCy Schubert         bail("cannot find data/krb5-pam.conf");
338*bf6873c5SCy Schubert     if (setenv("KRB5_CONFIG", krb5conf, 1) < 0)
339*bf6873c5SCy Schubert         sysbail("cannot set KRB5_CONFIG");
340*bf6873c5SCy Schubert     krb5_free_context(args->ctx);
341*bf6873c5SCy Schubert     status = krb5_init_context(&args->ctx);
342*bf6873c5SCy Schubert     if (status != 0)
343*bf6873c5SCy Schubert         bail("cannot parse test krb5.conf file");
344*bf6873c5SCy Schubert     args->config = config_new();
345*bf6873c5SCy Schubert     status = putil_args_defaults(args, options, optlen);
346*bf6873c5SCy Schubert     ok(status, "Setting the defaults");
347*bf6873c5SCy Schubert     status = putil_args_krb5(args, "testing", options, optlen);
348*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf");
349*bf6873c5SCy Schubert     ok(args->config->cells == NULL, "...cells default");
350*bf6873c5SCy Schubert     is_int(true, args->config->debug, "...debug set from krb5.conf");
351*bf6873c5SCy Schubert     is_int(1800, args->config->expires, "...expires set from krb5.conf");
352*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root default");
353*bf6873c5SCy Schubert     is_int(1000, args->config->minimum_uid,
354*bf6873c5SCy Schubert            "...minimum_uid set from krb5.conf");
355*bf6873c5SCy Schubert     ok(args->config->program == NULL, "...program default");
356*bf6873c5SCy Schubert     status = putil_args_krb5(args, "other-test", options, optlen);
357*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf (other-test)");
358*bf6873c5SCy Schubert     is_int(-1000, args->config->minimum_uid,
359*bf6873c5SCy Schubert            "...minimum_uid set from krb5.conf other-test");
360*bf6873c5SCy Schubert 
361*bf6873c5SCy Schubert     /* Test with a realm set, which should expose more settings. */
362*bf6873c5SCy Schubert     krb5_free_context(args->ctx);
363*bf6873c5SCy Schubert     status = krb5_init_context(&args->ctx);
364*bf6873c5SCy Schubert     if (status != 0)
365*bf6873c5SCy Schubert         bail("cannot parse test krb5.conf file");
366*bf6873c5SCy Schubert     args->realm = strdup("FOO.COM");
367*bf6873c5SCy Schubert     if (args->realm == NULL)
368*bf6873c5SCy Schubert         sysbail("cannot allocate memory");
369*bf6873c5SCy Schubert     status = putil_args_krb5(args, "testing", options, optlen);
370*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf with FOO.COM");
371*bf6873c5SCy Schubert     is_int(2, args->config->cells->count, "...cells count from krb5.conf");
372*bf6873c5SCy Schubert     is_string("foo.com", args->config->cells->strings[0],
373*bf6873c5SCy Schubert               "...first cell from krb5.conf");
374*bf6873c5SCy Schubert     is_string("bar.com", args->config->cells->strings[1],
375*bf6873c5SCy Schubert               "...second cell from krb5.conf");
376*bf6873c5SCy Schubert     is_int(true, args->config->debug, "...debug set from krb5.conf");
377*bf6873c5SCy Schubert     is_int(1800, args->config->expires, "...expires set from krb5.conf");
378*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root default");
379*bf6873c5SCy Schubert     is_int(1000, args->config->minimum_uid,
380*bf6873c5SCy Schubert            "...minimum_uid set from krb5.conf");
381*bf6873c5SCy Schubert     is_string("/bin/false", args->config->program,
382*bf6873c5SCy Schubert               "...program from krb5.conf");
383*bf6873c5SCy Schubert 
384*bf6873c5SCy Schubert     /* Test with a different realm. */
385*bf6873c5SCy Schubert     free(args->realm);
386*bf6873c5SCy Schubert     args->realm = strdup("BAR.COM");
387*bf6873c5SCy Schubert     if (args->realm == NULL)
388*bf6873c5SCy Schubert         sysbail("cannot allocate memory");
389*bf6873c5SCy Schubert     status = putil_args_krb5(args, "testing", options, optlen);
390*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf with BAR.COM");
391*bf6873c5SCy Schubert     is_int(2, args->config->cells->count, "...cells count from krb5.conf");
392*bf6873c5SCy Schubert     is_string("bar.com", args->config->cells->strings[0],
393*bf6873c5SCy Schubert               "...first cell from krb5.conf");
394*bf6873c5SCy Schubert     is_string("foo.com", args->config->cells->strings[1],
395*bf6873c5SCy Schubert               "...second cell from krb5.conf");
396*bf6873c5SCy Schubert     is_int(true, args->config->debug, "...debug set from krb5.conf");
397*bf6873c5SCy Schubert     is_int(1800, args->config->expires, "...expires set from krb5.conf");
398*bf6873c5SCy Schubert     is_int(true, args->config->ignore_root, "...ignore_root default");
399*bf6873c5SCy Schubert     is_int(1000, args->config->minimum_uid,
400*bf6873c5SCy Schubert            "...minimum_uid set from krb5.conf");
401*bf6873c5SCy Schubert     is_string("echo /bin/true", args->config->program,
402*bf6873c5SCy Schubert               "...program from krb5.conf");
403*bf6873c5SCy Schubert     config_free(args->config);
404*bf6873c5SCy Schubert     args->config = config_new();
405*bf6873c5SCy Schubert     status = putil_args_krb5(args, "other-test", options, optlen);
406*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf (other-test with realm)");
407*bf6873c5SCy Schubert     ok(args->config->cells == NULL, "...cells is NULL");
408*bf6873c5SCy Schubert     is_string("echo /bin/true", args->config->program,
409*bf6873c5SCy Schubert               "...program from krb5.conf");
410*bf6873c5SCy Schubert     config_free(args->config);
411*bf6873c5SCy Schubert     args->config = NULL;
412*bf6873c5SCy Schubert 
413*bf6873c5SCy Schubert     /* Test for time parsing errors. */
414*bf6873c5SCy Schubert     args->config = config_new();
415*bf6873c5SCy Schubert     TEST_ERROR("expires=ft87", LOG_ERR,
416*bf6873c5SCy Schubert                "bad time value in setting: expires=ft87");
417*bf6873c5SCy Schubert     config_free(args->config);
418*bf6873c5SCy Schubert 
419*bf6873c5SCy Schubert     /* Test error reporting from the krb5.conf parser. */
420*bf6873c5SCy Schubert     args->config = config_new();
421*bf6873c5SCy Schubert     status = putil_args_krb5(args, "bad-number", options, optlen);
422*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf (bad-number)");
423*bf6873c5SCy Schubert     seen = pam_output();
424*bf6873c5SCy Schubert     is_string("invalid number in krb5.conf setting for minimum_uid: 1000foo",
425*bf6873c5SCy Schubert               seen->lines[0].line, "...and correct error reported");
426*bf6873c5SCy Schubert     is_int(LOG_ERR, seen->lines[0].priority, "...with correct priority");
427*bf6873c5SCy Schubert     pam_output_free(seen);
428*bf6873c5SCy Schubert     config_free(args->config);
429*bf6873c5SCy Schubert     args->config = NULL;
430*bf6873c5SCy Schubert 
431*bf6873c5SCy Schubert     /* Test error reporting on times from the krb5.conf parser. */
432*bf6873c5SCy Schubert     args->config = config_new();
433*bf6873c5SCy Schubert     status = putil_args_krb5(args, "bad-time", options, optlen);
434*bf6873c5SCy Schubert     ok(status, "Options from krb5.conf (bad-time)");
435*bf6873c5SCy Schubert     seen = pam_output();
436*bf6873c5SCy Schubert     if (seen == NULL)
437*bf6873c5SCy Schubert         ok_block(2, false, "...no error output");
438*bf6873c5SCy Schubert     else {
439*bf6873c5SCy Schubert         is_string("invalid time in krb5.conf setting for expires: ft87",
440*bf6873c5SCy Schubert                   seen->lines[0].line, "...and correct error reported");
441*bf6873c5SCy Schubert         is_int(LOG_ERR, seen->lines[0].priority, "...with correct priority");
442*bf6873c5SCy Schubert     }
443*bf6873c5SCy Schubert     pam_output_free(seen);
444*bf6873c5SCy Schubert     config_free(args->config);
445*bf6873c5SCy Schubert     args->config = NULL;
446*bf6873c5SCy Schubert 
447*bf6873c5SCy Schubert     test_file_path_free(krb5conf);
448*bf6873c5SCy Schubert 
449*bf6873c5SCy Schubert #else /* !HAVE_KRB5 */
450*bf6873c5SCy Schubert 
451*bf6873c5SCy Schubert     skip_block(37, "Kerberos support not configured");
452*bf6873c5SCy Schubert 
453*bf6873c5SCy Schubert #endif
454*bf6873c5SCy Schubert 
455*bf6873c5SCy Schubert     putil_args_free(args);
456*bf6873c5SCy Schubert     pam_end(pamh, 0);
457*bf6873c5SCy Schubert     return 0;
458*bf6873c5SCy Schubert }
459