charset/tests: assert the exact values of str[n]casecmp_m()
[Samba.git] / lib / pam_wrapper / libpamtest.h
blob0307a2663afd7e7df77775ac4251be67dba98a69
1 /*
2 * Copyright (c) 2015 Andreas Schneider <asn@samba.org>
3 * Copyright (c) 2015 Jakub Hrozek <jakub.hrozek@posteo.se>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef __LIBPAMTEST_H_
20 #define __LIBPAMTEST_H_
22 #include <stdint.h>
23 #include <security/pam_appl.h>
25 /**
26 * @defgroup pamtest The pamtest API
28 * @{
31 /**
32 * @brief The enum which describes the operations performed by pamtest().
34 enum pamtest_ops {
35 /** run pam_authenticate to authenticate the account */
36 PAMTEST_AUTHENTICATE,
37 /** run pam_setcred() to establish/delete user credentials */
38 PAMTEST_SETCRED,
39 /** run pam_acct_mgmt() to validate the PAM account */
40 PAMTEST_ACCOUNT,
41 /** run pam_open_session() to start a PAM session */
42 PAMTEST_OPEN_SESSION,
43 /** run pam_close_session() to end a PAM session */
44 PAMTEST_CLOSE_SESSION,
45 /** run pam_chauthtok() to update the authentication token */
46 PAMTEST_CHAUTHTOK,
48 /**
49 * If this option is set the test will call pam_getenvlist() and copy
50 * the environment into case_out.envlist.
52 PAMTEST_GETENVLIST = 20,
53 /**
54 * This will prevent calling pam_end() and will just return the
55 * PAM handle in case_out.ph.
57 PAMTEST_KEEPHANDLE,
61 /**
62 * @brief The PAM testcase struction. Use the pam_test and pam_test_flags
63 * macros to fill them.
65 * @see run_pamtest()
67 struct pam_testcase {
68 enum pamtest_ops pam_operation; /* The pam operation to run */
69 int expected_rv; /* What we expect the op to return */
70 int flags; /* Extra flags to pass to the op */
72 int op_rv; /* What the op really returns */
74 union {
75 char **envlist; /* output of PAMTEST_ENVLIST */
76 pam_handle_t *ph; /* output of PAMTEST_KEEPHANDLE */
77 } case_out; /* depends on pam_operation, mostly unused */
80 /** Initializes a pam_tescase structure. */
81 #define pam_test(op, expected) { op, expected, 0, 0, { .envlist = NULL } }
82 /** Initializes a CMUnitTest structure with additional PAM flags. */
83 #define pam_test_flags(op, expected, flags) { op, expected, flags, 0, { .envlist = NULL } }
85 /**
86 * @brief The return code of the pamtest function
88 enum pamtest_err {
89 /** Testcases returns correspond with input */
90 PAMTEST_ERR_OK,
91 /** pam_start() failed */
92 PAMTEST_ERR_START,
93 /** A testcase failed. Use pamtest_failed_case */
94 PAMTEST_ERR_CASE,
95 /** Could not run a test case */
96 PAMTEST_ERR_OP,
97 /** pam_end failed */
98 PAMTEST_ERR_END,
99 /** Handled internally */
100 PAMTEST_ERR_KEEPHANDLE,
101 /** Internal error - bad input or similar */
102 PAMTEST_ERR_INTERNAL,
106 * @brief PAM conversation function, defined in pam_conv(3)
108 * This is just a typedef to use in our declarations. See man pam_conv(3)
109 * for more details.
111 typedef int (*pam_conv_fn)(int num_msg,
112 const struct pam_message **msg,
113 struct pam_response **resp,
114 void *appdata_ptr);
117 * @brief This structure should be used when using run_pamtest,
118 * which uses an internal conversation function.
120 struct pamtest_conv_data {
121 /** When the conversation function receives PAM_PROMPT_ECHO_OFF,
122 * it reads the auth token from the in_echo_off array and keeps
123 * an index internally.
125 const char **in_echo_off;
126 /** When the conversation function receives PAM_PROMPT_ECHO_ON,
127 * it reads the input from the in_echo_off array and keeps
128 * an index internally.
130 const char **in_echo_on;
132 /** Captures messages through PAM_TEXT_INFO. The test caller is
133 * responsible for allocating enough space in the array.
135 char **out_err;
136 /** Captures messages through PAM_ERROR_MSG. The test caller is
137 * responsible for allocating enough space in the array.
139 char **out_info;
142 #ifdef DOXYGEN
144 * @brief Run libpamtest test cases
146 * This is using the default libpamtest conversation function.
148 * @param[in] service The PAM service to use in the conversation
150 * @param[in] user The user to run conversation as
152 * @param[in] conv_fn Test-specific conversation function
154 * @param[in] conv_userdata Test-specific conversation data
156 * @param[in] test_cases List of libpamtest test cases. Must end with
157 * PAMTEST_CASE_SENTINEL
159 * @code
160 * int main(void) {
161 * int rc;
162 * const struct pam_testcase tests[] = {
163 * pam_test(PAM_AUTHENTICATE, PAM_SUCCESS),
164 * };
166 * rc = run_pamtest(tests, NULL, NULL);
168 * return rc;
170 * @endcode
172 * @return PAMTEST_ERR_OK on success, else the error code matching the failure.
174 enum pamtest_err run_pamtest_conv(const char *service,
175 const char *user,
176 pam_conv_fn conv_fn,
177 void *conv_userdata,
178 struct pam_testcase test_cases[]);
179 #else
180 #define run_pamtest_conv(service, user, conv_fn, conv_data, test_cases) \
181 _pamtest_conv(service, user, conv_fn, conv_data, test_cases, sizeof(test_cases)/sizeof(test_cases[0])
182 #endif
184 #ifdef DOXYGEN
186 * @brief Run libpamtest test cases
188 * This is using the default libpamtest conversation function.
190 * @param[in] service The PAM service to use in the conversation
192 * @param[in] user The user to run conversation as
194 * @param[in] conv_data Test-specific conversation data
196 * @param[in] test_cases List of libpamtest test cases. Must end with
197 * PAMTEST_CASE_SENTINEL
199 * @code
200 * int main(void) {
201 * int rc;
202 * const struct pam_testcase tests[] = {
203 * pam_test(PAM_AUTHENTICATE, PAM_SUCCESS),
204 * };
206 * rc = run_pamtest(tests, NULL, NULL);
208 * return rc;
210 * @endcode
212 * @return PAMTEST_ERR_OK on success, else the error code matching the failure.
214 enum pamtest_err run_pamtest(const char *service,
215 const char *user,
216 struct pamtest_conv_data *conv_data,
217 struct pam_testcase test_cases[]);
218 #else
219 #define run_pamtest(service, user, conv_data, test_cases) \
220 _pamtest(service, user, conv_data, test_cases, sizeof(test_cases)/sizeof(test_cases[0]))
221 #endif
223 #ifdef DOXYGEN
225 * @brief Helper you can call if run_pamtest() fails.
227 * If PAMTEST_ERR_CASE is returned by run_pamtest() you should call this
228 * function get a pointer to the failed test case.
230 * @param[in] test_cases The array of tests.
232 * @return a pointer to the array of test_cases[] that corresponds to the
233 * first test case where the expected error code doesn't match the real error
234 * code.
236 const struct pam_testcase *pamtest_failed_case(struct pam_testcase *test_cases);
237 #else
238 #define pamtest_failed_case(test_cases) \
239 _pamtest_failed_case(test_cases, sizeof(test_cases) / sizeof(test_cases[0]))
240 #endif
243 * @brief return a string representation of libpamtest error code.
245 * @param[in] perr libpamtest error code
247 * @return String representation of the perr argument. Never returns NULL.
249 const char *pamtest_strerror(enum pamtest_err perr);
252 * @brief This frees the string array returned by the PAMTEST_GETENVLIST test.
254 * @param[in] envlist The array to free.
256 void pamtest_free_env(char **envlist);
259 /* Internal function protypes */
260 enum pamtest_err _pamtest_conv(const char *service,
261 const char *user,
262 pam_conv_fn conv_fn,
263 void *conv_userdata,
264 struct pam_testcase test_cases[],
265 size_t num_test_cases);
267 enum pamtest_err _pamtest(const char *service,
268 const char *user,
269 struct pamtest_conv_data *conv_data,
270 struct pam_testcase test_cases[],
271 size_t num_test_cases);
273 const struct pam_testcase *_pamtest_failed_case(struct pam_testcase test_cases[],
274 size_t num_test_cases);
276 /** @} */
278 #endif /* __LIBPAMTEST_H_ */