q66 pushed a commit to branch master. http://git.enlightenment.org/core/enlightenment.git/commit/?id=90fe5a4d0dc75f25f08459ca5e40bd720cdcd6c0
commit 90fe5a4d0dc75f25f08459ca5e40bd720cdcd6c0 Author: Conrad Meyer <cse....@gmail.com> Date: Tue Apr 21 13:11:56 2015 +0100 e_auth: Add suid helper for lokker own-pw checking on FreeBSD Summary: PAM on FreeBSD, unlike on Linux, does not allow users to check their own password. Instead, we need a suid helper to do it for us. Add such a helper on FreeBSD. For now, it is limited to checking users in the local password database (traditional Unix passwd file). This could and should be extended to use PAM in a later patch. Test Plan: Tested empty pw, wrong pw, correct pw at lock screen; observed correct behavior in each instance. Reviewers: q66, zmike Reviewed By: q66, zmike Subscribers: cedric, seoz Differential Revision: https://phab.enlightenment.org/D2355 --- src/bin/.gitignore | 1 + src/bin/Makefile.mk | 14 ++++++++ src/bin/e_auth.c | 41 +++++++++++++++++++++--- src/bin/e_ckpasswd_main.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 4 deletions(-) diff --git a/src/bin/.gitignore b/src/bin/.gitignore index df39011..7addf4d 100644 --- a/src/bin/.gitignore +++ b/src/bin/.gitignore @@ -2,6 +2,7 @@ /enlightenment /enlightenment_alert /enlightenment_backlight +/enlightenment_ckpasswd /enlightenment_fm_op /enlightenment_filemanager /enlightenment_imc diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index 5afdb4a..ecc6f7b 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -36,6 +36,9 @@ src/bin/enlightenment_static_grabber if ! HAVE_WAYLAND_ONLY internal_bin_PROGRAMS += src/bin/enlightenment_alert endif +if HAVE_FREEBSD +internal_bin_PROGRAMS += src/bin/enlightenment_ckpasswd +endif ENLIGHTENMENTHEADERS = \ src/bin/e_about.h \ @@ -423,6 +426,14 @@ src/bin/e_backlight_main.c src_bin_enlightenment_backlight_CPPFLAGS = @SUID_CFLAGS@ @EEZE_CFLAGS@ src_bin_enlightenment_backlight_LDADD = @SUID_LDFLAGS@ @EEZE_LIBS@ +if HAVE_FREEBSD +src_bin_enlightenment_ckpasswd_SOURCES = \ +src/bin/e_ckpasswd_main.c + +src_bin_enlightenment_ckpasswd_CPPFLAGS = @SUID_CFLAGS@ +src_bin_enlightenment_ckpasswd_LDADD = @SUID_LDFLAGS@ -lcrypt +endif + src_bin_enlightenment_alert_SOURCES = \ src/bin/e_alert_main.c @@ -453,6 +464,9 @@ setuid_root_mode = a=rx,u+xs enlightenment-sys-install-data-hook: @chmod $(setuid_root_mode) $(DESTDIR)$(libdir)/enlightenment/utils/enlightenment_sys$(EXEEXT) || true @chmod $(setuid_root_mode) $(DESTDIR)$(libdir)/enlightenment/utils/enlightenment_backlight$(EXEEXT) || true +if HAVE_FREEBSD + @chmod $(setuid_root_mode) $(DESTDIR)$(libdir)/enlightenment/utils/enlightenment_ckpasswd$(EXEEXT) || true +endif installed_headersdir = $(prefix)/include/enlightenment installed_headers_DATA = $(ENLIGHTENMENTHEADERS) src/bin/e_fm_shared_types.h INSTALL_DATA_HOOKS += enlightenment-sys-install-data-hook diff --git a/src/bin/e_auth.c b/src/bin/e_auth.c index a85df6b..6d23d8b 100644 --- a/src/bin/e_auth.c +++ b/src/bin/e_auth.c @@ -1,6 +1,6 @@ #include "e.h" -#ifdef HAVE_PAM +#if defined(HAVE_PAM) && !defined(__FreeBSD__) # include <security/pam_appl.h> # include <pwd.h> @@ -128,11 +128,44 @@ _auth_pam_init(E_Auth *da) free(current_host); return 0; } - -#endif +#endif // HAVE_PAM && !__FreeBSD__ EAPI int -#ifdef HAVE_PAM +#if defined(__FreeBSD__) +e_auth_begin(char *passwd) +{ + char buf[PATH_MAX], *p; + Ecore_Exe *exe = NULL; + int ret = 0; + + if (strlen(passwd) == 0) goto out; + + snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_ckpasswd", + e_prefix_lib_get()); + + exe = ecore_exe_pipe_run(buf, ECORE_EXE_PIPE_WRITE, NULL); + if (ecore_exe_send(exe, passwd, strlen(passwd)) != EINA_TRUE) goto out; + ecore_exe_close_stdin(exe); + + ret = ecore_exe_pid_get(exe); + if (ret == -1) + { + ret = 0; + goto out; + } + + exe = NULL; +out: + if (exe) ecore_exe_free(exe); + + /* security - null out passwd string once we are done with it */ + for (p = passwd; *p; p++) + *p = 0; + if (passwd[0] || passwd[3]) fprintf(stderr, "ACK!\n"); + + return ret; +} +#elif defined(HAVE_PAM) e_auth_begin(char *passwd) { /* child */ diff --git a/src/bin/e_ckpasswd_main.c b/src/bin/e_ckpasswd_main.c new file mode 100644 index 0000000..c2508a7 --- /dev/null +++ b/src/bin/e_ckpasswd_main.c @@ -0,0 +1,81 @@ +#include <sys/types.h> + +#include <err.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <security/pam_constants.h> + +// Exit codes, per src/modules/lokker/lokker.c: +// 0: success (unlock) +// 1-128: PAM error but also unlock (!!!) +// else: failed. + +static char pw[4096]; +struct passwd *pwent; + +static void +zeropw(void) +{ + /* security - null out passwd string once we are done with it */ + memset(pw, 0, sizeof(pw)); + if (pw[0] || pw[3]) printf("ACK!\n"); + + if (pwent == NULL) return; + if (pwent->pw_passwd == NULL) return; + + /* security - null out passwd string once we are done with it */ + memset(pwent->pw_passwd, 0, strlen(pwent->pw_passwd)); + if (pwent->pw_passwd[0]) printf("ACK!\n"); +} + +int +main(int argc, char **argv) +{ + ssize_t rd; + uid_t id; + int i; + + for (i = 1; i < argc; i++) + { + if ((!strcmp(argv[i], "-h")) || + (!strcmp(argv[i], "-help")) || + (!strcmp(argv[i], "--help"))) + { + printf("This is an internal tool for Enlightenment.\n" + "do not use it.\n"); + exit(129); + } + } + if (argc != 1) + exit(130); + + id = getuid(); + + if (atexit(zeropw)) err(131, "atexit"); + + rd = read(0, pw, sizeof(pw) - 1); + if (rd < 0) err(132, "read"); + + if (setuid(0) != 0) + { + printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n"); + exit(133); + } + if (setgid(0) != 0) + { + printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n"); + exit(134); + } + + pwent = getpwuid(id); + if (pwent == NULL) return -2; + + if (strcmp(crypt(pw, pwent->pw_passwd), pwent->pw_passwd) == 0) + return 0; + + return -1; +} --