e auth - move all auth to child process only (e_ckpasswd).
this should fix 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
This commit is contained in:
parent
46764d5975
commit
51cb454993
234
src/bin/e_auth.c
234
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");
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
#include <security/pam_constants.h>
|
||||
#if defined(__OpenBSD__)
|
||||
|
||||
// Exit codes, per src/modules/lokker/lokker.c:
|
||||
// 0: success (unlock)
|
||||
// 1-128: PAM error but also unlock (!!!)
|
||||
// else: failed.
|
||||
|
||||
static char pw[4096];
|
||||
static int
|
||||
_check_auth(uid_t uid, const char *guess)
|
||||
{
|
||||
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");
|
||||
pwent = getpwuid_shadow(uid);
|
||||
if (!pwent) return -1;
|
||||
if (!pwent->pw_passwd) return -1;
|
||||
|
||||
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");
|
||||
return crypt_checkpass(guess, pw_ent->pw_passwd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <security/pam_constants.h>
|
||||
|
||||
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;
|
||||
|
||||
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 int
|
||||
_check_auth(uid_t uid, const char *pw)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#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;
|
||||
char pw[4096], *p;
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
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);
|
||||
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 (rd < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Error. Can't read passwd on stdin\n");
|
||||
goto err;
|
||||
}
|
||||
pw[rd] = 0;
|
||||
for (p = pw; *p; p++)
|
||||
{
|
||||
if ((*p == '\r') || (*p == '\n'))
|
||||
{
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n");
|
||||
exit(133);
|
||||
}
|
||||
fprintf(stderr,
|
||||
"Warning. Can't become user root. If password auth requires root then this will fail\n");
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")))
|
||||
|
|
|
@ -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([
|
||||
|
@ -555,17 +561,16 @@ 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 ],
|
||||
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')
|
||||
endif
|
||||
|
||||
if config_h.has('HAVE_WAYLAND') == true
|
||||
shared_library('loader',
|
||||
|
|
Loading…
Reference in New Issue