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/>.
28 #include <sys/types.h>
40 #ifdef HAVE_SECURITY_PAM_APPL_H
41 #include <security/pam_appl.h>
43 #ifdef HAVE_SECURITY_PAM_MODULES_H
44 #include <security/pam_modules.h>
46 #ifdef HAVE_SECURITY_PAM_EXT_H
47 #include <security/pam_ext.h>
50 #include "pwrap_compat.h"
52 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
53 # define PWRAP_THREAD __thread
58 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
59 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
61 #define CONSTRUCTOR_ATTRIBUTE
62 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
64 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
65 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
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)))
80 #define PRINTF_ATTRIBUTE(a,b)
81 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
84 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
88 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
91 #ifndef discard_const_p
92 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
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
,
114 va_list args
) PRINTF_ATTRIBUTE(3, 0);
116 static void pwrap_vlog(enum pwrap_dbglvl_e dbglvl
,
117 const char *function
,
123 unsigned int lvl
= 0;
124 const char *prefix
= "PWRAP";
126 d
= getenv("PAM_WRAPPER_DEBUGLEVEL");
135 vsnprintf(buffer
, sizeof(buffer
), format
, args
);
138 case PWRAP_LOG_ERROR
:
139 prefix
= "PWRAP_ERROR";
142 prefix
= "PWRAP_WARN";
144 case PWRAP_LOG_DEBUG
:
145 prefix
= "PWRAP_DEBUG";
147 case PWRAP_LOG_TRACE
:
148 prefix
= "PWRAP_TRACE";
160 static void pwrap_log(enum pwrap_dbglvl_e dbglvl
,
161 const char *function
,
162 const char *format
, ...)
166 va_start(va
, format
);
167 pwrap_vlog(dbglvl
, function
, format
, va
);
175 #define LIBPAM_NAME "libpam.so.0"
177 typedef int (*__libpam_pam_start
)(const char *service_name
,
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
,
206 typedef int (*__libpam_pam_set_item
)(pam_handle_t
*pamh
,
210 typedef int (*__libpam_pam_get_data
)(const pam_handle_t
*pamh
,
211 const char *module_data_name
,
214 typedef int (*__libpam_pam_set_data
)(pam_handle_t
*pamh
,
215 const char *module_data_name
,
217 void (*cleanup
)(pam_handle_t
*pamh
,
221 typedef int (*__libpam_pam_vprompt
)(pam_handle_t
*pamh
,
227 typedef const char * (*__libpam_pam_strerror
)(pam_handle_t
*pamh
,
230 #ifdef HAVE_PAM_VSYSLOG
231 typedef void (*__libpam_pam_vsyslog
)(const pam_handle_t
*pamh
,
237 #define PWRAP_SYMBOL_ENTRY(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
);
269 struct pwrap_libpam_symbols symbols
;
278 static struct pwrap pwrap
;
280 /*********************************************************
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 *********************************************************/
296 static void *pwrap_load_lib_handle(enum pwrap_lib lib
)
298 int flags
= RTLD_LAZY
;
302 flags
|= RTLD_DEEPBIND
;
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
;
320 if (handle
== NULL
) {
321 PWRAP_LOG(PWRAP_LOG_ERROR
,
322 "Failed to dlopen library: %s\n",
330 static void *_pwrap_bind_symbol(enum pwrap_lib lib
, const char *fn_name
)
335 handle
= pwrap_load_lib_handle(lib
);
337 func
= dlsym(handle
, fn_name
);
339 PWRAP_LOG(PWRAP_LOG_ERROR
,
340 "Failed to find %s: %s\n",
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); \
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
,
364 const struct pam_conv
*pam_conversation
,
367 pwrap_bind_symbol_libpam(pam_start
);
369 return pwrap
.libpam
.symbols
._libpam_pam_start
.f(service_name
,
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
,
463 pwrap_bind_symbol_libpam(pam_get_data
);
465 return pwrap
.libpam
.symbols
._libpam_pam_get_data
.f(pamh
,
470 static int libpam_pam_set_data(pam_handle_t
*pamh
,
471 const char *module_data_name
,
473 void (*cleanup
)(pam_handle_t
*pamh
,
477 pwrap_bind_symbol_libpam(pam_set_data
);
479 return pwrap
.libpam
.symbols
._libpam_pam_set_data
.f(pamh
,
485 static int libpam_pam_vprompt(pam_handle_t
*pamh
,
491 pwrap_bind_symbol_libpam(pam_vprompt
);
493 return pwrap
.libpam
.symbols
._libpam_pam_vprompt
.f(pamh
,
500 #ifdef HAVE_PAM_STRERROR_CONST
501 static const char *libpam_pam_strerror(const pam_handle_t
*pamh
, int errnum
)
503 static const char *libpam_pam_strerror(pam_handle_t
*pamh
, int errnum
)
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
,
517 #ifdef HAVE_PAM_VSYSLOG
518 pwrap_bind_symbol_libpam(pam_vsyslog
);
520 pwrap
.libpam
.symbols
._libpam_pam_vsyslog
.f(pamh
,
528 /*********************************************************
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
)
540 ssize_t bread
, bwritten
;
542 char buf
[BUFFER_SIZE
];
545 cmp
= strcmp(src
, dst
);
550 srcfd
= open(src
, O_RDONLY
, 0);
556 rc
= fstat(srcfd
, &sb
);
564 dstfd
= open(dst
, O_CREAT
|O_WRONLY
|O_TRUNC
, mode
);
572 bread
= read(srcfd
, buf
, BUFFER_SIZE
);
576 } else if (bread
< 0) {
582 /* EXTRA UGLY HACK */
586 while (p
< buf
+ BUFFER_SIZE
) {
588 cmp
= memcmp(p
, "/etc/pam.d", 10);
597 bwritten
= write(dstfd
, buf
, bread
);
604 if (bread
!= bwritten
) {
626 /* Do not pass any flag if not defined */
627 #ifndef FTW_ACTIONRETVAL
628 #define FTW_ACTIONRETVAL 0
631 /* Action return values */
637 #define FTW_CONTINUE 0
640 #ifndef FTW_SKIP_SUBTREE
641 #define FTW_SKIP_SUBTREE 0
644 static int copy_ftw(const char *fpath
,
645 const struct stat
*sb
,
650 char buf
[BUFFER_SIZE
];
655 /* We want to copy the directories from this directory */
656 if (ftwbuf
->level
== 0) {
659 return FTW_SKIP_SUBTREE
;
666 rc
= snprintf(buf
, BUFFER_SIZE
, "%s/%s", pwrap
.config_dir
, fpath
+ ftwbuf
->base
);
667 if (rc
>= BUFFER_SIZE
) {
671 PWRAP_LOG(PWRAP_LOG_TRACE
, "Copying %s", fpath
);
672 rc
= p_copy(fpath
, buf
, NULL
, sb
->st_mode
);
680 static int copy_confdir(const char *src
)
684 PWRAP_LOG(PWRAP_LOG_DEBUG
,
685 "Copy config files from %s to %s",
688 rc
= nftw(src
, copy_ftw
, 1, FTW_ACTIONRETVAL
);
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];
713 /* read the pidfile */
714 fd
= open(pidfile
, O_RDONLY
);
716 if (errno
== ENOENT
) {
717 PWRAP_LOG(PWRAP_LOG_TRACE
,
718 "pidfile %s missing, nothing to do\n",
721 PWRAP_LOG(PWRAP_LOG_ERROR
,
722 "Failed to open pidfile %s - error: %s",
723 pidfile
, strerror(errno
));
728 rc
= read(fd
, buf
, sizeof(buf
));
731 PWRAP_LOG(PWRAP_LOG_ERROR
,
732 "Failed to read pidfile %s - error: %s",
733 pidfile
, strerror(errno
));
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",
747 pid
= (pid_t
)(tmp
& 0xFFFF);
751 PWRAP_LOG(PWRAP_LOG_TRACE
,
752 "Remove stale pam_wrapper dir: %s",
760 static void pwrap_init(void)
762 char tmp_config_dir
[] = "/tmp/pam.X";
763 size_t len
= strlen(tmp_config_dir
);
767 char pam_library
[128] = { 0 };
768 char libpam_path
[1024] = { 0 };
771 char pidfile_path
[1024] = { 0 };
773 if (!pam_wrapper_enabled()) {
777 if (pwrap
.initialised
) {
781 PWRAP_LOG(PWRAP_LOG_DEBUG
, "Initialize pam_wrapper");
783 for (i
= 0; i
< 36; i
++) {
793 tmp_config_dir
[len
- 1] = c
;
794 rc
= lstat(tmp_config_dir
, &sb
);
796 PWRAP_LOG(PWRAP_LOG_TRACE
,
797 "Check if pam_wrapper dir %s is a "
800 pwrap_clean_stale_dirs(tmp_config_dir
);
802 } else if (errno
== ENOENT
) {
808 PWRAP_LOG(PWRAP_LOG_ERROR
,
809 "Failed to find a possible path to create "
810 "pam_wrapper config dir: %s",
815 pwrap
.config_dir
= strdup(tmp_config_dir
);
816 if (pwrap
.config_dir
== NULL
) {
817 PWRAP_LOG(PWRAP_LOG_ERROR
,
821 PWRAP_LOG(PWRAP_LOG_TRACE
,
822 "pam_wrapper config dir: %s",
825 rc
= mkdir(pwrap
.config_dir
, 0755);
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
);
836 p_rmdirs(pwrap
.config_dir
);
840 pidfile
= fopen(pidfile_path
, "w");
841 if (pidfile
== NULL
) {
842 p_rmdirs(pwrap
.config_dir
);
846 rc
= fprintf(pidfile
, "%d", getpid());
849 p_rmdirs(pwrap
.config_dir
);
853 /* create lib subdirectory */
854 snprintf(libpam_path
,
859 rc
= mkdir(libpam_path
, 0755);
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
);
868 snprintf(libpam_path
,
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
);
881 /* copy libpam.so.0 */
882 snprintf(libpam_path
, sizeof(libpam_path
), "%s", PAM_LIBRARY
);
883 PWRAP_LOG(PWRAP_LOG_TRACE
,
887 ret
= readlink(libpam_path
, pam_library
, sizeof(pam_library
) - 1);
888 PWRAP_LOG(PWRAP_LOG_TRACE
,
892 PWRAP_LOG(PWRAP_LOG_ERROR
, "Failed to read %s link", LIBPAM_NAME
);
893 p_rmdirs(pwrap
.config_dir
);
897 if (pam_library
[0] == '/') {
898 snprintf(libpam_path
,
903 char libpam_path_cp
[sizeof(libpam_path
)];
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
);
911 PWRAP_LOG(PWRAP_LOG_ERROR
,
912 "No directory component in %s", libpam_path
);
913 p_rmdirs(pwrap
.config_dir
);
917 snprintf(libpam_path
,
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);
928 PWRAP_LOG(PWRAP_LOG_ERROR
,
929 "Failed to copy %s - error: %s",
932 p_rmdirs(pwrap
.config_dir
);
936 pwrap
.initialised
= true;
938 env
= getenv("PAM_WRAPPER_SERVICE_DIR");
940 PWRAP_LOG(PWRAP_LOG_ERROR
, "No config file");
941 p_rmdirs(pwrap
.config_dir
);
945 rc
= copy_confdir(env
);
947 PWRAP_LOG(PWRAP_LOG_ERROR
, "Failed to copy config files");
948 p_rmdirs(pwrap
.config_dir
);
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)
961 pwrap
.enabled
= false;
963 env
= getenv("PAM_WRAPPER");
964 if (env
!= NULL
&& env
[0] == '1') {
965 pwrap
.enabled
= true;
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 /****************************
982 ***************************/
983 void pwrap_constructor(void)
986 * Here is safe place to call pwrap_init() and initialize data
994 static int pwrap_openpam_start(const char *service_name
,
996 const struct pam_conv
*pam_conversation
,
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");
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");
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");
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");
1036 return libpam_pam_start(fullpath
,
1043 static int pwrap_pam_start(const char *service_name
,
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",
1054 return pwrap_openpam_start(service_name
,
1059 return libpam_pam_start(service_name
,
1067 int pam_start(const char *service_name
,
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
)
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] == '/') {
1197 PWRAP_LOG(PWRAP_LOG_TRACE
,
1198 "PAM_SERVICE=%s", service_name
);
1199 return service_name
;
1201 return libpam_service
;
1205 static int pwrap_pam_get_item(const pam_handle_t
*pamh
,
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
) {
1219 PWRAP_LOG(PWRAP_LOG_TRACE
,
1220 "pwrap_get_item PAM_USER=%s",
1221 (const char *)*item
);
1224 svc
= pwrap_get_service((const char *) *item
);
1226 PWRAP_LOG(PWRAP_LOG_TRACE
,
1227 "pwrap_get_item PAM_SERVICE=%s",
1231 case PAM_USER_PROMPT
:
1232 PWRAP_LOG(PWRAP_LOG_TRACE
,
1233 "pwrap_get_item PAM_USER_PROMPT=%s",
1234 (const char *)*item
);
1237 PWRAP_LOG(PWRAP_LOG_TRACE
,
1238 "pwrap_get_item PAM_TTY=%s",
1239 (const char *)*item
);
1242 PWRAP_LOG(PWRAP_LOG_TRACE
,
1243 "pwrap_get_item PAM_RUSER=%s",
1244 (const char *)*item
);
1247 PWRAP_LOG(PWRAP_LOG_TRACE
,
1248 "pwrap_get_item PAM_RHOST=%s",
1249 (const char *)*item
);
1252 PWRAP_LOG(PWRAP_LOG_TRACE
,
1253 "pwrap_get_item PAM_AUTHTOK=%s",
1254 (const char *)*item
);
1256 case PAM_OLDAUTHTOK
:
1257 PWRAP_LOG(PWRAP_LOG_TRACE
,
1258 "pwrap_get_item PAM_OLDAUTHTOK=%s",
1259 (const char *)*item
);
1262 PWRAP_LOG(PWRAP_LOG_TRACE
,
1263 "pwrap_get_item PAM_CONV=%p",
1264 (const void *)*item
);
1267 PWRAP_LOG(PWRAP_LOG_TRACE
,
1268 "pwrap_get_item item_type=%d item=%p",
1269 item_type
, (const void *)*item
);
1273 PWRAP_LOG(PWRAP_LOG_TRACE
, "pwrap_get_item failed rc=%d", 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
,
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
) {
1296 PWRAP_LOG(PWRAP_LOG_TRACE
,
1297 "pwrap_set_item PAM_USER=%s",
1298 (const char *)item
);
1301 PWRAP_LOG(PWRAP_LOG_TRACE
,
1302 "pwrap_set_item PAM_SERVICE=%s",
1303 (const char *)item
);
1305 case PAM_USER_PROMPT
:
1306 PWRAP_LOG(PWRAP_LOG_TRACE
,
1307 "pwrap_set_item PAM_USER_PROMPT=%s",
1308 (const char *)item
);
1311 PWRAP_LOG(PWRAP_LOG_TRACE
,
1312 "pwrap_set_item PAM_TTY=%s",
1313 (const char *)item
);
1316 PWRAP_LOG(PWRAP_LOG_TRACE
,
1317 "pwrap_set_item PAM_RUSER=%s",
1318 (const char *)item
);
1321 PWRAP_LOG(PWRAP_LOG_TRACE
,
1322 "pwrap_set_item PAM_RHOST=%s",
1323 (const char *)item
);
1326 PWRAP_LOG(PWRAP_LOG_TRACE
,
1327 "pwrap_set_item PAM_AUTHTOK=%s",
1328 (const char *)item
);
1330 case PAM_OLDAUTHTOK
:
1331 PWRAP_LOG(PWRAP_LOG_TRACE
,
1332 "pwrap_set_item PAM_OLDAUTHTOK=%s",
1333 (const char *)item
);
1336 PWRAP_LOG(PWRAP_LOG_TRACE
,
1337 "pwrap_set_item PAM_CONV=%p",
1341 PWRAP_LOG(PWRAP_LOG_TRACE
,
1342 "pwrap_set_item item_type=%d item=%p",
1347 PWRAP_LOG(PWRAP_LOG_TRACE
, "pwrap_set_item failed rc=%d", 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
,
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
,
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
,
1377 void (*cleanup
)(pam_handle_t
*pamh
,
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
,
1390 void (*cleanup
)(pam_handle_t
*pamh
,
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
,
1400 static int pwrap_pam_vprompt(pam_handle_t
*pamh
,
1407 PWRAP_LOG(PWRAP_LOG_TRACE
, "pwrap_pam_vprompt style=%d", style
);
1408 return libpam_pam_vprompt(discard_const_p(pam_handle_t
, pamh
),
1415 #ifdef HAVE_PAM_VPROMPT_CONST
1416 int pam_vprompt(const pam_handle_t
*pamh
,
1422 int pam_vprompt(pam_handle_t
*pamh
,
1429 return pwrap_pam_vprompt(discard_const_p(pam_handle_t
, pamh
),
1436 #ifdef HAVE_PAM_PROMPT_CONST
1437 int pam_prompt(const pam_handle_t
*pamh
,
1440 const char *fmt
, ...)
1442 int pam_prompt(pam_handle_t
*pamh
,
1445 const char *fmt
, ...)
1451 va_start(args
, fmt
);
1452 rv
= pwrap_pam_vprompt(discard_const_p(pam_handle_t
, pamh
),
1462 #ifdef HAVE_PAM_STRERROR_CONST
1463 static const char *pwrap_pam_strerror(const pam_handle_t
*pamh
, int errnum
)
1465 static const char *pwrap_pam_strerror(pam_handle_t
*pamh
, int errnum
)
1472 PWRAP_LOG(PWRAP_LOG_TRACE
, "pam_strerror errnum=%d", errnum
);
1474 str
= libpam_pam_strerror(discard_const_p(pam_handle_t
, pamh
),
1477 PWRAP_LOG(PWRAP_LOG_TRACE
, "pam_strerror error=%s", str
);
1482 #ifdef HAVE_PAM_STRERROR_CONST
1483 const char *pam_strerror(const pam_handle_t
*pamh
, int errnum
)
1485 const char *pam_strerror(pam_handle_t
*pamh
, int errnum
)
1488 return pwrap_pam_strerror(discard_const_p(pam_handle_t
, pamh
),
1492 #if defined(HAVE_PAM_VSYSLOG) || defined(HAVE_PAM_SYSLOG)
1494 static void pwrap_pam_vsyslog(const pam_handle_t
*pamh
,
1497 va_list args
) PRINTF_ATTRIBUTE(3, 0);
1499 static void pwrap_pam_vsyslog(const pam_handle_t
*pamh
,
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
);
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
;
1523 case 4: /* LOG_WARN */
1524 dbglvl
= PWRAP_LOG_WARN
;
1526 case 5: /* LOG_NOTICE */
1527 case 6: /* LOG_INFO */
1528 case 7: /* LOG_DEBUG */
1529 dbglvl
= PWRAP_LOG_DEBUG
;
1532 dbglvl
= PWRAP_LOG_TRACE
;
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
,
1548 pwrap_pam_vsyslog(pamh
, priority
, fmt
, args
);
1552 #ifdef HAVE_PAM_SYSLOG
1553 void pam_syslog(const pam_handle_t
*pamh
,
1555 const char *fmt
, ...)
1559 va_start(args
, fmt
);
1560 pwrap_pam_vsyslog(pamh
, priority
, fmt
, args
);
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
;
1577 /* Disable BSD auditing */
1578 int cannot_audit(int x
);
1579 int cannot_audit(int x
)
1586 /****************************
1588 ***************************/
1590 static int p_rmdirs_at(const char *path
, int parent_fd
)
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) {
1608 d
= fdopendir(path_fd
);
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'))) {
1622 rc
= fstatat(path_fd
, dp
->d_name
,
1623 &sb
, AT_SYMLINK_NOFOLLOW
);
1628 if (S_ISDIR(sb
.st_mode
)) {
1629 rc
= p_rmdirs_at(dp
->d_name
, path_fd
);
1631 rc
= unlinkat(path_fd
, dp
->d_name
, 0);
1639 rc
= unlinkat(parent_fd
, path
, AT_REMOVEDIR
);
1642 PWRAP_LOG(PWRAP_LOG_TRACE
,
1643 "cannot unlink %s error %d\n", path
, rc
);
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)
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
) {
1682 PWRAP_LOG(PWRAP_LOG_TRACE
,
1683 "destructor called for pam_wrapper dir %s",
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
;