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 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