aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2018-02-26 19:01:46 +0900
committerMike Blumenkrantz <zmike@osg.samsung.com>2018-03-02 11:14:20 -0500
commit3c4e25360eb65d0bc9dbfbc2d697898d5b42280d (patch)
treeb49c8dcb0e516e2d3d31b2c89c3cdc09a9ce02e9
parentsysinfo: fix linux build. (diff)
downloadenlightenment-3c4e25360eb65d0bc9dbfbc2d697898d5b42280d.tar.gz
e auth - move all auth to child process only (e_ckpasswd).
this should fix https://phab.enlightenment.org/T6211 ensuring no drivers can cause a segfault at exit time. this also happens to remove the enlightenment_sys -z option for openbsd and unifies all the passwd checking into the single enlightenment_ckpasswd binary util (that has ifdefs for openbsd, freebsd and linux pam in it). this simplifies code removing a mess of auth being done in multiple places, removes special fork vs run 1 exe or a different exe in different cases making it more maintainable. yes - this requires enlightenment_ckpasswd to be setuid root, but it already was when it was built. @fix
-rw-r--r--src/bin/e_auth.c234
-rw-r--r--src/bin/e_auth.h1
-rw-r--r--src/bin/e_ckpasswd_main.c232
-rw-r--r--src/bin/e_desklock.c10
-rw-r--r--src/bin/e_sys_main.c60
-rw-r--r--src/bin/meson.build29
6 files changed, 202 insertions, 364 deletions
diff --git a/src/bin/e_auth.c b/src/bin/e_auth.c
index 2fabc25a6..00b0e5d84 100644
--- a/src/bin/e_auth.c
+++ b/src/bin/e_auth.c
@@ -1,137 +1,6 @@
#include "e.h"
-#if defined(HAVE_PAM) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
-# include <security/pam_appl.h>
-# include <pwd.h>
-
-
-typedef struct E_Auth
-{
- struct
- {
- struct pam_conv conv;
- pam_handle_t *handle;
- } pam;
-
- char user[4096];
- char passwd[4096];
-} E_Auth;
-
-static pid_t _e_auth_child_pid = -1;
-
-static char *
-_auth_auth_get_current_user(void)
-{
- char *user;
- struct passwd *pwent = NULL;
-
- pwent = getpwuid(getuid());
- if (!pwent) return NULL;
- user = strdup(pwent->pw_name);
- return user;
-}
-
-static int
-_auth_auth_pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
-{
- int replies = 0;
- E_Auth *da = (E_Auth *)appdata_ptr;
- struct pam_response *reply = NULL;
-
- reply = (struct pam_response *)malloc(sizeof(struct pam_response) * num_msg);
-
- if (!reply) return PAM_CONV_ERR;
-
- for (replies = 0; replies < num_msg; replies++)
- {
- switch (msg[replies]->msg_style)
- {
- case PAM_PROMPT_ECHO_ON:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = strdup(da->user);
- break;
-
- case PAM_PROMPT_ECHO_OFF:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = strdup(da->passwd);
- break;
-
- case PAM_ERROR_MSG:
- case PAM_TEXT_INFO:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = NULL;
- break;
-
- default:
- free(reply);
- return PAM_CONV_ERR;
- }
- }
- *resp = reply;
- return PAM_SUCCESS;
-}
-
-static int
-_auth_pam_init(E_Auth *da)
-{
- int pamerr;
- const char *pam_prof;
- char *current_host;
- char *current_user;
-
- if (!da) return -1;
-
- da->pam.conv.conv = _auth_auth_pam_conv;
- da->pam.conv.appdata_ptr = da;
- da->pam.handle = NULL;
-
- /* try other pam profiles - and system-auth (login for fbsd users) is a fallback */
- pam_prof = "login";
- if (ecore_file_exists("/etc/pam.d/enlightenment"))
- pam_prof = "enlightenment";
- else if (ecore_file_exists("/etc/pam.d/xscreensaver"))
- pam_prof = "xscreensaver";
- else if (ecore_file_exists("/etc/pam.d/kscreensaver"))
- pam_prof = "kscreensaver";
- else if (ecore_file_exists("/etc/pam.d/system-auth"))
- pam_prof = "system-auth";
- else if (ecore_file_exists("/etc/pam.d/system"))
- pam_prof = "system";
- else if (ecore_file_exists("/etc/pam.d/xdm"))
- pam_prof = "xdm";
- else if (ecore_file_exists("/etc/pam.d/gdm"))
- pam_prof = "gdm";
- else if (ecore_file_exists("/etc/pam.d/kdm"))
- pam_prof = "kdm";
-
- if ((pamerr = pam_start(pam_prof, da->user, &(da->pam.conv),
- &(da->pam.handle))) != PAM_SUCCESS)
- return pamerr;
-
- current_user = _auth_auth_get_current_user();
-
- if ((pamerr = pam_set_item(da->pam.handle, PAM_USER, current_user)) != PAM_SUCCESS)
- {
- free(current_user);
- return pamerr;
- }
-
- current_host = e_auth_hostname_get();
- if ((pamerr = pam_set_item(da->pam.handle, PAM_RHOST, current_host)) != PAM_SUCCESS)
- {
- free(current_user);
- free(current_host);
- return pamerr;
- }
-
- free(current_user);
- free(current_host);
- return 0;
-}
-#endif // HAVE_PAM && !__FreeBSD__ && !_OpenBSD__
-
E_API int
-#if defined(__FreeBSD__)
e_auth_begin(char *passwd)
{
char buf[PATH_MAX], *p;
@@ -159,109 +28,8 @@ 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;
+ for (p = passwd; *p; p++) *p = 0;
if (passwd[0] || passwd[3]) fprintf(stderr, "ACK!\n");
return ret;
}
-#elif defined(__OpenBSD__)
-e_auth_begin(char *passwd)
-{
- char exe_path[PATH_MAX], *p;
- Ecore_Exe *exe = NULL;
- int ret = 0;
- int len = strlen(passwd);
-
- if (len == 0) goto out;
-
- snprintf(exe_path, sizeof(exe_path), "%s/enlightenment/utils/enlightenment_sys -z",
- e_prefix_lib_get());
-
- exe = ecore_exe_pipe_run(exe_path, ECORE_EXE_PIPE_WRITE, NULL);
- if (!exe) goto out;
- if (ecore_exe_send(exe, passwd, len) != EINA_TRUE) goto out;
- if (ecore_exe_send(exe, "\n", 1) != 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);
-
- for (p = passwd; *p; p++)
- *p = 0;
-
- return ret;
-}
-#elif defined(HAVE_PAM)
-e_auth_begin(char *passwd)
-{
- /* child */
- int pamerr;
- E_Auth da;
- char *current_user;
- struct sigaction action;
-
- _e_auth_child_pid = fork();
- if (_e_auth_child_pid > 0) return _e_auth_child_pid;
- if (_e_auth_child_pid < 0) return -1;
-
- action.sa_handler = SIG_DFL;
- action.sa_flags = SA_ONSTACK | SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
- sigemptyset(&action.sa_mask);
- sigaction(SIGSEGV, &action, NULL);
- sigaction(SIGILL, &action, NULL);
- sigaction(SIGFPE, &action, NULL);
- sigaction(SIGBUS, &action, NULL);
- sigaction(SIGABRT, &action, NULL);
-
- current_user = _auth_auth_get_current_user();
- eina_strlcpy(da.user, current_user, sizeof(da.user));
- eina_strlcpy(da.passwd, passwd, sizeof(da.passwd));
- /* security - null out passwd string once we are done with it */
- e_util_memclear(passwd, strlen(passwd));
-
- da.pam.handle = NULL;
- da.pam.conv.conv = NULL;
- da.pam.conv.appdata_ptr = NULL;
-
- pamerr = _auth_pam_init(&da);
- if (pamerr != PAM_SUCCESS)
- {
- free(current_user);
- _exit(1);
- }
- pamerr = pam_authenticate(da.pam.handle, 0);
- pam_end(da.pam.handle, pamerr);
- /* security - null out passwd string once we are done with it */
- e_util_memclear(da.passwd, sizeof(da.passwd));
-
- if (pamerr == PAM_SUCCESS)
- {
- free(current_user);
- _exit(0);
- }
- free(current_user);
- _exit(-1);
-
- return 0;
-}
-#else
-e_auth_begin(char *passwd EINA_UNUSED)
-{
- return 0;
-}
-#endif
-
-E_API char *
-e_auth_hostname_get(void)
-{
- return strdup("localhost");
-}
diff --git a/src/bin/e_auth.h b/src/bin/e_auth.h
index a91f064d1..2ca283763 100644
--- a/src/bin/e_auth.h
+++ b/src/bin/e_auth.h
@@ -2,7 +2,6 @@
#define E_AUTH_H
E_API int e_auth_begin(char *passwd);
-E_API char *e_auth_hostname_get(void);
static inline int
e_auth_hash_djb2(const char *key, int len)
diff --git a/src/bin/e_ckpasswd_main.c b/src/bin/e_ckpasswd_main.c
index c2508a738..8b6479a1c 100644
--- a/src/bin/e_ckpasswd_main.c
+++ b/src/bin/e_ckpasswd_main.c
@@ -1,81 +1,217 @@
-#include <sys/types.h>
+#include "config.h"
+
+#define __USE_MISC
+#define _SVID_SOURCE
+#define _DEFAULT_SOURCE
-#include <err.h>
-#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#if defined(__OpenBSD__)
+
+static int
+_check_auth(uid_t uid, const char *guess)
+{
+ struct passwd *pwent;
+
+ pwent = getpwuid_shadow(uid);
+ if (!pwent) return -1;
+ if (!pwent->pw_passwd) return -1;
+
+ return crypt_checkpass(guess, pw_ent->pw_passwd);
+}
+
+
+
+
+#elif defined(__FreeBSD__)
#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 int
+_check_auth(uid_t uid, const char *pw)
+{
+ struct passwd *pwent = getpwuid(uid);
+
+ if (!pwent) return -1;
+ if (!pwent->pw_passwd) return -1;
+
+ if (!strcmp(crypt(pw, pwent->pw_passwd), pwent->pw_passwd)) return 0;
+ return -1;
+}
+
+
+
+
+
+#elif defined(HAVE_PAM)
+# include <security/pam_appl.h>
+
+typedef struct
+{
+ const char *user;
+ const char *pw;
+} Authinfo;
+
+static int
+_conv_cb(int num, const struct pam_message **msg, struct pam_response **resp, void *data)
+{
+ Authinfo *ai = data;
+ int replies;
+ struct pam_response *reply = NULL;
+
+ reply = malloc(sizeof(struct pam_response) * num);
+ if (!reply) return PAM_CONV_ERR;
-static char pw[4096];
-struct passwd *pwent;
+ for (replies = 0; replies < num; replies++)
+ {
+ switch (msg[replies]->msg_style)
+ {
+ case PAM_PROMPT_ECHO_ON:
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = strdup(ai->user);
+ break;
+ case PAM_PROMPT_ECHO_OFF:
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = strdup(ai->pw);
+ break;
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = NULL;
+ break;
+ default:
+ free(reply);
+ return PAM_CONV_ERR;
+ }
+ }
+ *resp = reply;
+ return PAM_SUCCESS;
+}
-static void
-zeropw(void)
+static int
+_check_auth(uid_t uid, const char *pw)
{
- /* security - null out passwd string once we are done with it */
- memset(pw, 0, sizeof(pw));
- if (pw[0] || pw[3]) printf("ACK!\n");
+ Authinfo ai;
+ struct passwd *pwent;
+ const char *user;
+ const char *prof;
+ const char *host;
+ struct stat st;
+ pam_handle_t *handle;
+ int pamerr;
+ struct pam_conv conv;
+
+ pwent = getpwuid(uid);
+ if (!pwent) return -1;
+ user = pwent->pw_name;
+ if (!user) return -1;
+
+ host = "localhost";
+
+ prof = "login";
+ if (!stat("/etc/pam.d/enlightenment", &st)) prof = "enlightenment";
+ else if (!stat("/etc/pam.d/xscreensaver", &st)) prof = "xscreensaver";
+ else if (!stat("/etc/pam.d/kscreensaver", &st)) prof = "kscreensaver";
+ else if (!stat("/etc/pam.d/system-auth", &st)) prof = "system-auth";
+ else if (!stat("/etc/pam.d/system", &st)) prof = "system";
+ else if (!stat("/etc/pam.d/xdm", &st)) prof = "xdm";
+ else if (!stat("/etc/pam.d/gdm", &st)) prof = "gdm";
+ else if (!stat("/etc/pam.d/kdm", &st)) prof = "kdm";
+
+ ai.user = user;
+ ai.pw = pw;
+
+ conv.conv = _conv_cb;
+ conv.appdata_ptr = &ai;
+ if (pam_start(prof, user, &conv, &handle) != PAM_SUCCESS) return -1;
+ if (pam_set_item(handle, PAM_USER, user) != PAM_SUCCESS) return -1;
+ if (pam_set_item(handle, PAM_RHOST, host) != PAM_SUCCESS) return -1;
+
+ pamerr = pam_authenticate(handle, 0);
+ pam_end(handle, pamerr);
+
+ if (pamerr != PAM_SUCCESS) return -1;
+
+ return 0;
+}
+
+
- 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");
+
+#else
+
+static int
+_check_auth(uid_t uid, const char *pw)
+{
+ return -1;
}
+
+
+
+
+#endif
+
int
main(int argc, char **argv)
{
ssize_t rd;
uid_t id;
- int i;
+ char pw[4096], *p;
- for (i = 1; i < argc; i++)
+ if (argc != 1)
{
- 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);
- }
+ int i;
+
+ for (i = 1; i < argc; i++)
+ fprintf(stderr, "Unknown option %s\n", argv[i]);
+ fprintf(stderr,
+ "This is an internal tool for Enlightenment\n");
+ goto err;
}
- if (argc != 1)
- exit(130);
+ // get uid who ran this
id = getuid();
- if (atexit(zeropw)) err(131, "atexit");
-
+ // read passwd from stdin
rd = read(0, pw, sizeof(pw) - 1);
- if (rd < 0) err(132, "read");
-
- if (setuid(0) != 0)
+ if (rd < 0)
{
- printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n");
- exit(133);
+ fprintf(stderr,
+ "Error. Can't read passwd on stdin\n");
+ goto err;
}
- if (setgid(0) != 0)
+ pw[rd] = 0;
+ for (p = pw; *p; p++)
{
- printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n");
- exit(134);
+ if ((*p == '\r') || (*p == '\n'))
+ {
+ *p = 0;
+ break;
+ }
}
- pwent = getpwuid(id);
- if (pwent == NULL) return -2;
-
- if (strcmp(crypt(pw, pwent->pw_passwd), pwent->pw_passwd) == 0)
- return 0;
-
+ // If we are setuid root then try become root - we can work without though
+ // if pam etc. can work without being root
+ if (setuid(0) != 0)
+ fprintf(stderr,
+ "Warning. Can't become user root. If password auth requires root then this will fail\n");
+ if (setgid(0) != 0)
+ fprintf(stderr,
+ "Warning. Can't become group root. If password auth requires root then this will fail\n");
+ if (_check_auth(id, pw) == 0) return 0;
+err:
+ fprintf(stderr,
+ "Password auth fail\n");
return -1;
}
diff --git a/src/bin/e_desklock.c b/src/bin/e_desklock.c
index 8a1214ac6..7b99fccfa 100644
--- a/src/bin/e_desklock.c
+++ b/src/bin/e_desklock.c
@@ -268,16 +268,6 @@ e_desklock_show(Eina_Bool suspend)
return 1;
}
-#if ! defined(HAVE_PAM) && ! defined(__OpenBSD__)
- if (e_desklock_is_system())
- {
- e_util_dialog_show(_("Error - no PAM support"),
- _("No PAM support was built into Enlightenment, so<ps/>"
- "desk locking is disabled."));
- return 0;
- }
-#endif
-
if (e_desklock_is_personal())
{
if (!e_config->desklock_passwd)
diff --git a/src/bin/e_sys_main.c b/src/bin/e_sys_main.c
index 9043b5854..e5e4e7a7a 100644
--- a/src/bin/e_sys_main.c
+++ b/src/bin/e_sys_main.c
@@ -49,57 +49,6 @@ static int auth_etc_enlightenment_sysactions(char *a,
static void auth_etc_enlightenment_sysactions_perm(char *path);
static char *get_word(char *s,
char *d);
-#if defined(__OpenBSD__)
-
-static void
-_exit_backoff(void)
-{
- sleep(3);
- exit(1 << 7);
-}
-
-static int
-_check_auth(const char *guess)
-{
- struct passwd *pw_ent;
- uid_t uid = getuid();
-
- pw_ent = getpwuid_shadow(uid);
- if (!pw_ent)
- _exit_backoff();
-
- return crypt_checkpass(guess, pw_ent->pw_passwd);
-}
-
-static int
-auth_generic_enlightenment_desklock(void)
-{
- char buf[4096];
- char byte[1];
- int res = -1;
- int i = 0;
-
- while (read(STDIN_FILENO, byte, sizeof(byte)) > 0)
- {
- if (byte[0] == '\n') break;
- buf[i++] = byte[0];
- if (i == sizeof(buf) -1) break;
- }
-
- buf[i] = '\0';
-
- if (!i)
- _exit_backoff();
-
- res = _check_auth(buf);
-
- if (res) _exit_backoff();
-
- return res;
-}
-
-#endif
-
/* local subsystem globals */
static Eina_Hash *actions = NULL;
static uid_t uid = -1;
@@ -132,15 +81,6 @@ main(int argc,
exit(0);
}
}
-#if defined(__OpenBSD__)
- if (argc >= 2)
- {
- if (!strcmp(argv[1], "-z"))
- {
- exit(auth_generic_enlightenment_desklock());
- }
- }
-#endif
if (argc >= 3)
{
if ((argc == 3) && (!strcmp(argv[1], "-t")))
diff --git a/src/bin/meson.build b/src/bin/meson.build
index a8f6aa760..f1624accf 100644
--- a/src/bin/meson.build
+++ b/src/bin/meson.build
@@ -35,8 +35,14 @@ deps_e = [
dep_intl
]
+deps_ckpass = [ ]
+
+if freebsd == true
+ deps_ckpass += dep_crypt
+endif
+
if config_h.has('HAVE_PAM') == true
- deps_e += dep_pam
+ deps_ckpass += dep_pam
endif
requires_e = ' '.join([
@@ -553,16 +559,15 @@ executable('enlightenment_sys',
)
suid_exes += join_paths(dir_e_utils, 'enlightenment_sys')
-if freebsd == true
- executable('enlightenment_ckpasswd',
- 'e_ckpasswd_main.c',
- dependencies : [ dep_crypt ],
- c_args : suid_cflags,
- link_args : suid_ldflags,
- install_dir : dir_e_utils,
- install : true
- )
- suid_exes += join_paths(dir_e_utils, 'enlightenment_ckpasswd')
-endif
+executable('enlightenment_ckpasswd',
+ 'e_ckpasswd_main.c',
+ include_directories: include_directories('../..'),
+ dependencies : deps_ckpass,
+ c_args : suid_cflags,
+ link_args : suid_ldflags,
+ install_dir : dir_e_utils,
+ install : true
+ )
+suid_exes += join_paths(dir_e_utils, 'enlightenment_ckpasswd')
subdir('e_fm')