1 /*
2 * PAM logging test suite.
3 *
4 * The canonical version of this file is maintained in the rra-c-util package,
5 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
6 *
7 * Written by Russ Allbery <eagle@eyrie.org>
8 * Copyright 2020 Russ Allbery <eagle@eyrie.org>
9 * Copyright 2010-2013
10 * The Board of Trustees of the Leland Stanford Junior University
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 *
30 * SPDX-License-Identifier: MIT
31 */
32
33 #include <config.h>
34 #include <portable/pam.h>
35 #include <portable/system.h>
36
37 #include <syslog.h>
38
39 #include <pam-util/args.h>
40 #include <pam-util/logging.h>
41 #include <tests/fakepam/pam.h>
42 #include <tests/tap/basic.h>
43 #include <tests/tap/string.h>
44
45 /* Test a normal PAM logging function. */
46 #define TEST(func, p, n) \
47 do { \
48 (func)(args, "%s", "foo"); \
49 seen = pam_output(); \
50 is_int((p), seen->lines[0].priority, "priority %d", (p)); \
51 is_string("foo", seen->lines[0].line, "line %s", (n)); \
52 pam_output_free(seen); \
53 } while (0)
54
55 /* Test a PAM error logging function. */
56 #define TEST_PAM(func, c, p, n) \
57 do { \
58 (func)(args, (c), "%s", "bar"); \
59 if ((c) == PAM_SUCCESS) \
60 expected = strdup("bar"); \
61 else \
62 basprintf(&expected, "%s: %s", "bar", \
63 pam_strerror(args->pamh, c)); \
64 seen = pam_output(); \
65 is_int((p), seen->lines[0].priority, "priority %s", (n)); \
66 is_string(expected, seen->lines[0].line, "line %s", (n)); \
67 pam_output_free(seen); \
68 free(expected); \
69 } while (0)
70
71 /* Test a PAM Kerberos error logging function .*/
72 #define TEST_KRB5(func, p, n) \
73 do { \
74 const char *msg; \
75 \
76 code = krb5_parse_name(args->ctx, "foo@bar@EXAMPLE.COM", &princ); \
77 (func)(args, code, "%s", "krb"); \
78 code = krb5_parse_name(args->ctx, "foo@bar@EXAMPLE.COM", &princ); \
79 msg = krb5_get_error_message(args->ctx, code); \
80 basprintf(&expected, "%s: %s", "krb", msg); \
81 seen = pam_output(); \
82 is_int((p), seen->lines[0].priority, "priority %s", (n)); \
83 is_string(expected, seen->lines[0].line, "line %s", (n)); \
84 pam_output_free(seen); \
85 free(expected); \
86 krb5_free_error_message(args->ctx, msg); \
87 } while (0)
88
89
90 int
main(void)91 main(void)
92 {
93 pam_handle_t *pamh;
94 struct pam_args *args;
95 struct pam_conv conv = {NULL, NULL};
96 char *expected;
97 struct output *seen;
98 #ifdef HAVE_KRB5
99 krb5_error_code code;
100 krb5_principal princ;
101 #endif
102
103 plan(27);
104
105 if (pam_start("test", NULL, &conv, &pamh) != PAM_SUCCESS)
106 sysbail("Fake PAM initialization failed");
107 args = putil_args_new(pamh, 0);
108 if (args == NULL)
109 bail("cannot create PAM argument struct");
110 TEST(putil_crit, LOG_CRIT, "putil_crit");
111 TEST(putil_err, LOG_ERR, "putil_err");
112 putil_debug(args, "%s", "foo");
113 ok(pam_output() == NULL, "putil_debug without debug on");
114 args->debug = true;
115 TEST(putil_debug, LOG_DEBUG, "putil_debug");
116 args->debug = false;
117
118 TEST_PAM(putil_crit_pam, PAM_SYSTEM_ERR, LOG_CRIT, "putil_crit_pam S");
119 TEST_PAM(putil_crit_pam, PAM_BUF_ERR, LOG_CRIT, "putil_crit_pam B");
120 TEST_PAM(putil_crit_pam, PAM_SUCCESS, LOG_CRIT, "putil_crit_pam ok");
121 TEST_PAM(putil_err_pam, PAM_SYSTEM_ERR, LOG_ERR, "putil_err_pam");
122 putil_debug_pam(args, PAM_SYSTEM_ERR, "%s", "bar");
123 ok(pam_output() == NULL, "putil_debug_pam without debug on");
124 args->debug = true;
125 TEST_PAM(putil_debug_pam, PAM_SYSTEM_ERR, LOG_DEBUG, "putil_debug_pam");
126 TEST_PAM(putil_debug_pam, PAM_SUCCESS, LOG_DEBUG, "putil_debug_pam ok");
127 args->debug = false;
128
129 #ifdef HAVE_KRB5
130 TEST_KRB5(putil_crit_krb5, LOG_CRIT, "putil_crit_krb5");
131 TEST_KRB5(putil_err_krb5, LOG_ERR, "putil_err_krb5");
132 code = krb5_parse_name(args->ctx, "foo@bar@EXAMPLE.COM", &princ);
133 putil_debug_krb5(args, code, "%s", "krb");
134 ok(pam_output() == NULL, "putil_debug_krb5 without debug on");
135 args->debug = true;
136 TEST_KRB5(putil_debug_krb5, LOG_DEBUG, "putil_debug_krb5");
137 args->debug = false;
138 #else
139 skip_block(4, "not built with Kerberos support");
140 #endif
141
142 putil_args_free(args);
143 pam_end(pamh, 0);
144
145 return 0;
146 }
147