Line data Source code
1 : /*
2 : * Copyright (c) 2015 Andreas Schneider <asn@samba.org>
3 : * Copyright (c) 2015 Jakub Hrozek <jakub.hrozek@posteo.se>
4 : *
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.
9 : *
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.
14 : *
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/>.
17 : */
18 :
19 : #include "config.h"
20 :
21 : #include <errno.h>
22 : #include <stdarg.h>
23 : #include <stdbool.h>
24 : #include <stdlib.h>
25 : #include <stdio.h>
26 : #include <string.h>
27 : #include <stdint.h>
28 : #include <sys/types.h>
29 : #include <sys/stat.h>
30 : #include <dirent.h>
31 : #include <fcntl.h>
32 : #include <unistd.h>
33 : #include <dlfcn.h>
34 : #include <libgen.h>
35 : #include <signal.h>
36 : #include <limits.h>
37 : #include <ctype.h>
38 :
39 : #include <pthread.h>
40 :
41 : #include <ftw.h>
42 :
43 : #ifdef HAVE_SECURITY_PAM_APPL_H
44 : #include <security/pam_appl.h>
45 : #endif
46 : #ifdef HAVE_SECURITY_PAM_MODULES_H
47 : #include <security/pam_modules.h>
48 : #endif
49 : #ifdef HAVE_SECURITY_PAM_EXT_H
50 : #include <security/pam_ext.h>
51 : #endif
52 :
53 : #include "pwrap_compat.h"
54 :
55 : #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
56 : # define PWRAP_THREAD __thread
57 : #else
58 : # define PWRAP_THREAD
59 : #endif
60 :
61 : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
62 : #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
63 : #else
64 : #define CONSTRUCTOR_ATTRIBUTE
65 : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
66 :
67 : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
68 : #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
69 : #else
70 : #define DESTRUCTOR_ATTRIBUTE
71 : #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
72 :
73 : #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
74 : #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
75 : #else /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
76 : #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
77 : #endif /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
78 :
79 : /* GCC have printf type attribute check. */
80 : #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
81 : #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
82 : #else
83 : #define PRINTF_ATTRIBUTE(a,b)
84 : #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
85 :
86 : #ifndef SAFE_FREE
87 : #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
88 : #endif
89 :
90 : #ifndef discard_const
91 : #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
92 : #endif
93 :
94 : #ifndef discard_const_p
95 : #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
96 : #endif
97 :
98 : /*****************
99 : * LOGGING
100 : *****************/
101 :
102 : #ifndef HAVE_GETPROGNAME
103 31324 : static const char *getprogname(void)
104 : {
105 : #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
106 31324 : return program_invocation_short_name;
107 : #elif defined(HAVE_GETEXECNAME)
108 : return getexecname();
109 : #else
110 : return NULL;
111 : #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
112 : }
113 : #endif /* HAVE_GETPROGNAME */
114 :
115 : enum pwrap_dbglvl_e {
116 : PWRAP_LOG_ERROR = 0,
117 : PWRAP_LOG_WARN,
118 : PWRAP_LOG_DEBUG,
119 : PWRAP_LOG_TRACE
120 : };
121 :
122 : static void pwrap_log(enum pwrap_dbglvl_e dbglvl,
123 : const char *function,
124 : const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
125 : # define PWRAP_LOG(dbglvl, ...) pwrap_log((dbglvl), __func__, __VA_ARGS__)
126 :
127 : static void pwrap_vlog(enum pwrap_dbglvl_e dbglvl,
128 : const char *function,
129 : const char *format,
130 : va_list args) PRINTF_ATTRIBUTE(3, 0);
131 :
132 31324 : static void pwrap_vlog(enum pwrap_dbglvl_e dbglvl,
133 : const char *function,
134 : const char *format,
135 : va_list args)
136 : {
137 : char buffer[1024];
138 : const char *d;
139 31324 : unsigned int lvl = 0;
140 31324 : const char *prefix = "PWRAP";
141 31324 : const char *progname = getprogname();
142 :
143 31324 : d = getenv("PAM_WRAPPER_DEBUGLEVEL");
144 31324 : if (d != NULL) {
145 31324 : lvl = atoi(d);
146 : }
147 :
148 31324 : if (lvl < dbglvl) {
149 25428 : return;
150 : }
151 :
152 5896 : vsnprintf(buffer, sizeof(buffer), format, args);
153 :
154 5896 : switch (dbglvl) {
155 201 : case PWRAP_LOG_ERROR:
156 201 : prefix = "PWRAP_ERROR";
157 201 : break;
158 76 : case PWRAP_LOG_WARN:
159 76 : prefix = "PWRAP_WARN";
160 76 : break;
161 5114 : case PWRAP_LOG_DEBUG:
162 5114 : prefix = "PWRAP_DEBUG";
163 5114 : break;
164 505 : case PWRAP_LOG_TRACE:
165 505 : prefix = "PWRAP_TRACE";
166 505 : break;
167 : }
168 :
169 5896 : if (progname == NULL) {
170 0 : progname = "<unknown>";
171 : }
172 :
173 5896 : fprintf(stderr,
174 : "%s[%s (%u)] - %s: %s\n",
175 : prefix,
176 : progname,
177 5896 : (unsigned int)getpid(),
178 : function,
179 : buffer);
180 : }
181 :
182 26865 : static void pwrap_log(enum pwrap_dbglvl_e dbglvl,
183 : const char *function,
184 : const char *format, ...)
185 : {
186 : va_list va;
187 :
188 26865 : va_start(va, format);
189 26865 : pwrap_vlog(dbglvl, function, format, va);
190 26865 : va_end(va);
191 26865 : }
192 :
193 : /*****************
194 : * LIBC
195 : *****************/
196 :
197 : #define LIBPAM_NAME "libpam.so.0"
198 :
199 : typedef int (*__libpam_pam_start)(const char *service_name,
200 : const char *user,
201 : const struct pam_conv *pam_conversation,
202 : pam_handle_t **pamh);
203 :
204 : typedef int (*__libpam_pam_start_confdir)(const char *service_name,
205 : const char *user,
206 : const struct pam_conv *pam_conversation,
207 : const char *confdir,
208 : pam_handle_t **pamh);
209 :
210 : typedef int (*__libpam_pam_end)(pam_handle_t *pamh, int pam_status);
211 :
212 : typedef int (*__libpam_pam_authenticate)(pam_handle_t *pamh, int flags);
213 :
214 : typedef int (*__libpam_pam_chauthtok)(pam_handle_t *pamh, int flags);
215 :
216 : typedef int (*__libpam_pam_acct_mgmt)(pam_handle_t *pamh, int flags);
217 :
218 : typedef int (*__libpam_pam_putenv)(pam_handle_t *pamh, const char *name_value);
219 :
220 : typedef const char * (*__libpam_pam_getenv)(pam_handle_t *pamh, const char *name);
221 :
222 : typedef char ** (*__libpam_pam_getenvlist)(pam_handle_t *pamh);
223 :
224 : typedef int (*__libpam_pam_open_session)(pam_handle_t *pamh, int flags);
225 :
226 : typedef int (*__libpam_pam_close_session)(pam_handle_t *pamh, int flags);
227 :
228 : typedef int (*__libpam_pam_setcred)(pam_handle_t *pamh, int flags);
229 :
230 : typedef int (*__libpam_pam_get_item)(const pam_handle_t *pamh,
231 : int item_type,
232 : const void **item);
233 :
234 : typedef int (*__libpam_pam_set_item)(pam_handle_t *pamh,
235 : int item_type,
236 : const void *item);
237 :
238 : typedef int (*__libpam_pam_get_data)(const pam_handle_t *pamh,
239 : const char *module_data_name,
240 : const void **data);
241 :
242 : typedef int (*__libpam_pam_set_data)(pam_handle_t *pamh,
243 : const char *module_data_name,
244 : void *data,
245 : void (*cleanup)(pam_handle_t *pamh,
246 : void *data,
247 : int error_status));
248 :
249 : typedef int (*__libpam_pam_vprompt)(pam_handle_t *pamh,
250 : int style,
251 : char **response,
252 : const char *fmt,
253 : va_list args);
254 :
255 : typedef const char * (*__libpam_pam_strerror)(pam_handle_t *pamh,
256 : int errnum);
257 :
258 : #ifdef HAVE_PAM_VSYSLOG
259 : typedef void (*__libpam_pam_vsyslog)(const pam_handle_t *pamh,
260 : int priority,
261 : const char *fmt,
262 : va_list args);
263 : #endif
264 :
265 : #define PWRAP_SYMBOL_ENTRY(i) \
266 : union { \
267 : __libpam_##i f; \
268 : void *obj; \
269 : } _libpam_##i
270 :
271 : struct pwrap_libpam_symbols {
272 : PWRAP_SYMBOL_ENTRY(pam_start);
273 : PWRAP_SYMBOL_ENTRY(pam_start_confdir);
274 : PWRAP_SYMBOL_ENTRY(pam_end);
275 : PWRAP_SYMBOL_ENTRY(pam_authenticate);
276 : PWRAP_SYMBOL_ENTRY(pam_chauthtok);
277 : PWRAP_SYMBOL_ENTRY(pam_acct_mgmt);
278 : PWRAP_SYMBOL_ENTRY(pam_putenv);
279 : PWRAP_SYMBOL_ENTRY(pam_getenv);
280 : PWRAP_SYMBOL_ENTRY(pam_getenvlist);
281 : PWRAP_SYMBOL_ENTRY(pam_open_session);
282 : PWRAP_SYMBOL_ENTRY(pam_close_session);
283 : PWRAP_SYMBOL_ENTRY(pam_setcred);
284 : PWRAP_SYMBOL_ENTRY(pam_get_item);
285 : PWRAP_SYMBOL_ENTRY(pam_set_item);
286 : PWRAP_SYMBOL_ENTRY(pam_get_data);
287 : PWRAP_SYMBOL_ENTRY(pam_set_data);
288 : PWRAP_SYMBOL_ENTRY(pam_vprompt);
289 : PWRAP_SYMBOL_ENTRY(pam_strerror);
290 : #ifdef HAVE_PAM_VSYSLOG
291 : PWRAP_SYMBOL_ENTRY(pam_vsyslog);
292 : #endif
293 : };
294 :
295 : struct pwrap {
296 : struct {
297 : void *handle;
298 : struct pwrap_libpam_symbols symbols;
299 : } libpam;
300 :
301 : bool enabled;
302 : bool initialised;
303 : char *config_dir;
304 : char *libpam_so;
305 : };
306 :
307 : static struct pwrap pwrap;
308 :
309 : /*********************************************************
310 : * PWRAP PROTOTYPES
311 : *********************************************************/
312 :
313 : bool pam_wrapper_enabled(void);
314 : #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
315 : /* xlC and other oldschool compilers support (only) this */
316 : #pragma init (pwrap_constructor)
317 : #endif
318 : void pwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
319 : #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
320 : #pragma fini (pwrap_destructor)
321 : #endif
322 : void pwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
323 :
324 : /*********************************************************
325 : * PWRAP LIBC LOADER FUNCTIONS
326 : *********************************************************/
327 :
328 : enum pwrap_lib {
329 : PWRAP_LIBPAM,
330 : };
331 :
332 708 : static void *pwrap_load_lib_handle(enum pwrap_lib lib)
333 : {
334 708 : int flags = RTLD_LAZY;
335 708 : void *handle = NULL;
336 :
337 : #ifdef RTLD_DEEPBIND
338 708 : const char *env_preload = getenv("LD_PRELOAD");
339 708 : const char *env_deepbind = getenv("UID_WRAPPER_DISABLE_DEEPBIND");
340 708 : bool enable_deepbind = true;
341 :
342 : /* Don't do a deepbind if we run with libasan */
343 708 : if (env_preload != NULL && strlen(env_preload) < 1024) {
344 708 : const char *p = strstr(env_preload, "libasan.so");
345 708 : if (p != NULL) {
346 0 : enable_deepbind = false;
347 : }
348 : }
349 :
350 708 : if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
351 0 : enable_deepbind = false;
352 : }
353 :
354 708 : if (enable_deepbind) {
355 708 : flags |= RTLD_DEEPBIND;
356 : }
357 : #endif
358 :
359 708 : switch (lib) {
360 708 : case PWRAP_LIBPAM:
361 708 : handle = pwrap.libpam.handle;
362 708 : if (handle == NULL) {
363 98 : handle = dlopen(pwrap.libpam_so, flags);
364 98 : if (handle != NULL) {
365 98 : PWRAP_LOG(PWRAP_LOG_DEBUG,
366 : "Opened %s\n", pwrap.libpam_so);
367 98 : pwrap.libpam.handle = handle;
368 98 : break;
369 : }
370 : }
371 610 : break;
372 : }
373 :
374 708 : if (handle == NULL) {
375 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
376 : "Failed to dlopen library: %s\n",
377 : dlerror());
378 0 : exit(-1);
379 : }
380 :
381 708 : return handle;
382 : }
383 :
384 708 : static void *_pwrap_bind_symbol(enum pwrap_lib lib, const char *fn_name)
385 : {
386 : void *handle;
387 : void *func;
388 :
389 708 : handle = pwrap_load_lib_handle(lib);
390 :
391 708 : func = dlsym(handle, fn_name);
392 708 : if (func == NULL) {
393 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
394 : "Failed to find %s: %s\n",
395 : fn_name, dlerror());
396 0 : exit(-1);
397 : }
398 :
399 708 : return func;
400 : }
401 :
402 : #define pwrap_bind_symbol_libpam(sym_name) \
403 : if (pwrap.libpam.symbols._libpam_##sym_name.obj == NULL) { \
404 : pwrap.libpam.symbols._libpam_##sym_name.obj = \
405 : _pwrap_bind_symbol(PWRAP_LIBPAM, #sym_name); \
406 : } \
407 :
408 : /*
409 : * IMPORTANT
410 : *
411 : * Functions especially from libpam need to be loaded individually, you can't
412 : * load all at once or gdb will segfault at startup. The same applies to
413 : * valgrind and has probably something todo with with the linker.
414 : * So we need load each function at the point it is called the first time.
415 : */
416 : #ifdef HAVE_PAM_START_CONFDIR
417 250 : static int libpam_pam_start_confdir(const char *service_name,
418 : const char *user,
419 : const struct pam_conv *pam_conversation,
420 : const char *confdir,
421 : pam_handle_t **pamh)
422 : {
423 250 : pwrap_bind_symbol_libpam(pam_start_confdir);
424 :
425 250 : return pwrap.libpam.symbols._libpam_pam_start_confdir.f(service_name,
426 : user,
427 : pam_conversation,
428 : confdir,
429 : pamh);
430 : }
431 : #else
432 : static int libpam_pam_start(const char *service_name,
433 : const char *user,
434 : const struct pam_conv *pam_conversation,
435 : pam_handle_t **pamh)
436 : {
437 : pwrap_bind_symbol_libpam(pam_start);
438 :
439 : return pwrap.libpam.symbols._libpam_pam_start.f(service_name,
440 : user,
441 : pam_conversation,
442 : pamh);
443 : }
444 :
445 : #endif
446 :
447 250 : static int libpam_pam_end(pam_handle_t *pamh, int pam_status)
448 : {
449 250 : pwrap_bind_symbol_libpam(pam_end);
450 :
451 250 : return pwrap.libpam.symbols._libpam_pam_end.f(pamh, pam_status);
452 : }
453 :
454 238 : static int libpam_pam_authenticate(pam_handle_t *pamh, int flags)
455 : {
456 238 : pwrap_bind_symbol_libpam(pam_authenticate);
457 :
458 238 : return pwrap.libpam.symbols._libpam_pam_authenticate.f(pamh, flags);
459 : }
460 :
461 12 : static int libpam_pam_chauthtok(pam_handle_t *pamh, int flags)
462 : {
463 12 : pwrap_bind_symbol_libpam(pam_chauthtok);
464 :
465 12 : return pwrap.libpam.symbols._libpam_pam_chauthtok.f(pamh, flags);
466 : }
467 :
468 0 : static int libpam_pam_acct_mgmt(pam_handle_t *pamh, int flags)
469 : {
470 0 : pwrap_bind_symbol_libpam(pam_acct_mgmt);
471 :
472 0 : return pwrap.libpam.symbols._libpam_pam_acct_mgmt.f(pamh, flags);
473 : }
474 :
475 30 : static int libpam_pam_putenv(pam_handle_t *pamh, const char *name_value)
476 : {
477 30 : pwrap_bind_symbol_libpam(pam_putenv);
478 :
479 30 : return pwrap.libpam.symbols._libpam_pam_putenv.f(pamh, name_value);
480 : }
481 :
482 4 : static const char *libpam_pam_getenv(pam_handle_t *pamh, const char *name)
483 : {
484 4 : pwrap_bind_symbol_libpam(pam_getenv);
485 :
486 4 : return pwrap.libpam.symbols._libpam_pam_getenv.f(pamh, name);
487 : }
488 :
489 2 : static char **libpam_pam_getenvlist(pam_handle_t *pamh)
490 : {
491 2 : pwrap_bind_symbol_libpam(pam_getenvlist);
492 :
493 2 : return pwrap.libpam.symbols._libpam_pam_getenvlist.f(pamh);
494 : }
495 :
496 0 : static int libpam_pam_open_session(pam_handle_t *pamh, int flags)
497 : {
498 0 : pwrap_bind_symbol_libpam(pam_open_session);
499 :
500 0 : return pwrap.libpam.symbols._libpam_pam_open_session.f(pamh, flags);
501 : }
502 :
503 0 : static int libpam_pam_close_session(pam_handle_t *pamh, int flags)
504 : {
505 0 : pwrap_bind_symbol_libpam(pam_close_session);
506 :
507 0 : return pwrap.libpam.symbols._libpam_pam_close_session.f(pamh, flags);
508 : }
509 :
510 2 : static int libpam_pam_setcred(pam_handle_t *pamh, int flags)
511 : {
512 2 : pwrap_bind_symbol_libpam(pam_setcred);
513 :
514 2 : return pwrap.libpam.symbols._libpam_pam_setcred.f(pamh, flags);
515 : }
516 :
517 6170 : static int libpam_pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
518 : {
519 6170 : pwrap_bind_symbol_libpam(pam_get_item);
520 :
521 6170 : return pwrap.libpam.symbols._libpam_pam_get_item.f(pamh, item_type, item);
522 : }
523 :
524 944 : static int libpam_pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
525 : {
526 944 : pwrap_bind_symbol_libpam(pam_set_item);
527 :
528 944 : return pwrap.libpam.symbols._libpam_pam_set_item.f(pamh, item_type, item);
529 : }
530 :
531 3748 : static int libpam_pam_get_data(const pam_handle_t *pamh,
532 : const char *module_data_name,
533 : const void **data)
534 : {
535 3748 : pwrap_bind_symbol_libpam(pam_get_data);
536 :
537 3748 : return pwrap.libpam.symbols._libpam_pam_get_data.f(pamh,
538 : module_data_name,
539 : data);
540 : }
541 :
542 756 : static int libpam_pam_set_data(pam_handle_t *pamh,
543 : const char *module_data_name,
544 : void *data,
545 : void (*cleanup)(pam_handle_t *pamh,
546 : void *data,
547 : int error_status))
548 : {
549 756 : pwrap_bind_symbol_libpam(pam_set_data);
550 :
551 756 : return pwrap.libpam.symbols._libpam_pam_set_data.f(pamh,
552 : module_data_name,
553 : data,
554 : cleanup);
555 : }
556 :
557 0 : static int libpam_pam_vprompt(pam_handle_t *pamh,
558 : int style,
559 : char **response,
560 : const char *fmt,
561 : va_list args)
562 : {
563 0 : pwrap_bind_symbol_libpam(pam_vprompt);
564 :
565 0 : return pwrap.libpam.symbols._libpam_pam_vprompt.f(pamh,
566 : style,
567 : response,
568 : fmt,
569 : args);
570 : }
571 :
572 : #ifdef HAVE_PAM_STRERROR_CONST
573 : static const char *libpam_pam_strerror(const pam_handle_t *pamh, int errnum)
574 : #else
575 0 : static const char *libpam_pam_strerror(pam_handle_t *pamh, int errnum)
576 : #endif
577 : {
578 0 : pwrap_bind_symbol_libpam(pam_strerror);
579 :
580 0 : return pwrap.libpam.symbols._libpam_pam_strerror.f(discard_const_p(pam_handle_t, pamh), errnum);
581 : }
582 :
583 : #ifdef HAVE_PAM_VSYSLOG
584 0 : static void libpam_pam_vsyslog(const pam_handle_t *pamh,
585 : int priority,
586 : const char *fmt,
587 : va_list args)
588 : {
589 0 : pwrap_bind_symbol_libpam(pam_vsyslog);
590 :
591 0 : pwrap.libpam.symbols._libpam_pam_vsyslog.f(pamh,
592 : priority,
593 : fmt,
594 : args);
595 0 : }
596 : #endif /* HAVE_PAM_VSYSLOG */
597 :
598 : /*********************************************************
599 : * PWRAP INIT
600 : *********************************************************/
601 :
602 : #define BUFFER_SIZE 32768
603 :
604 : /* copy file from src to dst, overwrites dst */
605 278 : static int p_copy(const char *src, const char *dst, mode_t mode)
606 : {
607 278 : int srcfd = -1;
608 278 : int dstfd = -1;
609 278 : int rc = -1;
610 : ssize_t bread, bwritten;
611 : struct stat sb;
612 : char buf[BUFFER_SIZE];
613 : int cmp;
614 :
615 278 : cmp = strcmp(src, dst);
616 278 : if (cmp == 0) {
617 0 : return -1;
618 : }
619 :
620 278 : srcfd = open(src, O_RDONLY, 0);
621 278 : if (srcfd < 0) {
622 0 : return -1;
623 : }
624 :
625 278 : if (mode == 0) {
626 0 : rc = fstat(srcfd, &sb);
627 0 : if (rc != 0) {
628 0 : rc = -1;
629 0 : goto out;
630 : }
631 0 : mode = sb.st_mode;
632 : }
633 :
634 278 : dstfd = open(dst, O_CREAT|O_WRONLY|O_TRUNC, mode);
635 278 : if (dstfd < 0) {
636 0 : rc = -1;
637 0 : goto out;
638 : }
639 :
640 : for (;;) {
641 556 : bread = read(srcfd, buf, BUFFER_SIZE);
642 556 : if (bread == 0) {
643 : /* done */
644 278 : break;
645 278 : } else if (bread < 0) {
646 0 : errno = EIO;
647 0 : rc = -1;
648 0 : goto out;
649 : }
650 :
651 278 : bwritten = write(dstfd, buf, bread);
652 278 : if (bwritten < 0) {
653 0 : errno = EIO;
654 0 : rc = -1;
655 0 : goto out;
656 : }
657 :
658 278 : if (bread != bwritten) {
659 0 : errno = EFAULT;
660 0 : rc = -1;
661 0 : goto out;
662 : }
663 : }
664 :
665 278 : rc = 0;
666 278 : out:
667 278 : if (srcfd != -1) {
668 278 : close(srcfd);
669 : }
670 278 : if (dstfd != -1) {
671 278 : close(dstfd);
672 : }
673 278 : if (rc < 0) {
674 0 : unlink(dst);
675 : }
676 :
677 278 : return rc;
678 : }
679 :
680 : /* Do not pass any flag if not defined */
681 : #ifndef FTW_ACTIONRETVAL
682 : #define FTW_ACTIONRETVAL 0
683 : #endif
684 :
685 : /* Action return values */
686 : #ifndef FTW_STOP
687 : #define FTW_STOP -1
688 : #endif
689 :
690 : #ifndef FTW_CONTINUE
691 : #define FTW_CONTINUE 0
692 : #endif
693 :
694 : #ifndef FTW_SKIP_SUBTREE
695 : #define FTW_SKIP_SUBTREE 0
696 : #endif
697 :
698 556 : static int copy_ftw(const char *fpath,
699 : const struct stat *sb,
700 : int typeflag,
701 : struct FTW *ftwbuf)
702 : {
703 : int rc;
704 : char buf[BUFFER_SIZE];
705 :
706 556 : switch (typeflag) {
707 278 : case FTW_D:
708 : case FTW_DNR:
709 : /* We want to copy the directories from this directory */
710 278 : if (ftwbuf->level == 0) {
711 278 : return FTW_CONTINUE;
712 : }
713 0 : return FTW_SKIP_SUBTREE;
714 278 : case FTW_F:
715 278 : break;
716 0 : default:
717 0 : return FTW_CONTINUE;
718 : }
719 :
720 278 : rc = snprintf(buf, BUFFER_SIZE, "%s/%s", pwrap.config_dir, fpath + ftwbuf->base);
721 278 : if (rc >= BUFFER_SIZE) {
722 0 : return FTW_STOP;
723 : }
724 :
725 278 : PWRAP_LOG(PWRAP_LOG_TRACE, "Copying %s", fpath);
726 278 : rc = p_copy(fpath, buf, sb->st_mode);
727 278 : if (rc != 0) {
728 0 : return FTW_STOP;
729 : }
730 :
731 278 : return FTW_CONTINUE;
732 : }
733 :
734 278 : static int copy_confdir(const char *src)
735 : {
736 : int rc;
737 :
738 278 : PWRAP_LOG(PWRAP_LOG_DEBUG,
739 : "Copy config files from %s to %s",
740 : src,
741 : pwrap.config_dir);
742 278 : rc = nftw(src, copy_ftw, 1, FTW_ACTIONRETVAL);
743 278 : if (rc != 0) {
744 0 : return -1;
745 : }
746 :
747 278 : return 0;
748 : }
749 :
750 : static int p_rmdirs(const char *path);
751 :
752 0 : static void pwrap_clean_stale_dirs(const char *dir)
753 0 : {
754 0 : size_t len = strlen(dir);
755 0 : char pidfile[len + 5];
756 : ssize_t rc;
757 0 : char buf[8] = {0};
758 : long int tmp;
759 : pid_t pid;
760 : int fd;
761 :
762 0 : snprintf(pidfile,
763 : sizeof(pidfile),
764 : "%s/pid",
765 : dir);
766 :
767 : /* read the pidfile */
768 0 : fd = open(pidfile, O_RDONLY);
769 0 : if (fd < 0) {
770 0 : if (errno == ENOENT) {
771 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
772 : "pidfile %s missing, nothing to do\n",
773 : pidfile);
774 : } else {
775 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
776 : "Failed to open pidfile %s - error: %s",
777 : pidfile, strerror(errno));
778 : }
779 0 : return;
780 : }
781 :
782 0 : rc = read(fd, buf, sizeof(buf));
783 0 : close(fd);
784 0 : if (rc < 0) {
785 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
786 : "Failed to read pidfile %s - error: %s",
787 : pidfile, strerror(errno));
788 0 : return;
789 : }
790 :
791 0 : buf[sizeof(buf) - 1] = '\0';
792 :
793 0 : tmp = strtol(buf, NULL, 10);
794 0 : if (tmp == 0 || errno == ERANGE) {
795 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
796 : "Failed to parse pid, buf=%s",
797 : buf);
798 0 : return;
799 : }
800 :
801 0 : pid = (pid_t)tmp;
802 : /* Check if we are out of pid_t range on this system */
803 0 : if ((long)pid != tmp) {
804 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
805 : "pid out of range: %ld", tmp);
806 0 : return;
807 : }
808 :
809 0 : rc = kill(pid, 0);
810 0 : if (rc == -1) {
811 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
812 : "Remove stale pam_wrapper dir: %s",
813 : dir);
814 0 : p_rmdirs(dir);
815 : }
816 :
817 0 : return;
818 : }
819 :
820 : #ifdef HAVE_PAM_START_CONFDIR
821 564 : static void pwrap_init(void)
822 : {
823 564 : char tmp_config_dir[] = "/tmp/pam.X";
824 564 : size_t len = strlen(tmp_config_dir);
825 : const char *env;
826 : struct stat sb;
827 : int rc;
828 : unsigned i;
829 : ssize_t ret;
830 : FILE *pidfile;
831 564 : char pidfile_path[1024] = { 0 };
832 : char letter;
833 :
834 564 : if (!pam_wrapper_enabled()) {
835 286 : return;
836 : }
837 :
838 528 : if (pwrap.initialised) {
839 250 : return;
840 : }
841 :
842 : /*
843 : * The name is selected to match/replace /etc/pam.d
844 : * We start from a random alphanum trying letters until
845 : * an available directory is found.
846 : */
847 278 : letter = 48 + (getpid() % 70);
848 487 : for (i = 0; i < 127; i++) {
849 487 : if (isalpha(letter) || isdigit(letter)) {
850 278 : tmp_config_dir[len - 1] = letter;
851 :
852 278 : rc = lstat(tmp_config_dir, &sb);
853 278 : if (rc == 0) {
854 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
855 : "Check if pam_wrapper dir %s is a "
856 : "stale directory",
857 : tmp_config_dir);
858 0 : pwrap_clean_stale_dirs(tmp_config_dir);
859 278 : } else if (rc < 0) {
860 278 : if (errno != ENOENT) {
861 0 : continue;
862 : }
863 278 : break; /* found */
864 : }
865 : }
866 :
867 209 : letter++;
868 209 : letter %= 127;
869 : }
870 :
871 278 : if (i == 127) {
872 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
873 : "Failed to find a possible path to create "
874 : "pam_wrapper config dir: %s",
875 : tmp_config_dir);
876 0 : exit(1);
877 : }
878 :
879 278 : PWRAP_LOG(PWRAP_LOG_DEBUG, "Initialize pam_wrapper");
880 :
881 278 : pwrap.config_dir = strdup(tmp_config_dir);
882 278 : if (pwrap.config_dir == NULL) {
883 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
884 : "No memory");
885 0 : exit(1);
886 : }
887 278 : PWRAP_LOG(PWRAP_LOG_TRACE,
888 : "pam_wrapper config dir: %s",
889 : tmp_config_dir);
890 :
891 278 : rc = mkdir(pwrap.config_dir, 0755);
892 278 : if (rc != 0) {
893 0 : PWRAP_LOG(PWRAP_LOG_ERROR,
894 : "Failed to create pam_wrapper config dir: %s - %s",
895 : tmp_config_dir, strerror(errno));
896 : }
897 :
898 : /* Create file with the PID of the the process */
899 278 : ret = snprintf(pidfile_path, sizeof(pidfile_path),
900 : "%s/pid", pwrap.config_dir);
901 278 : if (ret < 0) {
902 0 : p_rmdirs(pwrap.config_dir);
903 0 : exit(1);
904 : }
905 :
906 278 : pidfile = fopen(pidfile_path, "w");
907 278 : if (pidfile == NULL) {
908 0 : p_rmdirs(pwrap.config_dir);
909 0 : exit(1);
910 : }
911 :
912 278 : rc = fprintf(pidfile, "%d", getpid());
913 278 : fclose(pidfile);
914 278 : if (rc <= 0) {
915 0 : p_rmdirs(pwrap.config_dir);
916 0 : exit(1);
917 : }
918 :
919 278 : pwrap.libpam_so = strdup(PAM_LIBRARY);
920 278 : if (pwrap.libpam_so == NULL) {
921 0 : PWRAP_LOG(PWRAP_LOG_ERROR, "No memory");
922 0 : p_rmdirs(pwrap.config_dir);
923 0 : exit(1);
924 : }
925 :
926 278 : PWRAP_LOG(PWRAP_LOG_TRACE, "Using libpam path: %s", pwrap.libpam_so);
927 :
928 278 : pwrap.initialised = true;
929 :
930 278 : env = getenv("PAM_WRAPPER_SERVICE_DIR");
931 278 : if (env == NULL) {
932 0 : PWRAP_LOG(PWRAP_LOG_ERROR, "No config file");
933 0 : p_rmdirs(pwrap.config_dir);
934 0 : exit(1);
935 : }
936 :
937 278 : rc = copy_confdir(env);
938 278 : if (rc != 0) {
939 0 : PWRAP_LOG(PWRAP_LOG_ERROR, "Failed to copy config files");
940 0 : p_rmdirs(pwrap.config_dir);
941 0 : exit(1);
942 : }
943 :
944 278 : setenv("PAM_WRAPPER_RUNTIME_DIR", pwrap.config_dir, 1);
945 :
946 278 : PWRAP_LOG(PWRAP_LOG_DEBUG, "Successfully initialized pam_wrapper");
947 : }
948 :
949 : #else /* HAVE_PAM_START_CONFDIR */
950 :
951 : static int pso_copy(const char *src, const char *dst, const char *pdir, mode_t mode)
952 : {
953 : #define PSO_COPY_READ_SIZE 9
954 : int srcfd = -1;
955 : int dstfd = -1;
956 : int rc = -1;
957 : ssize_t bread, bwritten;
958 : struct stat sb;
959 : char buf[PSO_COPY_READ_SIZE + 1];
960 : int cmp;
961 : size_t to_read;
962 : bool found_slash;
963 :
964 : cmp = strcmp(src, dst);
965 : if (cmp == 0) {
966 : return -1;
967 : }
968 :
969 : srcfd = open(src, O_RDONLY, 0);
970 : if (srcfd < 0) {
971 : return -1;
972 : }
973 :
974 : if (mode == 0) {
975 : rc = fstat(srcfd, &sb);
976 : if (rc != 0) {
977 : rc = -1;
978 : goto out;
979 : }
980 : mode = sb.st_mode;
981 : }
982 :
983 : dstfd = open(dst, O_CREAT|O_WRONLY|O_TRUNC, mode);
984 : if (dstfd < 0) {
985 : rc = -1;
986 : goto out;
987 : }
988 :
989 : found_slash = false;
990 : to_read = 1;
991 :
992 : for (;;) {
993 : bread = read(srcfd, buf, to_read);
994 : if (bread == 0) {
995 : /* done */
996 : break;
997 : } else if (bread < 0) {
998 : errno = EIO;
999 : rc = -1;
1000 : goto out;
1001 : }
1002 :
1003 : to_read = 1;
1004 : if (!found_slash && buf[0] == '/') {
1005 : found_slash = true;
1006 : to_read = PSO_COPY_READ_SIZE;
1007 : }
1008 :
1009 : if (found_slash && bread == PSO_COPY_READ_SIZE) {
1010 : cmp = memcmp(buf, "etc/pam.d", PSO_COPY_READ_SIZE);
1011 : if (cmp == 0) {
1012 : memcpy(buf, pdir + 1, PSO_COPY_READ_SIZE);
1013 : }
1014 : found_slash = false;
1015 : }
1016 :
1017 : bwritten = write(dstfd, buf, bread);
1018 : if (bwritten < 0) {
1019 : errno = EIO;
1020 : rc = -1;
1021 : goto out;
1022 : }
1023 :
1024 : if (bread != bwritten) {
1025 : errno = EFAULT;
1026 : rc = -1;
1027 : goto out;
1028 : }
1029 : }
1030 :
1031 : rc = 0;
1032 : out:
1033 : if (srcfd != -1) {
1034 : close(srcfd);
1035 : }
1036 : if (dstfd != -1) {
1037 : close(dstfd);
1038 : }
1039 : if (rc < 0) {
1040 : unlink(dst);
1041 : }
1042 :
1043 : return rc;
1044 : #undef PSO_COPY_READ_SIZE
1045 : }
1046 :
1047 : static void pwrap_init(void)
1048 : {
1049 : char tmp_config_dir[] = "/tmp/pam.X";
1050 : size_t len = strlen(tmp_config_dir);
1051 : const char *env;
1052 : struct stat sb;
1053 : int rc;
1054 : unsigned i;
1055 : char pam_library[128] = { 0 };
1056 : char libpam_path[1024] = { 0 };
1057 : ssize_t ret;
1058 : FILE *pidfile;
1059 : char pidfile_path[1024] = { 0 };
1060 : char letter;
1061 :
1062 : if (!pam_wrapper_enabled()) {
1063 : return;
1064 : }
1065 :
1066 : if (pwrap.initialised) {
1067 : return;
1068 : }
1069 :
1070 : /*
1071 : * The name is selected to match/replace /etc/pam.d
1072 : * We start from a random alphanum trying letters until
1073 : * an available directory is found.
1074 : */
1075 : letter = 48 + (getpid() % 70);
1076 : for (i = 0; i < 127; i++) {
1077 : if (isalpha(letter) || isdigit(letter)) {
1078 : tmp_config_dir[len - 1] = letter;
1079 :
1080 : rc = lstat(tmp_config_dir, &sb);
1081 : if (rc == 0) {
1082 : PWRAP_LOG(PWRAP_LOG_TRACE,
1083 : "Check if pam_wrapper dir %s is a "
1084 : "stale directory",
1085 : tmp_config_dir);
1086 : pwrap_clean_stale_dirs(tmp_config_dir);
1087 : } else if (rc < 0) {
1088 : if (errno != ENOENT) {
1089 : continue;
1090 : }
1091 : break; /* found */
1092 : }
1093 : }
1094 :
1095 : letter++;
1096 : letter %= 127;
1097 : }
1098 :
1099 : if (i == 127) {
1100 : PWRAP_LOG(PWRAP_LOG_ERROR,
1101 : "Failed to find a possible path to create "
1102 : "pam_wrapper config dir: %s",
1103 : tmp_config_dir);
1104 : exit(1);
1105 : }
1106 :
1107 : PWRAP_LOG(PWRAP_LOG_DEBUG, "Initialize pam_wrapper");
1108 :
1109 : pwrap.config_dir = strdup(tmp_config_dir);
1110 : if (pwrap.config_dir == NULL) {
1111 : PWRAP_LOG(PWRAP_LOG_ERROR,
1112 : "No memory");
1113 : exit(1);
1114 : }
1115 : PWRAP_LOG(PWRAP_LOG_TRACE,
1116 : "pam_wrapper config dir: %s",
1117 : tmp_config_dir);
1118 :
1119 : rc = mkdir(pwrap.config_dir, 0755);
1120 : if (rc != 0) {
1121 : PWRAP_LOG(PWRAP_LOG_ERROR,
1122 : "Failed to create pam_wrapper config dir: %s - %s",
1123 : tmp_config_dir, strerror(errno));
1124 : }
1125 :
1126 : /* Create file with the PID of the the process */
1127 : ret = snprintf(pidfile_path, sizeof(pidfile_path),
1128 : "%s/pid", pwrap.config_dir);
1129 : if (ret < 0) {
1130 : p_rmdirs(pwrap.config_dir);
1131 : exit(1);
1132 : }
1133 :
1134 : pidfile = fopen(pidfile_path, "w");
1135 : if (pidfile == NULL) {
1136 : p_rmdirs(pwrap.config_dir);
1137 : exit(1);
1138 : }
1139 :
1140 : rc = fprintf(pidfile, "%d", getpid());
1141 : fclose(pidfile);
1142 : if (rc <= 0) {
1143 : p_rmdirs(pwrap.config_dir);
1144 : exit(1);
1145 : }
1146 :
1147 : /* create lib subdirectory */
1148 : snprintf(libpam_path,
1149 : sizeof(libpam_path),
1150 : "%s/lib",
1151 : pwrap.config_dir);
1152 :
1153 : rc = mkdir(libpam_path, 0755);
1154 : if (rc != 0) {
1155 : PWRAP_LOG(PWRAP_LOG_ERROR,
1156 : "Failed to create path for libpam: %s - %s",
1157 : tmp_config_dir, strerror(errno));
1158 : p_rmdirs(pwrap.config_dir);
1159 : exit(1);
1160 : }
1161 :
1162 : snprintf(libpam_path,
1163 : sizeof(libpam_path),
1164 : "%s/lib/%s",
1165 : pwrap.config_dir,
1166 : LIBPAM_NAME);
1167 :
1168 : pwrap.libpam_so = strdup(libpam_path);
1169 : if (pwrap.libpam_so == NULL) {
1170 : PWRAP_LOG(PWRAP_LOG_ERROR, "No memory");
1171 : p_rmdirs(pwrap.config_dir);
1172 : exit(1);
1173 : }
1174 :
1175 : /* copy libpam.so.0 */
1176 : snprintf(libpam_path, sizeof(libpam_path), "%s", PAM_LIBRARY);
1177 : PWRAP_LOG(PWRAP_LOG_TRACE,
1178 : "PAM path: %s",
1179 : libpam_path);
1180 :
1181 : ret = readlink(libpam_path, pam_library, sizeof(pam_library) - 1);
1182 : PWRAP_LOG(PWRAP_LOG_TRACE,
1183 : "PAM library: %s",
1184 : pam_library);
1185 : if (ret <= 0) {
1186 : PWRAP_LOG(PWRAP_LOG_ERROR, "Failed to read %s link", LIBPAM_NAME);
1187 : p_rmdirs(pwrap.config_dir);
1188 : exit(1);
1189 : }
1190 :
1191 : if (pam_library[0] == '/') {
1192 : snprintf(libpam_path,
1193 : sizeof(libpam_path),
1194 : "%s",
1195 : pam_library);
1196 : } else {
1197 : char libpam_path_cp[1024] = {0};
1198 : char *dname = NULL;
1199 :
1200 : snprintf(libpam_path_cp,
1201 : sizeof(libpam_path_cp),
1202 : "%s",
1203 : libpam_path);
1204 :
1205 : dname = dirname(libpam_path_cp);
1206 : if (dname == NULL) {
1207 : PWRAP_LOG(PWRAP_LOG_ERROR,
1208 : "No directory component in %s", libpam_path);
1209 : p_rmdirs(pwrap.config_dir);
1210 : exit(1);
1211 : }
1212 :
1213 : snprintf(libpam_path,
1214 : sizeof(libpam_path),
1215 : "%s/%s",
1216 : dname,
1217 : pam_library);
1218 : }
1219 : PWRAP_LOG(PWRAP_LOG_TRACE, "Reconstructed PAM path: %s", libpam_path);
1220 :
1221 : PWRAP_LOG(PWRAP_LOG_DEBUG, "Copy %s to %s", libpam_path, pwrap.libpam_so);
1222 : rc = pso_copy(libpam_path, pwrap.libpam_so, pwrap.config_dir, 0644);
1223 : if (rc != 0) {
1224 : PWRAP_LOG(PWRAP_LOG_ERROR,
1225 : "Failed to copy %s - error: %s",
1226 : LIBPAM_NAME,
1227 : strerror(errno));
1228 : p_rmdirs(pwrap.config_dir);
1229 : exit(1);
1230 : }
1231 :
1232 : PWRAP_LOG(PWRAP_LOG_TRACE, "Using libpam path: %s", pwrap.libpam_so);
1233 :
1234 : pwrap.initialised = true;
1235 :
1236 : env = getenv("PAM_WRAPPER_SERVICE_DIR");
1237 : if (env == NULL) {
1238 : PWRAP_LOG(PWRAP_LOG_ERROR, "No config file");
1239 : p_rmdirs(pwrap.config_dir);
1240 : exit(1);
1241 : }
1242 :
1243 : rc = copy_confdir(env);
1244 : if (rc != 0) {
1245 : PWRAP_LOG(PWRAP_LOG_ERROR, "Failed to copy config files");
1246 : p_rmdirs(pwrap.config_dir);
1247 : exit(1);
1248 : }
1249 :
1250 : setenv("PAM_WRAPPER_RUNTIME_DIR", pwrap.config_dir, 1);
1251 :
1252 : PWRAP_LOG(PWRAP_LOG_DEBUG, "Successfully initialized pam_wrapper");
1253 : }
1254 : #endif /* HAVE_PAM_START_CONFDIR */
1255 :
1256 564 : bool pam_wrapper_enabled(void)
1257 : {
1258 : const char *env;
1259 :
1260 564 : pwrap.enabled = false;
1261 :
1262 564 : env = getenv("PAM_WRAPPER");
1263 564 : if (env != NULL && env[0] == '1') {
1264 528 : pwrap.enabled = true;
1265 : }
1266 :
1267 564 : if (pwrap.enabled) {
1268 528 : pwrap.enabled = false;
1269 :
1270 528 : env = getenv("PAM_WRAPPER_SERVICE_DIR");
1271 528 : if (env != NULL && env[0] != '\0') {
1272 528 : pwrap.enabled = true;
1273 : }
1274 : }
1275 :
1276 564 : return pwrap.enabled;
1277 : }
1278 :
1279 : #ifdef HAVE_OPENPAM
1280 : static int pwrap_openpam_start(const char *service_name,
1281 : const char *user,
1282 : const struct pam_conv *pam_conversation,
1283 : pam_handle_t **pamh)
1284 : {
1285 : int rv;
1286 : char fullpath[1024];
1287 :
1288 : rv = openpam_set_feature(OPENPAM_RESTRICT_SERVICE_NAME, 0);
1289 : if (rv != PAM_SUCCESS) {
1290 : PWRAP_LOG(PWRAP_LOG_ERROR,
1291 : "Cannot disable OPENPAM_RESTRICT_SERVICE_NAME");
1292 : return rv;
1293 : }
1294 :
1295 : rv = openpam_set_feature(OPENPAM_RESTRICT_MODULE_NAME, 0);
1296 : if (rv != PAM_SUCCESS) {
1297 : PWRAP_LOG(PWRAP_LOG_ERROR,
1298 : "Cannot disable OPENPAM_RESTRICT_MODULE_NAME");
1299 : return rv;
1300 : }
1301 :
1302 : rv = openpam_set_feature(OPENPAM_VERIFY_MODULE_FILE, 0);
1303 : if (rv != PAM_SUCCESS) {
1304 : PWRAP_LOG(PWRAP_LOG_ERROR,
1305 : "Cannot disable OPENPAM_VERIFY_MODULE_FILE");
1306 : return rv;
1307 : }
1308 :
1309 : rv = openpam_set_feature(OPENPAM_VERIFY_POLICY_FILE, 0);
1310 : if (rv != PAM_SUCCESS) {
1311 : PWRAP_LOG(PWRAP_LOG_ERROR,
1312 : "Cannot disable OPENPAM_VERIFY_POLICY_FILE");
1313 : return rv;
1314 : }
1315 :
1316 : snprintf(fullpath,
1317 : sizeof(fullpath),
1318 : "%s/%s",
1319 : pwrap.config_dir,
1320 : service_name);
1321 :
1322 : return libpam_pam_start(fullpath,
1323 : user,
1324 : pam_conversation,
1325 : pamh);
1326 : }
1327 : #endif
1328 :
1329 250 : static int pwrap_pam_start(const char *service_name,
1330 : const char *user,
1331 : const struct pam_conv *pam_conversation,
1332 : pam_handle_t **pamh)
1333 : {
1334 : int rc;
1335 :
1336 250 : pwrap_init();
1337 :
1338 250 : PWRAP_LOG(PWRAP_LOG_TRACE,
1339 : "pam_start service=%s, user=%s",
1340 : service_name,
1341 : user);
1342 :
1343 : #if defined(HAVE_OPENPAM)
1344 : rc = pwrap_openpam_start(service_name,
1345 : user,
1346 : pam_conversation,
1347 : pamh);
1348 : #elif defined (HAVE_PAM_START_CONFDIR)
1349 250 : rc = libpam_pam_start_confdir(service_name,
1350 : user,
1351 : pam_conversation,
1352 250 : pwrap.config_dir,
1353 : pamh);
1354 : #else
1355 : rc = libpam_pam_start(service_name,
1356 : user,
1357 : pam_conversation,
1358 : pamh);
1359 : #endif
1360 250 : PWRAP_LOG(PWRAP_LOG_TRACE, "pam_start rc=%d", rc);
1361 :
1362 250 : return rc;
1363 : }
1364 :
1365 :
1366 : int pam_start(const char *service_name,
1367 : const char *user,
1368 : const struct pam_conv *pam_conversation,
1369 : pam_handle_t **pamh)
1370 : {
1371 250 : return pwrap_pam_start(service_name, user, pam_conversation, pamh);
1372 : }
1373 :
1374 250 : static int pwrap_pam_end(pam_handle_t *pamh, int pam_status)
1375 : {
1376 250 : PWRAP_LOG(PWRAP_LOG_TRACE, "pam_end status=%d", pam_status);
1377 250 : return libpam_pam_end(pamh, pam_status);
1378 : }
1379 :
1380 :
1381 : int pam_end(pam_handle_t *pamh, int pam_status)
1382 : {
1383 250 : return pwrap_pam_end(pamh, pam_status);
1384 : }
1385 :
1386 238 : static int pwrap_pam_authenticate(pam_handle_t *pamh, int flags)
1387 : {
1388 238 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_authenticate flags=%d", flags);
1389 238 : return libpam_pam_authenticate(pamh, flags);
1390 : }
1391 :
1392 : int pam_authenticate(pam_handle_t *pamh, int flags)
1393 : {
1394 238 : return pwrap_pam_authenticate(pamh, flags);
1395 : }
1396 :
1397 12 : static int pwrap_pam_chauthtok(pam_handle_t *pamh, int flags)
1398 : {
1399 12 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_chauthtok flags=%d", flags);
1400 12 : return libpam_pam_chauthtok(pamh, flags);
1401 : }
1402 :
1403 : int pam_chauthtok(pam_handle_t *pamh, int flags)
1404 : {
1405 12 : return pwrap_pam_chauthtok(pamh, flags);
1406 : }
1407 :
1408 0 : static int pwrap_pam_acct_mgmt(pam_handle_t *pamh, int flags)
1409 : {
1410 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_acct_mgmt flags=%d", flags);
1411 0 : return libpam_pam_acct_mgmt(pamh, flags);
1412 : }
1413 :
1414 : int pam_acct_mgmt(pam_handle_t *pamh, int flags)
1415 : {
1416 0 : return pwrap_pam_acct_mgmt(pamh, flags);
1417 : }
1418 :
1419 30 : static int pwrap_pam_putenv(pam_handle_t *pamh, const char *name_value)
1420 : {
1421 30 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_putenv name_value=%s", name_value);
1422 30 : return libpam_pam_putenv(pamh, name_value);
1423 : }
1424 :
1425 : int pam_putenv(pam_handle_t *pamh, const char *name_value)
1426 : {
1427 30 : return pwrap_pam_putenv(pamh, name_value);
1428 : }
1429 :
1430 4 : static const char *pwrap_pam_getenv(pam_handle_t *pamh, const char *name)
1431 : {
1432 4 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_getenv name=%s", name);
1433 4 : return libpam_pam_getenv(pamh, name);
1434 : }
1435 :
1436 : const char *pam_getenv(pam_handle_t *pamh, const char *name)
1437 : {
1438 4 : return pwrap_pam_getenv(pamh, name);
1439 : }
1440 :
1441 2 : static char **pwrap_pam_getenvlist(pam_handle_t *pamh)
1442 : {
1443 2 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_getenvlist called");
1444 2 : return libpam_pam_getenvlist(pamh);
1445 : }
1446 :
1447 : char **pam_getenvlist(pam_handle_t *pamh)
1448 : {
1449 2 : return pwrap_pam_getenvlist(pamh);
1450 : }
1451 :
1452 0 : static int pwrap_pam_open_session(pam_handle_t *pamh, int flags)
1453 : {
1454 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_open_session flags=%d", flags);
1455 0 : return libpam_pam_open_session(pamh, flags);
1456 : }
1457 :
1458 : int pam_open_session(pam_handle_t *pamh, int flags)
1459 : {
1460 0 : return pwrap_pam_open_session(pamh, flags);
1461 : }
1462 :
1463 0 : static int pwrap_pam_close_session(pam_handle_t *pamh, int flags)
1464 : {
1465 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_close_session flags=%d", flags);
1466 0 : return libpam_pam_close_session(pamh, flags);
1467 : }
1468 :
1469 : int pam_close_session(pam_handle_t *pamh, int flags)
1470 : {
1471 0 : return pwrap_pam_close_session(pamh, flags);
1472 : }
1473 :
1474 2 : static int pwrap_pam_setcred(pam_handle_t *pamh, int flags)
1475 : {
1476 2 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_setcred flags=%d", flags);
1477 2 : return libpam_pam_setcred(pamh, flags);
1478 : }
1479 :
1480 : int pam_setcred(pam_handle_t *pamh, int flags)
1481 : {
1482 2 : return pwrap_pam_setcred(pamh, flags);
1483 : }
1484 :
1485 798 : static const char *pwrap_get_service(const char *libpam_service)
1486 : {
1487 : #ifdef HAVE_OPENPAM
1488 : const char *service_name;
1489 :
1490 : PWRAP_LOG(PWRAP_LOG_TRACE,
1491 : "internal PAM_SERVICE=%s", libpam_service);
1492 : service_name = strrchr(libpam_service, '/');
1493 : if (service_name != NULL && service_name[0] == '/') {
1494 : service_name++;
1495 : }
1496 : PWRAP_LOG(PWRAP_LOG_TRACE,
1497 : "PAM_SERVICE=%s", service_name);
1498 : return service_name;
1499 : #else
1500 798 : return libpam_service;
1501 : #endif
1502 : }
1503 :
1504 6170 : static int pwrap_pam_get_item(const pam_handle_t *pamh,
1505 : int item_type,
1506 : const void **item)
1507 : {
1508 : int rc;
1509 : const char *svc;
1510 :
1511 6170 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_get_item called");
1512 :
1513 6170 : rc = libpam_pam_get_item(pamh, item_type, item);
1514 :
1515 6170 : if (rc == PAM_SUCCESS) {
1516 6170 : switch(item_type) {
1517 532 : case PAM_USER:
1518 532 : PWRAP_LOG(PWRAP_LOG_TRACE,
1519 : "pwrap_get_item PAM_USER=%s",
1520 : (const char *)*item);
1521 532 : break;
1522 798 : case PAM_SERVICE:
1523 798 : svc = pwrap_get_service((const char *) *item);
1524 :
1525 798 : PWRAP_LOG(PWRAP_LOG_TRACE,
1526 : "pwrap_get_item PAM_SERVICE=%s",
1527 : svc);
1528 798 : *item = svc;
1529 798 : break;
1530 532 : case PAM_USER_PROMPT:
1531 532 : PWRAP_LOG(PWRAP_LOG_TRACE,
1532 : "pwrap_get_item PAM_USER_PROMPT=%s",
1533 : (const char *)*item);
1534 532 : break;
1535 532 : case PAM_TTY:
1536 532 : PWRAP_LOG(PWRAP_LOG_TRACE,
1537 : "pwrap_get_item PAM_TTY=%s",
1538 : (const char *)*item);
1539 532 : break;
1540 532 : case PAM_RUSER:
1541 532 : PWRAP_LOG(PWRAP_LOG_TRACE,
1542 : "pwrap_get_item PAM_RUSER=%s",
1543 : (const char *)*item);
1544 532 : break;
1545 532 : case PAM_RHOST:
1546 532 : PWRAP_LOG(PWRAP_LOG_TRACE,
1547 : "pwrap_get_item PAM_RHOST=%s",
1548 : (const char *)*item);
1549 532 : break;
1550 782 : case PAM_AUTHTOK:
1551 782 : PWRAP_LOG(PWRAP_LOG_TRACE,
1552 : "pwrap_get_item PAM_AUTHTOK=%s",
1553 : (const char *)*item);
1554 782 : break;
1555 556 : case PAM_OLDAUTHTOK:
1556 556 : PWRAP_LOG(PWRAP_LOG_TRACE,
1557 : "pwrap_get_item PAM_OLDAUTHTOK=%s",
1558 : (const char *)*item);
1559 556 : break;
1560 842 : case PAM_CONV:
1561 842 : PWRAP_LOG(PWRAP_LOG_TRACE,
1562 : "pwrap_get_item PAM_CONV=%p",
1563 : (const void *)*item);
1564 842 : break;
1565 532 : default:
1566 532 : PWRAP_LOG(PWRAP_LOG_TRACE,
1567 : "pwrap_get_item item_type=%d item=%p",
1568 : item_type, (const void *)*item);
1569 532 : break;
1570 : }
1571 : } else {
1572 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_get_item failed rc=%d", rc);
1573 : }
1574 :
1575 6170 : return rc;
1576 : }
1577 :
1578 : int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
1579 : {
1580 6170 : return pwrap_pam_get_item(pamh, item_type, item);
1581 : }
1582 :
1583 944 : static int pwrap_pam_set_item(pam_handle_t *pamh,
1584 : int item_type,
1585 : const void *item)
1586 : {
1587 : int rc;
1588 :
1589 944 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_set_item called");
1590 :
1591 944 : rc = libpam_pam_set_item(pamh, item_type, item);
1592 944 : if (rc == PAM_SUCCESS) {
1593 944 : switch(item_type) {
1594 162 : case PAM_USER:
1595 162 : PWRAP_LOG(PWRAP_LOG_TRACE,
1596 : "pwrap_set_item PAM_USER=%s",
1597 : (const char *)item);
1598 162 : break;
1599 0 : case PAM_SERVICE:
1600 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1601 : "pwrap_set_item PAM_SERVICE=%s",
1602 : (const char *)item);
1603 0 : break;
1604 0 : case PAM_USER_PROMPT:
1605 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1606 : "pwrap_set_item PAM_USER_PROMPT=%s",
1607 : (const char *)item);
1608 0 : break;
1609 0 : case PAM_TTY:
1610 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1611 : "pwrap_set_item PAM_TTY=%s",
1612 : (const char *)item);
1613 0 : break;
1614 0 : case PAM_RUSER:
1615 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1616 : "pwrap_set_item PAM_RUSER=%s",
1617 : (const char *)item);
1618 0 : break;
1619 0 : case PAM_RHOST:
1620 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1621 : "pwrap_set_item PAM_RHOST=%s",
1622 : (const char *)item);
1623 0 : break;
1624 508 : case PAM_AUTHTOK:
1625 508 : PWRAP_LOG(PWRAP_LOG_TRACE,
1626 : "pwrap_set_item PAM_AUTHTOK=%s",
1627 : (const char *)item);
1628 508 : break;
1629 274 : case PAM_OLDAUTHTOK:
1630 274 : PWRAP_LOG(PWRAP_LOG_TRACE,
1631 : "pwrap_set_item PAM_OLDAUTHTOK=%s",
1632 : (const char *)item);
1633 274 : break;
1634 0 : case PAM_CONV:
1635 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1636 : "pwrap_set_item PAM_CONV=%p",
1637 : item);
1638 0 : break;
1639 0 : default:
1640 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1641 : "pwrap_set_item item_type=%d item=%p",
1642 : item_type, item);
1643 0 : break;
1644 : }
1645 : } else {
1646 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_set_item failed rc=%d", rc);
1647 : }
1648 :
1649 944 : return rc;
1650 : }
1651 :
1652 : int pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
1653 : {
1654 944 : return pwrap_pam_set_item(pamh, item_type, item);
1655 : }
1656 :
1657 3748 : static int pwrap_pam_get_data(const pam_handle_t *pamh,
1658 : const char *module_data_name,
1659 : const void **data)
1660 : {
1661 3748 : PWRAP_LOG(PWRAP_LOG_TRACE,
1662 : "pwrap_get_data module_data_name=%s", module_data_name);
1663 3748 : return libpam_pam_get_data(pamh, module_data_name, data);
1664 : }
1665 :
1666 : int pam_get_data(const pam_handle_t *pamh,
1667 : const char *module_data_name,
1668 : const void **data)
1669 : {
1670 3748 : return pwrap_pam_get_data(pamh, module_data_name, data);
1671 : }
1672 :
1673 756 : static int pwrap_pam_set_data(pam_handle_t *pamh,
1674 : const char *module_data_name,
1675 : void *data,
1676 : void (*cleanup)(pam_handle_t *pamh,
1677 : void *data,
1678 : int error_status))
1679 : {
1680 756 : PWRAP_LOG(PWRAP_LOG_TRACE,
1681 : "pwrap_set_data module_data_name=%s data=%p",
1682 : module_data_name, data);
1683 756 : return libpam_pam_set_data(pamh, module_data_name, data, cleanup);
1684 : }
1685 :
1686 : int pam_set_data(pam_handle_t *pamh,
1687 : const char *module_data_name,
1688 : void *data,
1689 : void (*cleanup)(pam_handle_t *pamh,
1690 : void *data,
1691 : int error_status))
1692 : {
1693 756 : return pwrap_pam_set_data(pamh, module_data_name, data, cleanup);
1694 : }
1695 :
1696 : #ifdef HAVE_PAM_VPROMPT_CONST
1697 : static int pwrap_pam_vprompt(const pam_handle_t *pamh,
1698 : #else
1699 0 : static int pwrap_pam_vprompt(pam_handle_t *pamh,
1700 : #endif
1701 : int style,
1702 : char **response,
1703 : const char *fmt,
1704 : va_list args)
1705 : {
1706 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_vprompt style=%d", style);
1707 0 : return libpam_pam_vprompt(discard_const_p(pam_handle_t, pamh),
1708 : style,
1709 : response,
1710 : fmt,
1711 : args);
1712 : }
1713 :
1714 : #ifdef HAVE_PAM_VPROMPT_CONST
1715 : int pam_vprompt(const pam_handle_t *pamh,
1716 : int style,
1717 : char **response,
1718 : const char *fmt,
1719 : va_list args)
1720 : #else
1721 : int pam_vprompt(pam_handle_t *pamh,
1722 : int style,
1723 : char **response,
1724 : const char *fmt,
1725 : va_list args)
1726 : #endif
1727 : {
1728 0 : return pwrap_pam_vprompt(discard_const_p(pam_handle_t, pamh),
1729 : style,
1730 : response,
1731 : fmt,
1732 : args);
1733 : }
1734 :
1735 : #ifdef HAVE_PAM_PROMPT_CONST
1736 : int pam_prompt(const pam_handle_t *pamh,
1737 : int style,
1738 : char **response,
1739 : const char *fmt, ...)
1740 : #else
1741 : int pam_prompt(pam_handle_t *pamh,
1742 : int style,
1743 : char **response,
1744 : const char *fmt, ...)
1745 : #endif
1746 : {
1747 : va_list args;
1748 : int rv;
1749 :
1750 0 : va_start(args, fmt);
1751 0 : rv = pwrap_pam_vprompt(discard_const_p(pam_handle_t, pamh),
1752 : style,
1753 : response,
1754 : fmt,
1755 : args);
1756 0 : va_end(args);
1757 :
1758 0 : return rv;
1759 : }
1760 :
1761 : #ifdef HAVE_PAM_STRERROR_CONST
1762 : static const char *pwrap_pam_strerror(const pam_handle_t *pamh, int errnum)
1763 : #else
1764 0 : static const char *pwrap_pam_strerror(pam_handle_t *pamh, int errnum)
1765 : #endif
1766 : {
1767 : const char *str;
1768 :
1769 0 : pwrap_init();
1770 :
1771 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pam_strerror errnum=%d", errnum);
1772 :
1773 0 : str = libpam_pam_strerror(discard_const_p(pam_handle_t, pamh),
1774 : errnum);
1775 :
1776 0 : PWRAP_LOG(PWRAP_LOG_TRACE, "pam_strerror error=%s", str);
1777 :
1778 0 : return str;
1779 : }
1780 :
1781 : #ifdef HAVE_PAM_STRERROR_CONST
1782 : const char *pam_strerror(const pam_handle_t *pamh, int errnum)
1783 : #else
1784 : const char *pam_strerror(pam_handle_t *pamh, int errnum)
1785 : #endif
1786 : {
1787 0 : return pwrap_pam_strerror(discard_const_p(pam_handle_t, pamh),
1788 : errnum);
1789 : }
1790 :
1791 : #if defined(HAVE_PAM_VSYSLOG) || defined(HAVE_PAM_SYSLOG)
1792 : static void pwrap_pam_vsyslog(const pam_handle_t *pamh,
1793 : int priority,
1794 : const char *fmt,
1795 : va_list args) PRINTF_ATTRIBUTE(3, 0);
1796 :
1797 4459 : static void pwrap_pam_vsyslog(const pam_handle_t *pamh,
1798 : int priority,
1799 : const char *fmt,
1800 : va_list args)
1801 : {
1802 : const char *d;
1803 4459 : char syslog_str[32] = {0};
1804 4459 : enum pwrap_dbglvl_e dbglvl = PWRAP_LOG_TRACE;
1805 :
1806 4459 : PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_vsyslog called");
1807 :
1808 : #ifdef HAVE_PAM_VSYSLOG
1809 4459 : d = getenv("PAM_WRAPPER_USE_SYSLOG");
1810 4459 : if (d != NULL && d[0] == '1') {
1811 0 : libpam_pam_vsyslog(pamh, priority, fmt, args);
1812 0 : return;
1813 : }
1814 : #endif /* HAVE_PAM_VSYSLOG */
1815 :
1816 4459 : switch(priority) {
1817 201 : case 0: /* LOG_EMERG */
1818 : case 1: /* LOG_ALERT */
1819 : case 2: /* LOG_CRIT */
1820 : case 3: /* LOG_ERR */
1821 201 : dbglvl = PWRAP_LOG_ERROR;
1822 201 : break;
1823 76 : case 4: /* LOG_WARN */
1824 76 : dbglvl = PWRAP_LOG_WARN;
1825 76 : break;
1826 4182 : case 5: /* LOG_NOTICE */
1827 : case 6: /* LOG_INFO */
1828 : case 7: /* LOG_DEBUG */
1829 4182 : dbglvl = PWRAP_LOG_DEBUG;
1830 4182 : break;
1831 0 : default:
1832 0 : dbglvl = PWRAP_LOG_TRACE;
1833 0 : break;
1834 : }
1835 :
1836 4459 : snprintf(syslog_str, sizeof(syslog_str), "SYSLOG(%d)", priority);
1837 :
1838 4459 : pwrap_vlog(dbglvl, syslog_str, fmt, args);
1839 : }
1840 : #endif /* defined(HAVE_PAM_VSYSLOG) || defined(HAVE_PAM_SYSLOG) */
1841 :
1842 : #ifdef HAVE_PAM_VSYSLOG
1843 : void pam_vsyslog(const pam_handle_t *pamh,
1844 : int priority,
1845 : const char *fmt,
1846 : va_list args)
1847 : {
1848 4334 : pwrap_pam_vsyslog(pamh, priority, fmt, args);
1849 4334 : }
1850 : #endif
1851 :
1852 : #ifdef HAVE_PAM_SYSLOG
1853 : void pam_syslog(const pam_handle_t *pamh,
1854 : int priority,
1855 : const char *fmt, ...)
1856 : {
1857 : va_list args;
1858 :
1859 125 : va_start(args, fmt);
1860 125 : pwrap_pam_vsyslog(pamh, priority, fmt, args);
1861 125 : va_end(args);
1862 125 : }
1863 : #endif
1864 :
1865 : /* This might be called by pam_end() running with sshd */
1866 : int audit_open(void);
1867 502 : int audit_open(void)
1868 : {
1869 : /*
1870 : * Tell the application that the kernel doesn't
1871 : * have audit compiled in.
1872 : */
1873 502 : errno = EPROTONOSUPPORT;
1874 502 : return -1;
1875 : }
1876 :
1877 : /* Disable BSD auditing */
1878 : int cannot_audit(int x);
1879 0 : int cannot_audit(int x)
1880 : {
1881 : (void) x;
1882 :
1883 0 : return 1;
1884 : }
1885 :
1886 : /****************************
1887 : * CONSTRUCTOR
1888 : ***************************/
1889 :
1890 : /*
1891 : * Handler executed before fork(2) processing starts.
1892 : */
1893 24 : static void pwrap_thread_prepare(void)
1894 : {
1895 24 : }
1896 :
1897 : /*
1898 : * Handler that is executed in the parent process after fork(2) processing
1899 : * completes.
1900 : */
1901 24 : static void pwrap_thread_parent(void)
1902 : {
1903 24 : }
1904 :
1905 : /*
1906 : * Handler that is executed in the child process after fork(2) processing
1907 : * completes.
1908 : */
1909 0 : static void pwrap_thread_child(void)
1910 : {
1911 0 : pwrap.initialised = false;
1912 0 : }
1913 :
1914 314 : void pwrap_constructor(void)
1915 : {
1916 : /*
1917 : * If we hold a lock and the application forks, then the child
1918 : * is not able to unlock the mutex and we are in a deadlock.
1919 : * This should prevent such deadlocks.
1920 : */
1921 314 : pthread_atfork(&pwrap_thread_prepare,
1922 : &pwrap_thread_parent,
1923 : &pwrap_thread_child);
1924 :
1925 : /*
1926 : * Here is safe place to call pwrap_init() and initialize data
1927 : * for main process.
1928 : */
1929 314 : pwrap_init();
1930 314 : }
1931 :
1932 : /****************************
1933 : * DESTRUCTOR
1934 : ***************************/
1935 :
1936 278 : static int p_rmdirs_at(const char *path, int parent_fd)
1937 : {
1938 278 : DIR *d = NULL;
1939 278 : struct dirent *dp = NULL;
1940 : struct stat sb;
1941 278 : char fd_str[64] = { 0 };
1942 : int path_fd;
1943 : int rc;
1944 :
1945 278 : switch(parent_fd) {
1946 278 : case AT_FDCWD:
1947 278 : snprintf(fd_str, sizeof(fd_str), "CWD");
1948 278 : break;
1949 0 : default:
1950 0 : snprintf(fd_str, sizeof(fd_str), "fd=%d", parent_fd);
1951 0 : break;
1952 : }
1953 :
1954 : /* If path is absolute, parent_fd is ignored. */
1955 278 : PWRAP_LOG(PWRAP_LOG_TRACE,
1956 : "p_rmdirs_at removing %s at %s\n", path, fd_str);
1957 :
1958 278 : path_fd = openat(parent_fd,
1959 : path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
1960 278 : if (path_fd == -1) {
1961 0 : return -1;
1962 : }
1963 :
1964 278 : d = fdopendir(path_fd);
1965 278 : if (d == NULL) {
1966 0 : close(path_fd);
1967 0 : return -1;
1968 : }
1969 :
1970 1390 : while ((dp = readdir(d)) != NULL) {
1971 : /* skip '.' and '..' */
1972 1112 : if (dp->d_name[0] == '.' &&
1973 556 : (dp->d_name[1] == '\0' ||
1974 278 : (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) {
1975 556 : continue;
1976 : }
1977 :
1978 556 : rc = fstatat(path_fd, dp->d_name,
1979 : &sb, AT_SYMLINK_NOFOLLOW);
1980 556 : if (rc != 0) {
1981 0 : continue;
1982 : }
1983 :
1984 556 : if (S_ISDIR(sb.st_mode)) {
1985 0 : rc = p_rmdirs_at(dp->d_name, path_fd);
1986 : } else {
1987 556 : rc = unlinkat(path_fd, dp->d_name, 0);
1988 : }
1989 556 : if (rc != 0) {
1990 0 : continue;
1991 : }
1992 : }
1993 278 : closedir(d);
1994 :
1995 278 : rc = unlinkat(parent_fd, path, AT_REMOVEDIR);
1996 278 : if (rc != 0) {
1997 0 : rc = errno;
1998 0 : PWRAP_LOG(PWRAP_LOG_TRACE,
1999 : "cannot unlink %s error %d\n", path, rc);
2000 0 : return -1;
2001 : }
2002 :
2003 278 : return 0;
2004 : }
2005 :
2006 278 : static int p_rmdirs(const char *path)
2007 : {
2008 : /*
2009 : * If path is absolute, p_rmdirs_at ignores parent_fd.
2010 : * If it's relative, start from cwd.
2011 : */
2012 278 : return p_rmdirs_at(path, AT_FDCWD);
2013 : }
2014 :
2015 : /*
2016 : * This function is called when the library is unloaded and makes sure that
2017 : * resources are freed.
2018 : */
2019 314 : void pwrap_destructor(void)
2020 : {
2021 : const char *env;
2022 :
2023 314 : PWRAP_LOG(PWRAP_LOG_TRACE, "entering pwrap_destructor");
2024 :
2025 314 : if (pwrap.libpam.handle != NULL) {
2026 98 : dlclose(pwrap.libpam.handle);
2027 : }
2028 :
2029 314 : if (pwrap.libpam_so != NULL) {
2030 278 : free(pwrap.libpam_so);
2031 278 : pwrap.libpam_so = NULL;
2032 : }
2033 :
2034 314 : if (!pwrap.initialised) {
2035 36 : return;
2036 : }
2037 278 : pwrap.initialised = false;
2038 :
2039 278 : PWRAP_LOG(PWRAP_LOG_TRACE,
2040 : "destructor called for pam_wrapper dir %s",
2041 : pwrap.config_dir);
2042 278 : env = getenv("PAM_WRAPPER_KEEP_DIR");
2043 278 : if (env == NULL || env[0] != '1') {
2044 278 : p_rmdirs(pwrap.config_dir);
2045 : }
2046 :
2047 278 : if (pwrap.config_dir != NULL) {
2048 278 : free(pwrap.config_dir);
2049 278 : pwrap.config_dir = NULL;
2050 : }
2051 : }
|