libsmb: Fix destructor setup in unexpected.c
[Samba.git] / third_party / pam_wrapper / pam_wrapper.c
blob2db9bcca889ad3725871e8a5d0bcb70ce7a545a1
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 #include "config.h"
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>
38 #include <ftw.h>
40 #ifdef HAVE_SECURITY_PAM_APPL_H
41 #include <security/pam_appl.h>
42 #endif
43 #ifdef HAVE_SECURITY_PAM_MODULES_H
44 #include <security/pam_modules.h>
45 #endif
46 #ifdef HAVE_SECURITY_PAM_EXT_H
47 #include <security/pam_ext.h>
48 #endif
50 #include "pwrap_compat.h"
52 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
53 # define PWRAP_THREAD __thread
54 #else
55 # define PWRAP_THREAD
56 #endif
58 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
59 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
60 #else
61 #define CONSTRUCTOR_ATTRIBUTE
62 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
64 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
65 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
66 #else
67 #define DESTRUCTOR_ATTRIBUTE
68 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
70 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
71 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
72 #else /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
73 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
74 #endif /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
76 /* GCC have printf type attribute check. */
77 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
78 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
79 #else
80 #define PRINTF_ATTRIBUTE(a,b)
81 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
83 #ifndef SAFE_FREE
84 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
85 #endif
87 #ifndef discard_const
88 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
89 #endif
91 #ifndef discard_const_p
92 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
93 #endif
95 /*****************
96 * LOGGING
97 *****************/
99 enum pwrap_dbglvl_e {
100 PWRAP_LOG_ERROR = 0,
101 PWRAP_LOG_WARN,
102 PWRAP_LOG_DEBUG,
103 PWRAP_LOG_TRACE
106 static void pwrap_log(enum pwrap_dbglvl_e dbglvl,
107 const char *function,
108 const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
109 # define PWRAP_LOG(dbglvl, ...) pwrap_log((dbglvl), __func__, __VA_ARGS__)
111 static void pwrap_vlog(enum pwrap_dbglvl_e dbglvl,
112 const char *function,
113 const char *format,
114 va_list args) PRINTF_ATTRIBUTE(3, 0);
116 static void pwrap_vlog(enum pwrap_dbglvl_e dbglvl,
117 const char *function,
118 const char *format,
119 va_list args)
121 char buffer[1024];
122 const char *d;
123 unsigned int lvl = 0;
124 const char *prefix = "PWRAP";
126 d = getenv("PAM_WRAPPER_DEBUGLEVEL");
127 if (d != NULL) {
128 lvl = atoi(d);
131 if (lvl < dbglvl) {
132 return;
135 vsnprintf(buffer, sizeof(buffer), format, args);
137 switch (dbglvl) {
138 case PWRAP_LOG_ERROR:
139 prefix = "PWRAP_ERROR";
140 break;
141 case PWRAP_LOG_WARN:
142 prefix = "PWRAP_WARN";
143 break;
144 case PWRAP_LOG_DEBUG:
145 prefix = "PWRAP_DEBUG";
146 break;
147 case PWRAP_LOG_TRACE:
148 prefix = "PWRAP_TRACE";
149 break;
152 fprintf(stderr,
153 "%s(%d) - %s: %s\n",
154 prefix,
155 (int)getpid(),
156 function,
157 buffer);
160 static void pwrap_log(enum pwrap_dbglvl_e dbglvl,
161 const char *function,
162 const char *format, ...)
164 va_list va;
166 va_start(va, format);
167 pwrap_vlog(dbglvl, function, format, va);
168 va_end(va);
171 /*****************
172 * LIBC
173 *****************/
175 #define LIBPAM_NAME "libpam.so.0"
177 typedef int (*__libpam_pam_start)(const char *service_name,
178 const char *user,
179 const struct pam_conv *pam_conversation,
180 pam_handle_t **pamh);
182 typedef int (*__libpam_pam_end)(pam_handle_t *pamh, int pam_status);
184 typedef int (*__libpam_pam_authenticate)(pam_handle_t *pamh, int flags);
186 typedef int (*__libpam_pam_chauthtok)(pam_handle_t *pamh, int flags);
188 typedef int (*__libpam_pam_acct_mgmt)(pam_handle_t *pamh, int flags);
190 typedef int (*__libpam_pam_putenv)(pam_handle_t *pamh, const char *name_value);
192 typedef const char * (*__libpam_pam_getenv)(pam_handle_t *pamh, const char *name);
194 typedef char ** (*__libpam_pam_getenvlist)(pam_handle_t *pamh);
196 typedef int (*__libpam_pam_open_session)(pam_handle_t *pamh, int flags);
198 typedef int (*__libpam_pam_close_session)(pam_handle_t *pamh, int flags);
200 typedef int (*__libpam_pam_setcred)(pam_handle_t *pamh, int flags);
202 typedef int (*__libpam_pam_get_item)(const pam_handle_t *pamh,
203 int item_type,
204 const void **item);
206 typedef int (*__libpam_pam_set_item)(pam_handle_t *pamh,
207 int item_type,
208 const void *item);
210 typedef int (*__libpam_pam_get_data)(const pam_handle_t *pamh,
211 const char *module_data_name,
212 const void **data);
214 typedef int (*__libpam_pam_set_data)(pam_handle_t *pamh,
215 const char *module_data_name,
216 void *data,
217 void (*cleanup)(pam_handle_t *pamh,
218 void *data,
219 int error_status));
221 typedef int (*__libpam_pam_vprompt)(pam_handle_t *pamh,
222 int style,
223 char **response,
224 const char *fmt,
225 va_list args);
227 typedef const char * (*__libpam_pam_strerror)(pam_handle_t *pamh,
228 int errnum);
230 #ifdef HAVE_PAM_VSYSLOG
231 typedef void (*__libpam_pam_vsyslog)(const pam_handle_t *pamh,
232 int priority,
233 const char *fmt,
234 va_list args);
235 #endif
237 #define PWRAP_SYMBOL_ENTRY(i) \
238 union { \
239 __libpam_##i f; \
240 void *obj; \
241 } _libpam_##i
243 struct pwrap_libpam_symbols {
244 PWRAP_SYMBOL_ENTRY(pam_start);
245 PWRAP_SYMBOL_ENTRY(pam_end);
246 PWRAP_SYMBOL_ENTRY(pam_authenticate);
247 PWRAP_SYMBOL_ENTRY(pam_chauthtok);
248 PWRAP_SYMBOL_ENTRY(pam_acct_mgmt);
249 PWRAP_SYMBOL_ENTRY(pam_putenv);
250 PWRAP_SYMBOL_ENTRY(pam_getenv);
251 PWRAP_SYMBOL_ENTRY(pam_getenvlist);
252 PWRAP_SYMBOL_ENTRY(pam_open_session);
253 PWRAP_SYMBOL_ENTRY(pam_close_session);
254 PWRAP_SYMBOL_ENTRY(pam_setcred);
255 PWRAP_SYMBOL_ENTRY(pam_get_item);
256 PWRAP_SYMBOL_ENTRY(pam_set_item);
257 PWRAP_SYMBOL_ENTRY(pam_get_data);
258 PWRAP_SYMBOL_ENTRY(pam_set_data);
259 PWRAP_SYMBOL_ENTRY(pam_vprompt);
260 PWRAP_SYMBOL_ENTRY(pam_strerror);
261 #ifdef HAVE_PAM_VSYSLOG
262 PWRAP_SYMBOL_ENTRY(pam_vsyslog);
263 #endif
266 struct pwrap {
267 struct {
268 void *handle;
269 struct pwrap_libpam_symbols symbols;
270 } libpam;
272 bool enabled;
273 bool initialised;
274 char *config_dir;
275 char *libpam_so;
278 static struct pwrap pwrap;
280 /*********************************************************
281 * PWRAP PROTOTYPES
282 *********************************************************/
284 bool pam_wrapper_enabled(void);
285 void pwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
286 void pwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
288 /*********************************************************
289 * PWRAP LIBC LOADER FUNCTIONS
290 *********************************************************/
292 enum pwrap_lib {
293 PWRAP_LIBPAM,
296 static void *pwrap_load_lib_handle(enum pwrap_lib lib)
298 int flags = RTLD_LAZY;
299 void *handle = NULL;
301 #ifdef RTLD_DEEPBIND
302 flags |= RTLD_DEEPBIND;
303 #endif
305 switch (lib) {
306 case PWRAP_LIBPAM:
307 handle = pwrap.libpam.handle;
308 if (handle == NULL) {
309 handle = dlopen(pwrap.libpam_so, flags);
310 if (handle != NULL) {
311 PWRAP_LOG(PWRAP_LOG_DEBUG,
312 "Opened %s\n", pwrap.libpam_so);
313 pwrap.libpam.handle = handle;
314 break;
317 break;
320 if (handle == NULL) {
321 PWRAP_LOG(PWRAP_LOG_ERROR,
322 "Failed to dlopen library: %s\n",
323 dlerror());
324 exit(-1);
327 return handle;
330 static void *_pwrap_bind_symbol(enum pwrap_lib lib, const char *fn_name)
332 void *handle;
333 void *func;
335 handle = pwrap_load_lib_handle(lib);
337 func = dlsym(handle, fn_name);
338 if (func == NULL) {
339 PWRAP_LOG(PWRAP_LOG_ERROR,
340 "Failed to find %s: %s\n",
341 fn_name, dlerror());
342 exit(-1);
345 return func;
348 #define pwrap_bind_symbol_libpam(sym_name) \
349 if (pwrap.libpam.symbols._libpam_##sym_name.obj == NULL) { \
350 pwrap.libpam.symbols._libpam_##sym_name.obj = \
351 _pwrap_bind_symbol(PWRAP_LIBPAM, #sym_name); \
355 * IMPORTANT
357 * Functions especially from libpam need to be loaded individually, you can't
358 * load all at once or gdb will segfault at startup. The same applies to
359 * valgrind and has probably something todo with with the linker.
360 * So we need load each function at the point it is called the first time.
362 static int libpam_pam_start(const char *service_name,
363 const char *user,
364 const struct pam_conv *pam_conversation,
365 pam_handle_t **pamh)
367 pwrap_bind_symbol_libpam(pam_start);
369 return pwrap.libpam.symbols._libpam_pam_start.f(service_name,
370 user,
371 pam_conversation,
372 pamh);
375 static int libpam_pam_end(pam_handle_t *pamh, int pam_status)
377 pwrap_bind_symbol_libpam(pam_end);
379 return pwrap.libpam.symbols._libpam_pam_end.f(pamh, pam_status);
382 static int libpam_pam_authenticate(pam_handle_t *pamh, int flags)
384 pwrap_bind_symbol_libpam(pam_authenticate);
386 return pwrap.libpam.symbols._libpam_pam_authenticate.f(pamh, flags);
389 static int libpam_pam_chauthtok(pam_handle_t *pamh, int flags)
391 pwrap_bind_symbol_libpam(pam_chauthtok);
393 return pwrap.libpam.symbols._libpam_pam_chauthtok.f(pamh, flags);
396 static int libpam_pam_acct_mgmt(pam_handle_t *pamh, int flags)
398 pwrap_bind_symbol_libpam(pam_acct_mgmt);
400 return pwrap.libpam.symbols._libpam_pam_acct_mgmt.f(pamh, flags);
403 static int libpam_pam_putenv(pam_handle_t *pamh, const char *name_value)
405 pwrap_bind_symbol_libpam(pam_putenv);
407 return pwrap.libpam.symbols._libpam_pam_putenv.f(pamh, name_value);
410 static const char *libpam_pam_getenv(pam_handle_t *pamh, const char *name)
412 pwrap_bind_symbol_libpam(pam_getenv);
414 return pwrap.libpam.symbols._libpam_pam_getenv.f(pamh, name);
417 static char **libpam_pam_getenvlist(pam_handle_t *pamh)
419 pwrap_bind_symbol_libpam(pam_getenvlist);
421 return pwrap.libpam.symbols._libpam_pam_getenvlist.f(pamh);
424 static int libpam_pam_open_session(pam_handle_t *pamh, int flags)
426 pwrap_bind_symbol_libpam(pam_open_session);
428 return pwrap.libpam.symbols._libpam_pam_open_session.f(pamh, flags);
431 static int libpam_pam_close_session(pam_handle_t *pamh, int flags)
433 pwrap_bind_symbol_libpam(pam_close_session);
435 return pwrap.libpam.symbols._libpam_pam_close_session.f(pamh, flags);
438 static int libpam_pam_setcred(pam_handle_t *pamh, int flags)
440 pwrap_bind_symbol_libpam(pam_setcred);
442 return pwrap.libpam.symbols._libpam_pam_setcred.f(pamh, flags);
445 static int libpam_pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
447 pwrap_bind_symbol_libpam(pam_get_item);
449 return pwrap.libpam.symbols._libpam_pam_get_item.f(pamh, item_type, item);
452 static int libpam_pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
454 pwrap_bind_symbol_libpam(pam_set_item);
456 return pwrap.libpam.symbols._libpam_pam_set_item.f(pamh, item_type, item);
459 static int libpam_pam_get_data(const pam_handle_t *pamh,
460 const char *module_data_name,
461 const void **data)
463 pwrap_bind_symbol_libpam(pam_get_data);
465 return pwrap.libpam.symbols._libpam_pam_get_data.f(pamh,
466 module_data_name,
467 data);
470 static int libpam_pam_set_data(pam_handle_t *pamh,
471 const char *module_data_name,
472 void *data,
473 void (*cleanup)(pam_handle_t *pamh,
474 void *data,
475 int error_status))
477 pwrap_bind_symbol_libpam(pam_set_data);
479 return pwrap.libpam.symbols._libpam_pam_set_data.f(pamh,
480 module_data_name,
481 data,
482 cleanup);
485 static int libpam_pam_vprompt(pam_handle_t *pamh,
486 int style,
487 char **response,
488 const char *fmt,
489 va_list args)
491 pwrap_bind_symbol_libpam(pam_vprompt);
493 return pwrap.libpam.symbols._libpam_pam_vprompt.f(pamh,
494 style,
495 response,
496 fmt,
497 args);
500 #ifdef HAVE_PAM_STRERROR_CONST
501 static const char *libpam_pam_strerror(const pam_handle_t *pamh, int errnum)
502 #else
503 static const char *libpam_pam_strerror(pam_handle_t *pamh, int errnum)
504 #endif
506 pwrap_bind_symbol_libpam(pam_strerror);
508 return pwrap.libpam.symbols._libpam_pam_strerror.f(discard_const_p(pam_handle_t, pamh), errnum);
511 #if defined(HAVE_PAM_VSYSLOG) || defined(HAVE_PAM_SYSLOG)
512 static void libpam_pam_vsyslog(const pam_handle_t *pamh,
513 int priority,
514 const char *fmt,
515 va_list args)
517 #ifdef HAVE_PAM_VSYSLOG
518 pwrap_bind_symbol_libpam(pam_vsyslog);
520 pwrap.libpam.symbols._libpam_pam_vsyslog.f(pamh,
521 priority,
522 fmt,
523 args);
524 #endif
526 #endif
528 /*********************************************************
529 * PWRAP INIT
530 *********************************************************/
532 #define BUFFER_SIZE 32768
534 /* copy file from src to dst, overwrites dst */
535 static int p_copy(const char *src, const char *dst, const char *pdir, mode_t mode)
537 int srcfd = -1;
538 int dstfd = -1;
539 int rc = -1;
540 ssize_t bread, bwritten;
541 struct stat sb;
542 char buf[BUFFER_SIZE];
543 int cmp;
545 cmp = strcmp(src, dst);
546 if (cmp == 0) {
547 return -1;
550 srcfd = open(src, O_RDONLY, 0);
551 if (srcfd < 0) {
552 return -1;
555 if (mode == 0) {
556 rc = fstat(srcfd, &sb);
557 if (rc != 0) {
558 rc = -1;
559 goto out;
561 mode = sb.st_mode;
564 dstfd = open(dst, O_CREAT|O_WRONLY|O_TRUNC, mode);
565 if (dstfd < 0) {
566 rc = -1;
567 goto out;
570 for (;;) {
571 char *p;
572 bread = read(srcfd, buf, BUFFER_SIZE);
573 if (bread == 0) {
574 /* done */
575 break;
576 } else if (bread < 0) {
577 errno = EIO;
578 rc = -1;
579 goto out;
582 /* EXTRA UGLY HACK */
583 if (pdir != NULL) {
584 p = buf;
586 while (p < buf + BUFFER_SIZE) {
587 if (*p == '/') {
588 cmp = memcmp(p, "/etc/pam.d", 10);
589 if (cmp == 0) {
590 memcpy(p, pdir, 10);
593 p++;
597 bwritten = write(dstfd, buf, bread);
598 if (bwritten < 0) {
599 errno = EIO;
600 rc = -1;
601 goto out;
604 if (bread != bwritten) {
605 errno = EFAULT;
606 rc = -1;
607 goto out;
611 rc = 0;
612 out:
613 if (srcfd != -1) {
614 close(srcfd);
616 if (dstfd != -1) {
617 close(dstfd);
619 if (rc < 0) {
620 unlink(dst);
623 return rc;
626 /* Do not pass any flag if not defined */
627 #ifndef FTW_ACTIONRETVAL
628 #define FTW_ACTIONRETVAL 0
629 #endif
631 /* Action return values */
632 #ifndef FTW_STOP
633 #define FTW_STOP -1
634 #endif
636 #ifndef FTW_CONTINUE
637 #define FTW_CONTINUE 0
638 #endif
640 #ifndef FTW_SKIP_SUBTREE
641 #define FTW_SKIP_SUBTREE 0
642 #endif
644 static int copy_ftw(const char *fpath,
645 const struct stat *sb,
646 int typeflag,
647 struct FTW *ftwbuf)
649 int rc;
650 char buf[BUFFER_SIZE];
652 switch (typeflag) {
653 case FTW_D:
654 case FTW_DNR:
655 /* We want to copy the directories from this directory */
656 if (ftwbuf->level == 0) {
657 return FTW_CONTINUE;
659 return FTW_SKIP_SUBTREE;
660 case FTW_F:
661 break;
662 default:
663 return FTW_CONTINUE;
666 rc = snprintf(buf, BUFFER_SIZE, "%s/%s", pwrap.config_dir, fpath + ftwbuf->base);
667 if (rc >= BUFFER_SIZE) {
668 return FTW_STOP;
671 PWRAP_LOG(PWRAP_LOG_TRACE, "Copying %s", fpath);
672 rc = p_copy(fpath, buf, NULL, sb->st_mode);
673 if (rc != 0) {
674 return FTW_STOP;
677 return FTW_CONTINUE;
680 static int copy_confdir(const char *src)
682 int rc;
684 PWRAP_LOG(PWRAP_LOG_DEBUG,
685 "Copy config files from %s to %s",
686 src,
687 pwrap.config_dir);
688 rc = nftw(src, copy_ftw, 1, FTW_ACTIONRETVAL);
689 if (rc != 0) {
690 return -1;
693 return 0;
696 static int p_rmdirs(const char *path);
698 static void pwrap_clean_stale_dirs(const char *dir)
700 size_t len = strlen(dir);
701 char pidfile[len + 5];
702 ssize_t rc;
703 char buf[8] = {0};
704 long int tmp;
705 pid_t pid;
706 int fd;
708 snprintf(pidfile,
709 sizeof(pidfile),
710 "%s/pid",
711 dir);
713 /* read the pidfile */
714 fd = open(pidfile, O_RDONLY);
715 if (fd < 0) {
716 if (errno == ENOENT) {
717 PWRAP_LOG(PWRAP_LOG_TRACE,
718 "pidfile %s missing, nothing to do\n",
719 pidfile);
720 } else {
721 PWRAP_LOG(PWRAP_LOG_ERROR,
722 "Failed to open pidfile %s - error: %s",
723 pidfile, strerror(errno));
725 return;
728 rc = read(fd, buf, sizeof(buf));
729 close(fd);
730 if (rc < 0) {
731 PWRAP_LOG(PWRAP_LOG_ERROR,
732 "Failed to read pidfile %s - error: %s",
733 pidfile, strerror(errno));
734 return;
737 buf[sizeof(buf) - 1] = '\0';
739 tmp = strtol(buf, NULL, 10);
740 if (tmp == 0 || tmp > 0xFFFF || errno == ERANGE) {
741 PWRAP_LOG(PWRAP_LOG_ERROR,
742 "Failed to parse pid, buf=%s",
743 buf);
744 return;
747 pid = (pid_t)(tmp & 0xFFFF);
749 rc = kill(pid, 0);
750 if (rc == -1) {
751 PWRAP_LOG(PWRAP_LOG_TRACE,
752 "Remove stale pam_wrapper dir: %s",
753 dir);
754 p_rmdirs(dir);
757 return;
760 static void pwrap_init(void)
762 char tmp_config_dir[] = "/tmp/pam.X";
763 size_t len = strlen(tmp_config_dir);
764 const char *env;
765 uint32_t i;
766 int rc;
767 char pam_library[128] = { 0 };
768 char libpam_path[1024] = { 0 };
769 ssize_t ret;
770 FILE *pidfile;
771 char pidfile_path[1024] = { 0 };
773 if (!pam_wrapper_enabled()) {
774 return;
777 if (pwrap.initialised) {
778 return;
781 PWRAP_LOG(PWRAP_LOG_DEBUG, "Initialize pam_wrapper");
783 for (i = 0; i < 36; i++) {
784 struct stat sb;
785 char c;
787 if (i < 10) {
788 c = (char)(i + 48);
789 } else {
790 c = (char)(i + 87);
793 tmp_config_dir[len - 1] = c;
794 rc = lstat(tmp_config_dir, &sb);
795 if (rc == 0) {
796 PWRAP_LOG(PWRAP_LOG_TRACE,
797 "Check if pam_wrapper dir %s is a "
798 "stale directory",
799 tmp_config_dir);
800 pwrap_clean_stale_dirs(tmp_config_dir);
801 continue;
802 } else if (errno == ENOENT) {
803 break;
807 if (i == 36) {
808 PWRAP_LOG(PWRAP_LOG_ERROR,
809 "Failed to find a possible path to create "
810 "pam_wrapper config dir: %s",
811 tmp_config_dir);
812 exit(1);
815 pwrap.config_dir = strdup(tmp_config_dir);
816 if (pwrap.config_dir == NULL) {
817 PWRAP_LOG(PWRAP_LOG_ERROR,
818 "No memory");
819 exit(1);
821 PWRAP_LOG(PWRAP_LOG_TRACE,
822 "pam_wrapper config dir: %s",
823 tmp_config_dir);
825 rc = mkdir(pwrap.config_dir, 0755);
826 if (rc != 0) {
827 PWRAP_LOG(PWRAP_LOG_ERROR,
828 "Failed to create pam_wrapper config dir: %s - %s",
829 tmp_config_dir, strerror(errno));
832 /* Create file with the PID of the the process */
833 ret = snprintf(pidfile_path, sizeof(pidfile_path),
834 "%s/pid", pwrap.config_dir);
835 if (ret < 0) {
836 p_rmdirs(pwrap.config_dir);
837 exit(1);
840 pidfile = fopen(pidfile_path, "w");
841 if (pidfile == NULL) {
842 p_rmdirs(pwrap.config_dir);
843 exit(1);
846 rc = fprintf(pidfile, "%d", getpid());
847 fclose(pidfile);
848 if (rc <= 0) {
849 p_rmdirs(pwrap.config_dir);
850 exit(1);
853 /* create lib subdirectory */
854 snprintf(libpam_path,
855 sizeof(libpam_path),
856 "%s/lib",
857 pwrap.config_dir);
859 rc = mkdir(libpam_path, 0755);
860 if (rc != 0) {
861 PWRAP_LOG(PWRAP_LOG_ERROR,
862 "Failed to create pam_wrapper config dir: %s - %s",
863 tmp_config_dir, strerror(errno));
864 p_rmdirs(pwrap.config_dir);
865 exit(1);
868 snprintf(libpam_path,
869 sizeof(libpam_path),
870 "%s/lib/%s",
871 pwrap.config_dir,
872 LIBPAM_NAME);
874 pwrap.libpam_so = strdup(libpam_path);
875 if (pwrap.libpam_so == NULL) {
876 PWRAP_LOG(PWRAP_LOG_ERROR, "No memory");
877 p_rmdirs(pwrap.config_dir);
878 exit(1);
881 /* copy libpam.so.0 */
882 snprintf(libpam_path, sizeof(libpam_path), "%s", PAM_LIBRARY);
883 PWRAP_LOG(PWRAP_LOG_TRACE,
884 "PAM path: %s",
885 libpam_path);
887 ret = readlink(libpam_path, pam_library, sizeof(pam_library) - 1);
888 PWRAP_LOG(PWRAP_LOG_TRACE,
889 "PAM library: %s",
890 pam_library);
891 if (ret <= 0) {
892 PWRAP_LOG(PWRAP_LOG_ERROR, "Failed to read %s link", LIBPAM_NAME);
893 p_rmdirs(pwrap.config_dir);
894 exit(1);
897 if (pam_library[0] == '/') {
898 snprintf(libpam_path,
899 sizeof(libpam_path),
900 "%s",
901 pam_library);
902 } else {
903 char libpam_path_cp[sizeof(libpam_path)];
904 char *dname;
906 strncpy(libpam_path_cp, libpam_path, sizeof(libpam_path_cp));
907 libpam_path_cp[sizeof(libpam_path_cp) - 1] = '\0';
909 dname = dirname(libpam_path_cp);
910 if (dname == NULL) {
911 PWRAP_LOG(PWRAP_LOG_ERROR,
912 "No directory component in %s", libpam_path);
913 p_rmdirs(pwrap.config_dir);
914 exit(1);
917 snprintf(libpam_path,
918 sizeof(libpam_path),
919 "%s/%s",
920 dname,
921 pam_library);
923 PWRAP_LOG(PWRAP_LOG_TRACE, "Reconstructed PAM path: %s", libpam_path);
925 PWRAP_LOG(PWRAP_LOG_DEBUG, "Copy %s to %s", libpam_path, pwrap.libpam_so);
926 rc = p_copy(libpam_path, pwrap.libpam_so, pwrap.config_dir, 0644);
927 if (rc != 0) {
928 PWRAP_LOG(PWRAP_LOG_ERROR,
929 "Failed to copy %s - error: %s",
930 LIBPAM_NAME,
931 strerror(errno));
932 p_rmdirs(pwrap.config_dir);
933 exit(1);
936 pwrap.initialised = true;
938 env = getenv("PAM_WRAPPER_SERVICE_DIR");
939 if (env == NULL) {
940 PWRAP_LOG(PWRAP_LOG_ERROR, "No config file");
941 p_rmdirs(pwrap.config_dir);
942 exit(1);
945 rc = copy_confdir(env);
946 if (rc != 0) {
947 PWRAP_LOG(PWRAP_LOG_ERROR, "Failed to copy config files");
948 p_rmdirs(pwrap.config_dir);
949 exit(1);
952 setenv("PAM_WRAPPER_RUNTIME_DIR", pwrap.config_dir, 1);
954 PWRAP_LOG(PWRAP_LOG_DEBUG, "Successfully initialized pam_wrapper");
957 bool pam_wrapper_enabled(void)
959 const char *env;
961 pwrap.enabled = false;
963 env = getenv("PAM_WRAPPER");
964 if (env != NULL && env[0] == '1') {
965 pwrap.enabled = true;
968 if (pwrap.enabled) {
969 pwrap.enabled = false;
971 env = getenv("PAM_WRAPPER_SERVICE_DIR");
972 if (env != NULL && env[0] != '\0') {
973 pwrap.enabled = true;
977 return pwrap.enabled;
980 /****************************
981 * CONSTRUCTOR
982 ***************************/
983 void pwrap_constructor(void)
986 * Here is safe place to call pwrap_init() and initialize data
987 * for main process.
989 pwrap_init();
993 #ifdef HAVE_OPENPAM
994 static int pwrap_openpam_start(const char *service_name,
995 const char *user,
996 const struct pam_conv *pam_conversation,
997 pam_handle_t **pamh)
999 int rv;
1000 char fullpath[1024];
1002 rv = openpam_set_feature(OPENPAM_RESTRICT_SERVICE_NAME, 0);
1003 if (rv != PAM_SUCCESS) {
1004 PWRAP_LOG(PWRAP_LOG_ERROR,
1005 "Cannot disable OPENPAM_RESTRICT_SERVICE_NAME");
1006 return rv;
1009 rv = openpam_set_feature(OPENPAM_RESTRICT_MODULE_NAME, 0);
1010 if (rv != PAM_SUCCESS) {
1011 PWRAP_LOG(PWRAP_LOG_ERROR,
1012 "Cannot disable OPENPAM_RESTRICT_MODULE_NAME");
1013 return rv;
1016 rv = openpam_set_feature(OPENPAM_VERIFY_MODULE_FILE, 0);
1017 if (rv != PAM_SUCCESS) {
1018 PWRAP_LOG(PWRAP_LOG_ERROR,
1019 "Cannot disable OPENPAM_VERIFY_MODULE_FILE");
1020 return rv;
1023 rv = openpam_set_feature(OPENPAM_VERIFY_POLICY_FILE, 0);
1024 if (rv != PAM_SUCCESS) {
1025 PWRAP_LOG(PWRAP_LOG_ERROR,
1026 "Cannot disable OPENPAM_VERIFY_POLICY_FILE");
1027 return rv;
1030 snprintf(fullpath,
1031 sizeof(fullpath),
1032 "%s/%s",
1033 pwrap.config_dir,
1034 service_name);
1036 return libpam_pam_start(fullpath,
1037 user,
1038 pam_conversation,
1039 pamh);
1041 #endif
1043 static int pwrap_pam_start(const char *service_name,
1044 const char *user,
1045 const struct pam_conv *pam_conversation,
1046 pam_handle_t **pamh)
1048 PWRAP_LOG(PWRAP_LOG_TRACE,
1049 "pam_start service=%s, user=%s",
1050 service_name,
1051 user);
1053 #ifdef HAVE_OPENPAM
1054 return pwrap_openpam_start(service_name,
1055 user,
1056 pam_conversation,
1057 pamh);
1058 #else
1059 return libpam_pam_start(service_name,
1060 user,
1061 pam_conversation,
1062 pamh);
1063 #endif
1067 int pam_start(const char *service_name,
1068 const char *user,
1069 const struct pam_conv *pam_conversation,
1070 pam_handle_t **pamh)
1072 return pwrap_pam_start(service_name, user, pam_conversation, pamh);
1075 static int pwrap_pam_end(pam_handle_t *pamh, int pam_status)
1077 PWRAP_LOG(PWRAP_LOG_TRACE, "pam_end status=%d", pam_status);
1078 return libpam_pam_end(pamh, pam_status);
1082 int pam_end(pam_handle_t *pamh, int pam_status)
1084 return pwrap_pam_end(pamh, pam_status);
1087 static int pwrap_pam_authenticate(pam_handle_t *pamh, int flags)
1089 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_authenticate flags=%d", flags);
1090 return libpam_pam_authenticate(pamh, flags);
1093 int pam_authenticate(pam_handle_t *pamh, int flags)
1095 return pwrap_pam_authenticate(pamh, flags);
1098 static int pwrap_pam_chauthtok(pam_handle_t *pamh, int flags)
1100 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_chauthtok flags=%d", flags);
1101 return libpam_pam_chauthtok(pamh, flags);
1104 int pam_chauthtok(pam_handle_t *pamh, int flags)
1106 return pwrap_pam_chauthtok(pamh, flags);
1109 static int pwrap_pam_acct_mgmt(pam_handle_t *pamh, int flags)
1111 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_acct_mgmt flags=%d", flags);
1112 return libpam_pam_acct_mgmt(pamh, flags);
1115 int pam_acct_mgmt(pam_handle_t *pamh, int flags)
1117 return pwrap_pam_acct_mgmt(pamh, flags);
1120 static int pwrap_pam_putenv(pam_handle_t *pamh, const char *name_value)
1122 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_putenv name_value=%s", name_value);
1123 return libpam_pam_putenv(pamh, name_value);
1126 int pam_putenv(pam_handle_t *pamh, const char *name_value)
1128 return pwrap_pam_putenv(pamh, name_value);
1131 static const char *pwrap_pam_getenv(pam_handle_t *pamh, const char *name)
1133 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_getenv name=%s", name);
1134 return libpam_pam_getenv(pamh, name);
1137 const char *pam_getenv(pam_handle_t *pamh, const char *name)
1139 return pwrap_pam_getenv(pamh, name);
1142 static char **pwrap_pam_getenvlist(pam_handle_t *pamh)
1144 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_getenvlist called");
1145 return libpam_pam_getenvlist(pamh);
1148 char **pam_getenvlist(pam_handle_t *pamh)
1150 return pwrap_pam_getenvlist(pamh);
1153 static int pwrap_pam_open_session(pam_handle_t *pamh, int flags)
1155 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_open_session flags=%d", flags);
1156 return libpam_pam_open_session(pamh, flags);
1159 int pam_open_session(pam_handle_t *pamh, int flags)
1161 return pwrap_pam_open_session(pamh, flags);
1164 static int pwrap_pam_close_session(pam_handle_t *pamh, int flags)
1166 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_close_session flags=%d", flags);
1167 return libpam_pam_close_session(pamh, flags);
1170 int pam_close_session(pam_handle_t *pamh, int flags)
1172 return pwrap_pam_close_session(pamh, flags);
1175 static int pwrap_pam_setcred(pam_handle_t *pamh, int flags)
1177 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_setcred flags=%d", flags);
1178 return libpam_pam_setcred(pamh, flags);
1181 int pam_setcred(pam_handle_t *pamh, int flags)
1183 return pwrap_pam_setcred(pamh, flags);
1186 static const char *pwrap_get_service(const char *libpam_service)
1188 #ifdef HAVE_OPENPAM
1189 const char *service_name;
1191 PWRAP_LOG(PWRAP_LOG_TRACE,
1192 "internal PAM_SERVICE=%s", libpam_service);
1193 service_name = strrchr(libpam_service, '/');
1194 if (service_name != NULL && service_name[0] == '/') {
1195 service_name++;
1197 PWRAP_LOG(PWRAP_LOG_TRACE,
1198 "PAM_SERVICE=%s", service_name);
1199 return service_name;
1200 #else
1201 return libpam_service;
1202 #endif
1205 static int pwrap_pam_get_item(const pam_handle_t *pamh,
1206 int item_type,
1207 const void **item)
1209 int rc;
1210 const char *svc;
1212 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_get_item called");
1214 rc = libpam_pam_get_item(pamh, item_type, item);
1216 if (rc == PAM_SUCCESS) {
1217 switch(item_type) {
1218 case PAM_USER:
1219 PWRAP_LOG(PWRAP_LOG_TRACE,
1220 "pwrap_get_item PAM_USER=%s",
1221 (const char *)*item);
1222 break;
1223 case PAM_SERVICE:
1224 svc = pwrap_get_service((const char *) *item);
1226 PWRAP_LOG(PWRAP_LOG_TRACE,
1227 "pwrap_get_item PAM_SERVICE=%s",
1228 svc);
1229 *item = svc;
1230 break;
1231 case PAM_USER_PROMPT:
1232 PWRAP_LOG(PWRAP_LOG_TRACE,
1233 "pwrap_get_item PAM_USER_PROMPT=%s",
1234 (const char *)*item);
1235 break;
1236 case PAM_TTY:
1237 PWRAP_LOG(PWRAP_LOG_TRACE,
1238 "pwrap_get_item PAM_TTY=%s",
1239 (const char *)*item);
1240 break;
1241 case PAM_RUSER:
1242 PWRAP_LOG(PWRAP_LOG_TRACE,
1243 "pwrap_get_item PAM_RUSER=%s",
1244 (const char *)*item);
1245 break;
1246 case PAM_RHOST:
1247 PWRAP_LOG(PWRAP_LOG_TRACE,
1248 "pwrap_get_item PAM_RHOST=%s",
1249 (const char *)*item);
1250 break;
1251 case PAM_AUTHTOK:
1252 PWRAP_LOG(PWRAP_LOG_TRACE,
1253 "pwrap_get_item PAM_AUTHTOK=%s",
1254 (const char *)*item);
1255 break;
1256 case PAM_OLDAUTHTOK:
1257 PWRAP_LOG(PWRAP_LOG_TRACE,
1258 "pwrap_get_item PAM_OLDAUTHTOK=%s",
1259 (const char *)*item);
1260 break;
1261 case PAM_CONV:
1262 PWRAP_LOG(PWRAP_LOG_TRACE,
1263 "pwrap_get_item PAM_CONV=%p",
1264 (const void *)*item);
1265 break;
1266 default:
1267 PWRAP_LOG(PWRAP_LOG_TRACE,
1268 "pwrap_get_item item_type=%d item=%p",
1269 item_type, (const void *)*item);
1270 break;
1272 } else {
1273 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_get_item failed rc=%d", rc);
1276 return rc;
1279 int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
1281 return pwrap_pam_get_item(pamh, item_type, item);
1284 static int pwrap_pam_set_item(pam_handle_t *pamh,
1285 int item_type,
1286 const void *item)
1288 int rc;
1290 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_set_item called");
1292 rc = libpam_pam_set_item(pamh, item_type, item);
1293 if (rc == PAM_SUCCESS) {
1294 switch(item_type) {
1295 case PAM_USER:
1296 PWRAP_LOG(PWRAP_LOG_TRACE,
1297 "pwrap_set_item PAM_USER=%s",
1298 (const char *)item);
1299 break;
1300 case PAM_SERVICE:
1301 PWRAP_LOG(PWRAP_LOG_TRACE,
1302 "pwrap_set_item PAM_SERVICE=%s",
1303 (const char *)item);
1304 break;
1305 case PAM_USER_PROMPT:
1306 PWRAP_LOG(PWRAP_LOG_TRACE,
1307 "pwrap_set_item PAM_USER_PROMPT=%s",
1308 (const char *)item);
1309 break;
1310 case PAM_TTY:
1311 PWRAP_LOG(PWRAP_LOG_TRACE,
1312 "pwrap_set_item PAM_TTY=%s",
1313 (const char *)item);
1314 break;
1315 case PAM_RUSER:
1316 PWRAP_LOG(PWRAP_LOG_TRACE,
1317 "pwrap_set_item PAM_RUSER=%s",
1318 (const char *)item);
1319 break;
1320 case PAM_RHOST:
1321 PWRAP_LOG(PWRAP_LOG_TRACE,
1322 "pwrap_set_item PAM_RHOST=%s",
1323 (const char *)item);
1324 break;
1325 case PAM_AUTHTOK:
1326 PWRAP_LOG(PWRAP_LOG_TRACE,
1327 "pwrap_set_item PAM_AUTHTOK=%s",
1328 (const char *)item);
1329 break;
1330 case PAM_OLDAUTHTOK:
1331 PWRAP_LOG(PWRAP_LOG_TRACE,
1332 "pwrap_set_item PAM_OLDAUTHTOK=%s",
1333 (const char *)item);
1334 break;
1335 case PAM_CONV:
1336 PWRAP_LOG(PWRAP_LOG_TRACE,
1337 "pwrap_set_item PAM_CONV=%p",
1338 item);
1339 break;
1340 default:
1341 PWRAP_LOG(PWRAP_LOG_TRACE,
1342 "pwrap_set_item item_type=%d item=%p",
1343 item_type, item);
1344 break;
1346 } else {
1347 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_set_item failed rc=%d", rc);
1350 return rc;
1353 int pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
1355 return pwrap_pam_set_item(pamh, item_type, item);
1358 static int pwrap_pam_get_data(const pam_handle_t *pamh,
1359 const char *module_data_name,
1360 const void **data)
1362 PWRAP_LOG(PWRAP_LOG_TRACE,
1363 "pwrap_get_data module_data_name=%s", module_data_name);
1364 return libpam_pam_get_data(pamh, module_data_name, data);
1367 int pam_get_data(const pam_handle_t *pamh,
1368 const char *module_data_name,
1369 const void **data)
1371 return pwrap_pam_get_data(pamh, module_data_name, data);
1374 static int pwrap_pam_set_data(pam_handle_t *pamh,
1375 const char *module_data_name,
1376 void *data,
1377 void (*cleanup)(pam_handle_t *pamh,
1378 void *data,
1379 int error_status))
1381 PWRAP_LOG(PWRAP_LOG_TRACE,
1382 "pwrap_set_data module_data_name=%s data=%p",
1383 module_data_name, data);
1384 return libpam_pam_set_data(pamh, module_data_name, data, cleanup);
1387 int pam_set_data(pam_handle_t *pamh,
1388 const char *module_data_name,
1389 void *data,
1390 void (*cleanup)(pam_handle_t *pamh,
1391 void *data,
1392 int error_status))
1394 return pwrap_pam_set_data(pamh, module_data_name, data, cleanup);
1397 #ifdef HAVE_PAM_VPROMPT_CONST
1398 static int pwrap_pam_vprompt(const pam_handle_t *pamh,
1399 #else
1400 static int pwrap_pam_vprompt(pam_handle_t *pamh,
1401 #endif
1402 int style,
1403 char **response,
1404 const char *fmt,
1405 va_list args)
1407 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_vprompt style=%d", style);
1408 return libpam_pam_vprompt(discard_const_p(pam_handle_t, pamh),
1409 style,
1410 response,
1411 fmt,
1412 args);
1415 #ifdef HAVE_PAM_VPROMPT_CONST
1416 int pam_vprompt(const pam_handle_t *pamh,
1417 int style,
1418 char **response,
1419 const char *fmt,
1420 va_list args)
1421 #else
1422 int pam_vprompt(pam_handle_t *pamh,
1423 int style,
1424 char **response,
1425 const char *fmt,
1426 va_list args)
1427 #endif
1429 return pwrap_pam_vprompt(discard_const_p(pam_handle_t, pamh),
1430 style,
1431 response,
1432 fmt,
1433 args);
1436 #ifdef HAVE_PAM_PROMPT_CONST
1437 int pam_prompt(const pam_handle_t *pamh,
1438 int style,
1439 char **response,
1440 const char *fmt, ...)
1441 #else
1442 int pam_prompt(pam_handle_t *pamh,
1443 int style,
1444 char **response,
1445 const char *fmt, ...)
1446 #endif
1448 va_list args;
1449 int rv;
1451 va_start(args, fmt);
1452 rv = pwrap_pam_vprompt(discard_const_p(pam_handle_t, pamh),
1453 style,
1454 response,
1455 fmt,
1456 args);
1457 va_end(args);
1459 return rv;
1462 #ifdef HAVE_PAM_STRERROR_CONST
1463 static const char *pwrap_pam_strerror(const pam_handle_t *pamh, int errnum)
1464 #else
1465 static const char *pwrap_pam_strerror(pam_handle_t *pamh, int errnum)
1466 #endif
1468 const char *str;
1470 pwrap_init();
1472 PWRAP_LOG(PWRAP_LOG_TRACE, "pam_strerror errnum=%d", errnum);
1474 str = libpam_pam_strerror(discard_const_p(pam_handle_t, pamh),
1475 errnum);
1477 PWRAP_LOG(PWRAP_LOG_TRACE, "pam_strerror error=%s", str);
1479 return str;
1482 #ifdef HAVE_PAM_STRERROR_CONST
1483 const char *pam_strerror(const pam_handle_t *pamh, int errnum)
1484 #else
1485 const char *pam_strerror(pam_handle_t *pamh, int errnum)
1486 #endif
1488 return pwrap_pam_strerror(discard_const_p(pam_handle_t, pamh),
1489 errnum);
1492 #if defined(HAVE_PAM_VSYSLOG) || defined(HAVE_PAM_SYSLOG)
1494 static void pwrap_pam_vsyslog(const pam_handle_t *pamh,
1495 int priority,
1496 const char *fmt,
1497 va_list args) PRINTF_ATTRIBUTE(3, 0);
1499 static void pwrap_pam_vsyslog(const pam_handle_t *pamh,
1500 int priority,
1501 const char *fmt,
1502 va_list args)
1504 const char *d;
1505 char syslog_str[32] = {0};
1506 enum pwrap_dbglvl_e dbglvl = PWRAP_LOG_TRACE;
1508 PWRAP_LOG(PWRAP_LOG_TRACE, "pwrap_pam_vsyslog called");
1510 d = getenv("PAM_WRAPPER_USE_SYSLOG");
1511 if (d != NULL && d[0] == '1') {
1512 libpam_pam_vsyslog(pamh, priority, fmt, args);
1513 return;
1516 switch(priority) {
1517 case 0: /* LOG_EMERG */
1518 case 1: /* LOG_ALERT */
1519 case 2: /* LOG_CRIT */
1520 case 3: /* LOG_ERR */
1521 dbglvl = PWRAP_LOG_ERROR;
1522 break;
1523 case 4: /* LOG_WARN */
1524 dbglvl = PWRAP_LOG_WARN;
1525 break;
1526 case 5: /* LOG_NOTICE */
1527 case 6: /* LOG_INFO */
1528 case 7: /* LOG_DEBUG */
1529 dbglvl = PWRAP_LOG_DEBUG;
1530 break;
1531 default:
1532 dbglvl = PWRAP_LOG_TRACE;
1533 break;
1536 snprintf(syslog_str, sizeof(syslog_str), "SYSLOG(%d)", priority);
1538 pwrap_vlog(dbglvl, syslog_str, fmt, args);
1540 #endif /* defined(HAVE_PAM_VSYSLOG) || defined(HAVE_PAM_SYSLOG) */
1542 #ifdef HAVE_PAM_VSYSLOG
1543 void pam_vsyslog(const pam_handle_t *pamh,
1544 int priority,
1545 const char *fmt,
1546 va_list args)
1548 pwrap_pam_vsyslog(pamh, priority, fmt, args);
1550 #endif
1552 #ifdef HAVE_PAM_SYSLOG
1553 void pam_syslog(const pam_handle_t *pamh,
1554 int priority,
1555 const char *fmt, ...)
1557 va_list args;
1559 va_start(args, fmt);
1560 pwrap_pam_vsyslog(pamh, priority, fmt, args);
1561 va_end(args);
1563 #endif
1565 /* This might be called by pam_end() running with sshd */
1566 int audit_open(void);
1567 int audit_open(void)
1570 * Tell the application that the kernel doesn't
1571 * have audit compiled in.
1573 errno = EPROTONOSUPPORT;
1574 return -1;
1577 /* Disable BSD auditing */
1578 int cannot_audit(int x);
1579 int cannot_audit(int x)
1581 (void) x;
1583 return 1;
1586 /****************************
1587 * DESTRUCTOR
1588 ***************************/
1590 static int p_rmdirs_at(const char *path, int parent_fd)
1592 DIR *d;
1593 struct dirent *dp;
1594 struct stat sb;
1595 int path_fd;
1596 int rc;
1598 /* If path is absolute, parent_fd is ignored. */
1599 PWRAP_LOG(PWRAP_LOG_TRACE,
1600 "p_rmdirs_at removing %s at %d\n", path, parent_fd);
1602 path_fd = openat(parent_fd,
1603 path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
1604 if (path_fd == -1) {
1605 return -1;
1608 d = fdopendir(path_fd);
1609 if (d == NULL) {
1610 close(path_fd);
1611 return -1;
1614 while ((dp = readdir(d)) != NULL) {
1615 /* skip '.' and '..' */
1616 if (dp->d_name[0] == '.' &&
1617 (dp->d_name[1] == '\0' ||
1618 (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) {
1619 continue;
1622 rc = fstatat(path_fd, dp->d_name,
1623 &sb, AT_SYMLINK_NOFOLLOW);
1624 if (rc != 0) {
1625 continue;
1628 if (S_ISDIR(sb.st_mode)) {
1629 rc = p_rmdirs_at(dp->d_name, path_fd);
1630 } else {
1631 rc = unlinkat(path_fd, dp->d_name, 0);
1633 if (rc != 0) {
1634 continue;
1637 closedir(d);
1639 rc = unlinkat(parent_fd, path, AT_REMOVEDIR);
1640 if (rc != 0) {
1641 rc = errno;
1642 PWRAP_LOG(PWRAP_LOG_TRACE,
1643 "cannot unlink %s error %d\n", path, rc);
1644 return -1;
1647 return 0;
1650 static int p_rmdirs(const char *path)
1653 * If path is absolute, p_rmdirs_at ignores parent_fd.
1654 * If it's relative, start from cwd.
1656 return p_rmdirs_at(path, AT_FDCWD);
1660 * This function is called when the library is unloaded and makes sure that
1661 * resources are freed.
1663 void pwrap_destructor(void)
1665 const char *env;
1667 PWRAP_LOG(PWRAP_LOG_TRACE, "entering pwrap_destructor");
1669 if (pwrap.libpam.handle != NULL) {
1670 dlclose(pwrap.libpam.handle);
1673 if (pwrap.libpam_so != NULL) {
1674 free(pwrap.libpam_so);
1675 pwrap.libpam_so = NULL;
1678 if (!pwrap.initialised) {
1679 return;
1682 PWRAP_LOG(PWRAP_LOG_TRACE,
1683 "destructor called for pam_wrapper dir %s",
1684 pwrap.config_dir);
1685 env = getenv("PAM_WRAPPER_KEEP_DIR");
1686 if (env == NULL || env[0] != '1') {
1687 p_rmdirs(pwrap.config_dir);
1690 if (pwrap.config_dir != NULL) {
1691 free(pwrap.config_dir);
1692 pwrap.config_dir = NULL;