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
This commit is contained in:
Conrad Meyer 2015-04-21 13:11:56 +01:00 committed by Daniel Kolesa
parent 99b8d84485
commit 90fe5a4d0d
4 changed files with 133 additions and 4 deletions

1
src/bin/.gitignore vendored
View File

@ -2,6 +2,7 @@
/enlightenment
/enlightenment_alert
/enlightenment_backlight
/enlightenment_ckpasswd
/enlightenment_fm_op
/enlightenment_filemanager
/enlightenment_imc

View File

@ -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

View File

@ -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 */

81
src/bin/e_ckpasswd_main.c Normal file
View File

@ -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;
}