1 /*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions
4 * are met:
5 * 1. Redistributions of source code must retain the above copyright
6 * notice, and the entire permission notice in its entirety,
7 * including the disclaimer of warranties.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * 3. The name of the author may not be used to endorse or promote
12 * products derived from this software without specific prior
13 * written permission.
14 *
15 * ALTERNATIVELY, this product may be distributed under the terms of
16 * the GNU Public License, in which case the provisions of the GPL are
17 * required INSTEAD OF the above restrictions. (This clause is
18 * necessary due to a potential bad interaction between the GPL and
19 * the restrictions contained in a BSD-style copyright.)
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <string.h>
41
42 #include <security/pam_appl.h>
43 #include <security/pam_modules.h>
44 #include <pam_private.h>
45
46 static int cleanup_was_called = 0;
47 static int cleanup3_was_called = 0;
48 static int cleanup3_retval = 0;
49 static int cleanup6_was_called = 0;
50 static int cleanup6_retval = 0;
51 static int cleanup7_was_called = 0;
52 static int cleanup7_retval = 0;
53 static int cleanup7b_was_called = 0;
54 static int cleanup7b_retval = 0;
55 static int cleanup8_was_called = 0;
56 static int cleanup8_retval = 0;
57
58 static void
59 tst_cleanup (pam_handle_t *pamh UNUSED, void *data, int error_status)
60 {
61 cleanup_was_called = 1;
62 fprintf (stderr, "tst_cleanup was called: data=\"%s\", error_status=%d\n",
63 (char *)data, error_status);
64 }
65
66 static void
67 tst_cleanup_3 (pam_handle_t *pamh UNUSED, void *data, int error_status)
68 {
69 cleanup3_was_called = 1;
70
71 if (strcmp (data, "test3") != 0)
72 {
73 fprintf (stderr, "tst_cleanup_3 called with wrong data, got \"%s\"\n",
74 (char *)data);
75 cleanup3_retval = 1;
76 return;
77 }
78
79 free (data);
80
81 if (error_status & PAM_DATA_REPLACE)
82 {
83 fprintf (stderr, "tst_cleanup_3 called with PAM_DATA_REPLACE set\n");
84 cleanup3_retval = 1;
85 return;
86 }
87
88 if (error_status & PAM_DATA_SILENT)
89 {
90 fprintf (stderr, "tst_cleanup_3 called with PAM_DATA_SILENT set\n");
91 cleanup3_retval = 1;
92 return;
93 }
94
95 if (error_status != 0)
96 {
97 fprintf (stderr, "tst_cleanup_3 called with error_status set: %d\n",
98 error_status);
99 cleanup3_retval = 1;
100 return;
101 }
102 }
103
104 static void
105 tst_cleanup_6 (pam_handle_t *pamh UNUSED, void *data, int error_status)
106 {
107 cleanup6_was_called = 1;
108
109 if (error_status & PAM_DATA_SILENT)
110 {
111 fprintf (stderr, "tst_cleanup_6 called with PAM_DATA_SILENT set\n");
112 cleanup6_retval = 1;
113 return;
114 }
115
116 if (error_status & PAM_DATA_REPLACE)
117 {
118 if (strcmp (data, "test6a") != 0)
119 {
120 fprintf (stderr, "tst_cleanup_6 called with wrong data, got \"%s\"\n",
121 (char *)data);
122 cleanup6_retval = 1;
123 return;
124 }
125
126 if (error_status != PAM_DATA_REPLACE)
127 {
128 fprintf (stderr, "tst_cleanup_6 called with error_status set: %d\n",
129 error_status);
130 cleanup6_retval = 1;
131 return;
132 }
133 }
134 else
135 {
136 if (strcmp (data, "test6b") != 0)
137 {
138 fprintf (stderr, "tst_cleanup_6 called with wrong data, got \"%s\"\n",
139 (char *)data);
140 cleanup6_retval = 1;
141 return;
142 }
143
144 if (error_status != 0)
145 {
146 fprintf (stderr, "tst_cleanup_6 called with error_status set: %d\n",
147 error_status);
148 cleanup6_retval = 1;
149 return;
150 }
151 }
152
153 free (data);
154 }
155
156 static void
157 tst_cleanup_7 (pam_handle_t *pamh UNUSED, void *data, int error_status)
158 {
159 cleanup7_was_called = 1;
160
161 if (error_status & PAM_DATA_SILENT)
162 {
163 fprintf (stderr, "tst_cleanup_7 called with PAM_DATA_SILENT set\n");
164 cleanup7_retval = 1;
165 return;
166 }
167
168 if (error_status & PAM_DATA_REPLACE)
169 {
170 if (strcmp (data, "test7a") != 0)
171 {
172 fprintf (stderr, "tst_cleanup_7 called with wrong data, got \"%s\"\n",
173 (char *)data);
174 cleanup7_retval = 1;
175 return;
176 }
177
178 if (error_status != PAM_DATA_REPLACE)
179 {
180 fprintf (stderr, "tst_cleanup_7 called with error_status set: %d\n",
181 error_status);
182 cleanup7_retval = 1;
183 return;
184 }
185 }
186 else
187 {
188 fprintf (stderr, "tst_cleanup_7 called without PAM_DATA_REPLACE set: %d\n",
189 error_status);
190 cleanup7_retval = 1;
191 return;
192 }
193
194 free (data);
195 }
196
197 static void
198 tst_cleanup_7b (pam_handle_t *pamh UNUSED, void *data, int error_status)
199 {
200 cleanup7b_was_called = 1;
201
202 if (strcmp (data, "test7b") != 0)
203 {
204 fprintf (stderr, "tst_cleanup_7b called with wrong data, got \"%s\"\n",
205 (char *)data);
206 cleanup7b_retval = 1;
207 return;
208 }
209
210 free (data);
211
212 if (error_status & PAM_DATA_REPLACE)
213 {
214 fprintf (stderr, "tst_cleanup_7b called with PAM_DATA_REPLACE set\n");
215 cleanup7b_retval = 1;
216 return;
217 }
218
219 if (error_status & PAM_DATA_SILENT)
220 {
221 fprintf (stderr, "tst_cleanup_7b called with PAM_DATA_SILENT set\n");
222 cleanup7b_retval = 1;
223 return;
224 }
225
226 if (error_status != 0)
227 {
228 fprintf (stderr, "tst_cleanup_7b called with error_status set: %d\n",
229 error_status);
230 cleanup7b_retval = 1;
231 return;
232 }
233 }
234
235 static void
236 tst_cleanup_8 (pam_handle_t *pamh UNUSED, void *data, int error_status)
237 {
238 cleanup8_was_called = 1;
239
240 if (strcmp (data, "test8") != 0)
241 {
242 fprintf (stderr, "tst_cleanup_8 called with wrong data, got \"%s\"\n",
243 (char *)data);
244 cleanup8_retval = 1;
245 return;
246 }
247
248 free (data);
249
250 if (error_status & PAM_DATA_REPLACE)
251 {
252 fprintf (stderr, "tst_cleanup_8 called with PAM_DATA_REPLACE set\n");
253 cleanup8_retval = 1;
254 return;
255 }
256
257 if (error_status & PAM_DATA_SILENT)
258 {
259 fprintf (stderr, "tst_cleanup_8 called with PAM_DATA_SILENT set\n");
260 cleanup8_retval = 1;
261 return;
262 }
263
264 if (error_status != 987)
265 {
266 fprintf (stderr, "tst_cleanup_8 called with wrong error_status set: %d\n",
267 error_status);
268 cleanup8_retval = 1;
269 return;
270 }
271 }
272
273 int
274 main (void)
275 {
276 const char *service = "dummy";
277 const char *user = "root";
278 struct pam_conv conv = { NULL, NULL };
279 pam_handle_t *pamh;
280 void *dataptr;
281 int retval;
282
283 /* 1: Call with NULL as pam handle */
284 dataptr = strdup ("test1");
285 retval = pam_set_data (NULL, "tst-pam_set_data-1", dataptr, tst_cleanup);
286 if (retval == PAM_SUCCESS)
287 {
288 fprintf (stderr, "pam_set_data (NULL, ...) returned PAM_SUCCESS\n");
289 return 1;
290 }
291 free (dataptr);
292
293 /* setup pam handle */
294 retval = pam_start (service, user, &conv, &pamh);
295 if (retval != PAM_SUCCESS)
296 {
297 fprintf (stderr, "pam_start (%s, %s, &conv, &pamh) returned %d\n",
298 service, user, retval);
299 return 1;
300 }
301
302 /* 2: check for call from application */
303 dataptr = strdup ("test2");
304 retval = pam_set_data (pamh, "tst-pam_set_data-2", dataptr, tst_cleanup);
305 if (retval != PAM_SYSTEM_ERR)
306 {
307 fprintf (stderr,
308 "pam_set_data returned %d when expecting PAM_SYSTEM_ERR\n",
309 retval);
310 return 1;
311 }
312 free (dataptr);
313
314
315 /* 3: check for call from module */
316 __PAM_TO_MODULE(pamh);
317 dataptr = strdup ("test3");
318 retval = pam_set_data (pamh, "tst-pam_set_data-3", dataptr,
319 tst_cleanup_3);
320 if (retval != PAM_SUCCESS)
321 {
322 fprintf (stderr,
323 "pam_set_data failed: %d\n",
324 retval);
325 return 1;
326 }
327
328 /* 4: check for call with NULL as module_data_name */
329 dataptr = strdup ("test4");
330 retval = pam_set_data (pamh, NULL, dataptr, tst_cleanup);
331 if (retval == PAM_SUCCESS)
332 {
333 fprintf (stderr,
334 "pam_set_data with NULL as module_data_name succeeded!\n");
335 return 1;
336 }
337 free (dataptr);
338
339 /* 5: check for call with NULL as cleanup function */
340 dataptr = strdup ("test5");
341 retval = pam_set_data (pamh, "tst-pam_set_data-5", dataptr, NULL);
342 if (retval != PAM_SUCCESS)
343 {
344 fprintf (stderr,
345 "pam_set_data with NULL as cleanup function failed: %d\n",
346 retval);
347 return 1;
348 }
349 free (dataptr);
350
351 /* 6: Overwrite data and check cleanup flags */
352 dataptr = strdup ("test6a");
353 retval = pam_set_data (pamh, "tst-pam_set_data-6", dataptr,
354 tst_cleanup_6);
355 if (retval != PAM_SUCCESS)
356 {
357 fprintf (stderr,
358 "test6: first pam_set_data failed: %d\n",
359 retval);
360 return 1;
361 }
362
363 dataptr = strdup ("test6b");
364 retval = pam_set_data (pamh, "tst-pam_set_data-6", dataptr,
365 tst_cleanup_6);
366 if (retval != PAM_SUCCESS)
367 {
368 fprintf (stderr,
369 "test6: second pam_set_data failed: %d\n",
370 retval);
371 return 1;
372 }
373
374 /* 7: Overwrite data and cleanup function, check cleanup flags */
375 dataptr = strdup ("test7a");
376 retval = pam_set_data (pamh, "tst-pam_set_data-7", dataptr,
377 tst_cleanup_7);
378 if (retval != PAM_SUCCESS)
379 {
380 fprintf (stderr,
381 "test7: first pam_set_data failed: %d\n",
382 retval);
383 return 1;
384 }
385
386 dataptr = strdup ("test7b");
387 retval = pam_set_data (pamh, "tst-pam_set_data-7", dataptr,
388 tst_cleanup_7b);
389 if (retval != PAM_SUCCESS)
390 {
391 fprintf (stderr,
392 "test7: second pam_set_data failed: %d\n",
393 retval);
394 return 1;
395 }
396
397 __PAM_TO_APP(pamh);
398
399 /* Close PAM handle and check return codes of cleanup functions */
400 retval = pam_end (pamh, 0);
401 if (retval != PAM_SUCCESS)
402 {
403 fprintf (stderr,
404 "pam_end reported an error: %d\n",
405 retval);
406 return 1;
407 }
408
409 if (cleanup_was_called == 1)
410 return 1;
411
412 if (cleanup3_was_called == 0)
413 {
414 fprintf (stderr, "tst_cleanup_3 was never called!\n");
415 return 1;
416 }
417 if (cleanup3_retval != 0)
418 return 1;
419
420 if (cleanup6_was_called == 0)
421 {
422 fprintf (stderr, "tst_cleanup_6 was never called!\n");
423 return 1;
424 }
425 if (cleanup6_retval != 0)
426 return 1;
427
428 if (cleanup7_was_called == 0)
429 {
430 fprintf (stderr, "tst_cleanup_7 was never called!\n");
431 return 1;
432 }
433 if (cleanup7_retval != 0)
434 return 1;
435
436 if (cleanup7b_was_called == 0)
437 {
438 fprintf (stderr, "tst_cleanup_7b was never called!\n");
439 return 1;
440 }
441 if (cleanup7b_retval != 0)
442 return 1;
443
444 /* test if error code is delivered to cleanup function */
445 /* setup pam handle */
446 retval = pam_start (service, user, &conv, &pamh);
447 if (retval != PAM_SUCCESS)
448 {
449 fprintf (stderr, "pam_start (%s, %s, &conv, &pamh) returned %d\n",
450 service, user, retval);
451 return 1;
452 }
453
454 /* 8: check if cleanup function is called with correct error code */
455 __PAM_TO_MODULE(pamh);
456 dataptr = strdup ("test8");
457 retval = pam_set_data (pamh, "tst-pam_set_data-8", dataptr,
458 tst_cleanup_8);
459 if (retval != PAM_SUCCESS)
460 {
461 fprintf (stderr,
462 "test8: pam_set_data failed: %d\n",
463 retval);
464 return 1;
465 }
466
467 __PAM_TO_APP(pamh);
468
469 retval = pam_end (pamh, 987);
470 if (retval != PAM_SUCCESS)
471 {
472 fprintf (stderr,
473 "pam_end reported an error: %d\n",
474 retval);
475 return 1;
476 }
477
478 if (cleanup8_was_called == 0)
479 {
480 fprintf (stderr, "tst_cleanup_3 was never called!\n");
481 return 1;
482 }
483
484 if (cleanup8_retval != 0)
485 return 1;
486
487 return 0;
488 }