xref: /freebsd/contrib/pam-krb5/tests/fakepam/logging.c (revision bf6873c5786e333d679a7838d28812febf479a8a)
1*bf6873c5SCy Schubert /*
2*bf6873c5SCy Schubert  * Logging functions for the fake PAM library, used for testing.
3*bf6873c5SCy Schubert  *
4*bf6873c5SCy Schubert  * This file contains the implementation of pam_syslog and pam_vsyslog, which
5*bf6873c5SCy Schubert  * log to an internal buffer rather than to syslog, and the testing function
6*bf6873c5SCy Schubert  * used to recover that buffer.  It also includes the pam_strerror
7*bf6873c5SCy Schubert  * implementation.
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-2012, 2014
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 #include <config.h>
39*bf6873c5SCy Schubert #include <portable/pam.h>
40*bf6873c5SCy Schubert #include <portable/system.h>
41*bf6873c5SCy Schubert 
42*bf6873c5SCy Schubert #include <tests/fakepam/internal.h>
43*bf6873c5SCy Schubert #include <tests/fakepam/pam.h>
44*bf6873c5SCy Schubert #include <tests/tap/basic.h>
45*bf6873c5SCy Schubert #include <tests/tap/string.h>
46*bf6873c5SCy Schubert 
47*bf6873c5SCy Schubert /* Used for unused parameters to silence gcc warnings. */
48*bf6873c5SCy Schubert #define UNUSED __attribute__((__unused__))
49*bf6873c5SCy Schubert 
50*bf6873c5SCy Schubert /* The struct used to accumulate log messages. */
51*bf6873c5SCy Schubert static struct output *messages = NULL;
52*bf6873c5SCy Schubert 
53*bf6873c5SCy Schubert 
54*bf6873c5SCy Schubert /*
55*bf6873c5SCy Schubert  * Allocate a new, empty output struct and call bail if memory allocation
56*bf6873c5SCy Schubert  * fails.
57*bf6873c5SCy Schubert  */
58*bf6873c5SCy Schubert struct output *
output_new(void)59*bf6873c5SCy Schubert output_new(void)
60*bf6873c5SCy Schubert {
61*bf6873c5SCy Schubert     struct output *output;
62*bf6873c5SCy Schubert 
63*bf6873c5SCy Schubert     output = bmalloc(sizeof(struct output));
64*bf6873c5SCy Schubert     output->count = 0;
65*bf6873c5SCy Schubert     output->allocated = 1;
66*bf6873c5SCy Schubert     output->lines = bmalloc(sizeof(output->lines[0]));
67*bf6873c5SCy Schubert     output->lines[0].line = NULL;
68*bf6873c5SCy Schubert     return output;
69*bf6873c5SCy Schubert }
70*bf6873c5SCy Schubert 
71*bf6873c5SCy Schubert 
72*bf6873c5SCy Schubert /*
73*bf6873c5SCy Schubert  * Add a new output line to the output struct, resizing the array as
74*bf6873c5SCy Schubert  * necessary.  Calls bail if memory allocation fails.
75*bf6873c5SCy Schubert  */
76*bf6873c5SCy Schubert void
output_add(struct output * output,int priority,const char * string)77*bf6873c5SCy Schubert output_add(struct output *output, int priority, const char *string)
78*bf6873c5SCy Schubert {
79*bf6873c5SCy Schubert     size_t next = output->count;
80*bf6873c5SCy Schubert     size_t size, n;
81*bf6873c5SCy Schubert 
82*bf6873c5SCy Schubert     if (output->count == output->allocated) {
83*bf6873c5SCy Schubert         n = output->allocated + 1;
84*bf6873c5SCy Schubert         size = sizeof(output->lines[0]);
85*bf6873c5SCy Schubert         output->lines = breallocarray(output->lines, n, size);
86*bf6873c5SCy Schubert         output->allocated = n;
87*bf6873c5SCy Schubert     }
88*bf6873c5SCy Schubert     output->lines[next].priority = priority;
89*bf6873c5SCy Schubert     output->lines[next].line = bstrdup(string);
90*bf6873c5SCy Schubert     output->count++;
91*bf6873c5SCy Schubert }
92*bf6873c5SCy Schubert 
93*bf6873c5SCy Schubert 
94*bf6873c5SCy Schubert /*
95*bf6873c5SCy Schubert  * Return the error string associated with the PAM error code.  We do this as
96*bf6873c5SCy Schubert  * a giant case statement so that we don't assume anything about the error
97*bf6873c5SCy Schubert  * codes used by the system PAM library.
98*bf6873c5SCy Schubert  */
99*bf6873c5SCy Schubert const char *
pam_strerror(PAM_STRERROR_CONST pam_handle_t * pamh UNUSED,int code)100*bf6873c5SCy Schubert pam_strerror(PAM_STRERROR_CONST pam_handle_t *pamh UNUSED, int code)
101*bf6873c5SCy Schubert {
102*bf6873c5SCy Schubert     /* clang-format off */
103*bf6873c5SCy Schubert     switch (code) {
104*bf6873c5SCy Schubert     case PAM_SUCCESS:     return "No error";
105*bf6873c5SCy Schubert     case PAM_OPEN_ERR:    return "Failure loading service module";
106*bf6873c5SCy Schubert     case PAM_SYMBOL_ERR:  return "Symbol not found";
107*bf6873c5SCy Schubert     case PAM_SERVICE_ERR: return "Error in service module";
108*bf6873c5SCy Schubert     case PAM_SYSTEM_ERR:  return "System error";
109*bf6873c5SCy Schubert     case PAM_BUF_ERR:     return "Memory buffer error";
110*bf6873c5SCy Schubert     default:              return "Unknown error";
111*bf6873c5SCy Schubert     }
112*bf6873c5SCy Schubert     /* clang-format on */
113*bf6873c5SCy Schubert }
114*bf6873c5SCy Schubert 
115*bf6873c5SCy Schubert 
116*bf6873c5SCy Schubert /*
117*bf6873c5SCy Schubert  * Log a message using variadic arguments.  Just a wrapper around
118*bf6873c5SCy Schubert  * pam_vsyslog.
119*bf6873c5SCy Schubert  */
120*bf6873c5SCy Schubert void
pam_syslog(const pam_handle_t * pamh,int priority,const char * format,...)121*bf6873c5SCy Schubert pam_syslog(const pam_handle_t *pamh, int priority, const char *format, ...)
122*bf6873c5SCy Schubert {
123*bf6873c5SCy Schubert     va_list args;
124*bf6873c5SCy Schubert 
125*bf6873c5SCy Schubert     va_start(args, format);
126*bf6873c5SCy Schubert     pam_vsyslog(pamh, priority, format, args);
127*bf6873c5SCy Schubert     va_end(args);
128*bf6873c5SCy Schubert }
129*bf6873c5SCy Schubert 
130*bf6873c5SCy Schubert 
131*bf6873c5SCy Schubert /*
132*bf6873c5SCy Schubert  * Log a PAM error message with a given priority.  Just appends the priority,
133*bf6873c5SCy Schubert  * a space, and the error message, followed by a newline, to the internal
134*bf6873c5SCy Schubert  * buffer, allocating new space if needed.  Ignore memory allocation failures;
135*bf6873c5SCy Schubert  * we have no way of reporting them, but the tests will fail due to missing
136*bf6873c5SCy Schubert  * output.
137*bf6873c5SCy Schubert  */
138*bf6873c5SCy Schubert void
pam_vsyslog(const pam_handle_t * pamh UNUSED,int priority,const char * format,va_list args)139*bf6873c5SCy Schubert pam_vsyslog(const pam_handle_t *pamh UNUSED, int priority, const char *format,
140*bf6873c5SCy Schubert             va_list args)
141*bf6873c5SCy Schubert {
142*bf6873c5SCy Schubert     char *message = NULL;
143*bf6873c5SCy Schubert 
144*bf6873c5SCy Schubert     bvasprintf(&message, format, args);
145*bf6873c5SCy Schubert     if (messages == NULL)
146*bf6873c5SCy Schubert         messages = output_new();
147*bf6873c5SCy Schubert     output_add(messages, priority, message);
148*bf6873c5SCy Schubert     free(message);
149*bf6873c5SCy Schubert }
150*bf6873c5SCy Schubert 
151*bf6873c5SCy Schubert 
152*bf6873c5SCy Schubert /*
153*bf6873c5SCy Schubert  * Used by test code.  Returns the accumulated messages in an output struct
154*bf6873c5SCy Schubert  * and starts a new one.  Caller is responsible for freeing with
155*bf6873c5SCy Schubert  * pam_output_free.
156*bf6873c5SCy Schubert  */
157*bf6873c5SCy Schubert struct output *
pam_output(void)158*bf6873c5SCy Schubert pam_output(void)
159*bf6873c5SCy Schubert {
160*bf6873c5SCy Schubert     struct output *output;
161*bf6873c5SCy Schubert 
162*bf6873c5SCy Schubert     output = messages;
163*bf6873c5SCy Schubert     messages = NULL;
164*bf6873c5SCy Schubert     return output;
165*bf6873c5SCy Schubert }
166*bf6873c5SCy Schubert 
167*bf6873c5SCy Schubert 
168*bf6873c5SCy Schubert /*
169*bf6873c5SCy Schubert  * Free an output struct.
170*bf6873c5SCy Schubert  */
171*bf6873c5SCy Schubert void
pam_output_free(struct output * output)172*bf6873c5SCy Schubert pam_output_free(struct output *output)
173*bf6873c5SCy Schubert {
174*bf6873c5SCy Schubert     size_t i;
175*bf6873c5SCy Schubert 
176*bf6873c5SCy Schubert     if (output == NULL)
177*bf6873c5SCy Schubert         return;
178*bf6873c5SCy Schubert     for (i = 0; i < output->count; i++)
179*bf6873c5SCy Schubert         if (output->lines[i].line != NULL)
180*bf6873c5SCy Schubert             free(output->lines[i].line);
181*bf6873c5SCy Schubert     free(output->lines);
182*bf6873c5SCy Schubert     free(output);
183*bf6873c5SCy Schubert }
184