2006-09-27 23:07:15 -07:00
|
|
|
#include "config.h"
|
|
|
|
|
2006-09-03 01:51:32 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
2011-05-16 03:33:57 -07:00
|
|
|
#include <sys/stat.h>
|
2012-10-31 08:40:53 -07:00
|
|
|
#include <sys/wait.h>
|
2006-09-03 01:51:32 -07:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <grp.h>
|
|
|
|
#include <fnmatch.h>
|
2006-12-14 11:27:46 -08:00
|
|
|
#include <ctype.h>
|
2006-09-27 23:07:15 -07:00
|
|
|
#ifdef HAVE_ALLOCA_H
|
|
|
|
#include <alloca.h>
|
|
|
|
#endif
|
2008-12-07 17:39:33 -08:00
|
|
|
#include <Eina.h>
|
2006-09-03 01:51:32 -07:00
|
|
|
|
|
|
|
/* local subsystem functions */
|
2012-07-30 03:28:25 -07:00
|
|
|
#ifdef HAVE_EEZE_MOUNT
|
2012-07-30 03:13:06 -07:00
|
|
|
static Eina_Bool mountopts_check(const char *opts);
|
|
|
|
static Eina_Bool mount_args_check(int argc, char **argv, const char *action);
|
2012-07-30 03:28:25 -07:00
|
|
|
#endif
|
2013-01-11 02:34:29 -08:00
|
|
|
static int auth_action_ok(char *a,
|
|
|
|
gid_t gid,
|
|
|
|
gid_t *gl,
|
|
|
|
int gn,
|
|
|
|
gid_t egid);
|
|
|
|
static int auth_etc_enlightenment_sysactions(char *a,
|
|
|
|
char *u,
|
|
|
|
char **g);
|
|
|
|
static void auth_etc_enlightenment_sysactions_perm(char *path);
|
|
|
|
static char *get_word(char *s,
|
|
|
|
char *d);
|
2006-09-03 01:51:32 -07:00
|
|
|
|
|
|
|
/* local subsystem globals */
|
2008-12-17 07:33:43 -08:00
|
|
|
static Eina_Hash *actions = NULL;
|
2012-07-30 03:13:06 -07:00
|
|
|
static uid_t uid = -1;
|
2006-09-03 01:51:32 -07:00
|
|
|
|
|
|
|
/* externally accessible functions */
|
|
|
|
int
|
2011-05-15 15:11:30 -07:00
|
|
|
main(int argc,
|
|
|
|
char **argv)
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
2006-09-27 23:35:43 -07:00
|
|
|
int i, gn;
|
2006-09-03 01:51:32 -07:00
|
|
|
int test = 0;
|
2012-08-10 09:00:38 -07:00
|
|
|
char *action = NULL, *cmd;
|
2012-10-30 01:36:26 -07:00
|
|
|
char *output = NULL;
|
2012-07-30 03:28:25 -07:00
|
|
|
#ifdef HAVE_EEZE_MOUNT
|
|
|
|
Eina_Bool mnt = EINA_FALSE;
|
2012-07-30 03:13:06 -07:00
|
|
|
const char *act;
|
2012-07-30 03:28:25 -07:00
|
|
|
#endif
|
2010-10-21 08:04:48 -07:00
|
|
|
gid_t gid, gl[65536], egid;
|
2012-10-31 08:40:53 -07:00
|
|
|
int pid = 0;
|
2006-09-03 01:51:32 -07:00
|
|
|
|
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
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(0);
|
|
|
|
}
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
2011-05-15 16:47:42 -07:00
|
|
|
if (argc >= 3)
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
2011-05-15 16:47:42 -07:00
|
|
|
if ((argc == 3) && (!strcmp(argv[1], "-t")))
|
|
|
|
{
|
|
|
|
test = 1;
|
|
|
|
action = argv[2];
|
|
|
|
}
|
2013-01-11 02:34:29 -08:00
|
|
|
else if (!strcmp(argv[1], "gdb"))
|
2012-10-31 08:40:53 -07:00
|
|
|
{
|
2013-01-11 02:34:29 -08:00
|
|
|
if (argc != 4) exit(1);
|
|
|
|
char *end = NULL;
|
2012-10-30 01:36:26 -07:00
|
|
|
|
2013-01-11 02:34:29 -08:00
|
|
|
action = argv[1];
|
|
|
|
pid = strtoul(argv[2], &end, 10);
|
|
|
|
if (end == NULL || *end != '\0')
|
|
|
|
{
|
|
|
|
printf("Invalid pid for '%s'.\n", argv[3]);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
output = argv[3];
|
|
|
|
}
|
2012-07-30 03:28:25 -07:00
|
|
|
#ifdef HAVE_EEZE_MOUNT
|
2011-05-15 16:47:42 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
s = strrchr(argv[1], '/');
|
2013-01-11 02:34:29 -08:00
|
|
|
if ((!s) || (!s[1])) exit(1); /* eeze always uses complete path */
|
2012-07-30 03:13:06 -07:00
|
|
|
s++;
|
2011-05-16 04:03:45 -07:00
|
|
|
if (strcmp(s, "mount") && strcmp(s, "umount") && strcmp(s, "eject")) exit(1);
|
2011-05-15 16:47:42 -07:00
|
|
|
mnt = EINA_TRUE;
|
2012-07-30 03:13:06 -07:00
|
|
|
act = s;
|
2011-05-15 16:47:42 -07:00
|
|
|
action = argv[1];
|
|
|
|
}
|
2012-07-30 03:28:25 -07:00
|
|
|
#endif
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
|
|
|
else if (argc == 2)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
action = argv[1];
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
exit(1);
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
2012-08-01 23:31:50 -07:00
|
|
|
if (!action) exit(1);
|
2012-10-31 08:40:53 -07:00
|
|
|
fprintf(stderr, "action %s %i\n", action, argc);
|
2006-09-03 02:35:28 -07:00
|
|
|
|
2006-09-03 16:09:14 -07:00
|
|
|
uid = getuid();
|
|
|
|
gid = getgid();
|
2006-09-27 23:35:43 -07:00
|
|
|
egid = getegid();
|
2010-10-21 08:04:48 -07:00
|
|
|
gn = getgroups(65536, gl);
|
|
|
|
if (gn < 0)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
printf("ERROR: MEMBER OF MORE THAN 65536 GROUPS\n");
|
|
|
|
exit(3);
|
2010-10-21 08:04:48 -07:00
|
|
|
}
|
2006-09-03 16:09:14 -07:00
|
|
|
if (setuid(0) != 0)
|
2006-09-03 02:35:28 -07:00
|
|
|
{
|
2011-05-15 15:17:15 -07:00
|
|
|
printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n");
|
2011-05-15 15:11:30 -07:00
|
|
|
exit(5);
|
2006-09-03 02:35:28 -07:00
|
|
|
}
|
2006-09-03 16:09:14 -07:00
|
|
|
if (setgid(0) != 0)
|
|
|
|
{
|
2011-05-15 15:17:15 -07:00
|
|
|
printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n");
|
2011-05-15 15:11:30 -07:00
|
|
|
exit(7);
|
2006-09-03 16:09:14 -07:00
|
|
|
}
|
2011-05-15 15:11:30 -07:00
|
|
|
|
2008-12-07 17:39:33 -08:00
|
|
|
eina_init();
|
2006-09-03 01:51:32 -07:00
|
|
|
|
2012-08-10 03:11:34 -07:00
|
|
|
if (!auth_action_ok(action, gid, gl, gn, egid))
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
printf("ERROR: ACTION NOT ALLOWED: %s\n", action);
|
|
|
|
exit(10);
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
|
|
|
/* we can add more levels of auth here */
|
2011-05-15 15:11:30 -07:00
|
|
|
|
2011-05-15 16:47:42 -07:00
|
|
|
/* when mounting, this will match the exact path to the exe,
|
|
|
|
* as required in sysactions.conf
|
|
|
|
* this is intentionally pedantic for security
|
|
|
|
*/
|
2008-12-07 17:39:33 -08:00
|
|
|
cmd = eina_hash_find(actions, action);
|
2006-09-03 01:51:32 -07:00
|
|
|
if (!cmd)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
printf("ERROR: UNDEFINED ACTION: %s\n", action);
|
|
|
|
exit(20);
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
2012-10-30 01:36:26 -07:00
|
|
|
|
2012-10-31 08:40:53 -07:00
|
|
|
if (!strcmp(action, "gdb"))
|
2012-10-30 01:36:26 -07:00
|
|
|
{
|
|
|
|
char buffer[4096];
|
|
|
|
int r;
|
|
|
|
|
2013-01-11 02:34:29 -08:00
|
|
|
snprintf(buffer, 4096,
|
2012-10-31 18:09:22 -07:00
|
|
|
"%s --pid=%i "
|
2013-01-11 02:34:29 -08:00
|
|
|
"-ex 'set logging file %s' "
|
|
|
|
"-ex 'set logging on' "
|
|
|
|
"-ex 'thread apply all backtrace full' "
|
|
|
|
"-ex detach -ex quit > /dev/null 2> /dev/null",
|
2012-10-30 01:36:26 -07:00
|
|
|
cmd,
|
2013-01-11 02:34:29 -08:00
|
|
|
pid,
|
2013-01-23 02:53:26 -08:00
|
|
|
output ?: "e-output.txt");
|
2012-10-30 01:36:26 -07:00
|
|
|
|
2012-10-31 18:09:22 -07:00
|
|
|
r = system(buffer);
|
2012-10-30 01:36:26 -07:00
|
|
|
|
|
|
|
exit(WEXITSTATUS(r));
|
|
|
|
}
|
2012-07-30 03:28:25 -07:00
|
|
|
if ((!test)
|
|
|
|
#ifdef HAVE_EEZE_MOUNT
|
2013-01-11 02:34:29 -08:00
|
|
|
&& (!mnt)
|
2012-07-30 03:28:25 -07:00
|
|
|
#endif
|
2013-01-11 02:34:29 -08:00
|
|
|
)
|
2012-07-30 03:28:25 -07:00
|
|
|
return system(cmd);
|
|
|
|
#ifdef HAVE_EEZE_MOUNT
|
2011-05-15 16:47:42 -07:00
|
|
|
if (mnt)
|
|
|
|
{
|
2011-05-22 10:08:07 -07:00
|
|
|
int ret = 0;
|
|
|
|
const char *mp = NULL;
|
2012-07-30 03:28:25 -07:00
|
|
|
Eina_Strbuf *buf = NULL;
|
2011-05-15 15:11:30 -07:00
|
|
|
|
2012-07-30 03:28:25 -07:00
|
|
|
if (!mount_args_check(argc, argv, act)) exit(40);
|
2012-07-30 03:13:06 -07:00
|
|
|
/* all options are deemed safe at this point, so away we go! */
|
|
|
|
if (!strcmp(act, "mount"))
|
2011-05-16 03:33:57 -07:00
|
|
|
{
|
2012-07-30 03:13:06 -07:00
|
|
|
struct stat s;
|
|
|
|
|
|
|
|
mp = argv[5];
|
|
|
|
if (stat("/media", &s))
|
|
|
|
{
|
|
|
|
mode_t um;
|
|
|
|
|
|
|
|
um = umask(0);
|
|
|
|
if (mkdir("/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
|
|
|
{
|
|
|
|
printf("ERROR: COULD NOT CREATE DIRECTORY /media\n");
|
|
|
|
exit(40);
|
|
|
|
}
|
|
|
|
umask(um);
|
|
|
|
}
|
|
|
|
else if (!S_ISDIR(s.st_mode))
|
|
|
|
{
|
|
|
|
printf("ERROR: NOT A DIRECTORY: /media\n");
|
|
|
|
exit(40);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stat(mp, &s))
|
2011-05-16 03:33:57 -07:00
|
|
|
{
|
2012-07-30 03:13:06 -07:00
|
|
|
mode_t um;
|
|
|
|
|
|
|
|
um = umask(0);
|
|
|
|
if (mkdir(mp, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
2011-05-16 03:33:57 -07:00
|
|
|
{
|
2012-07-30 03:13:06 -07:00
|
|
|
printf("ERROR: COULD NOT CREATE DIRECTORY %s\n", mp);
|
|
|
|
exit(40);
|
2011-05-16 03:33:57 -07:00
|
|
|
}
|
2012-07-30 03:13:06 -07:00
|
|
|
umask(um);
|
|
|
|
}
|
|
|
|
else if (!S_ISDIR(s.st_mode))
|
|
|
|
{
|
|
|
|
printf("ERROR: NOT A DIRECTORY: %s\n", mp);
|
|
|
|
exit(40);
|
2011-05-16 03:33:57 -07:00
|
|
|
}
|
|
|
|
}
|
2012-07-30 03:13:06 -07:00
|
|
|
buf = eina_strbuf_new();
|
2012-07-30 03:28:25 -07:00
|
|
|
if (!buf) exit(30);
|
2012-07-30 03:13:06 -07:00
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
eina_strbuf_append_printf(buf, "%s ", argv[i]);
|
2011-05-16 03:33:57 -07:00
|
|
|
ret = system(eina_strbuf_string_get(buf));
|
2012-07-30 03:13:06 -07:00
|
|
|
if ((!strcmp(act, "umount")) && (!ret))
|
2011-05-16 03:33:57 -07:00
|
|
|
{
|
2012-07-30 03:13:06 -07:00
|
|
|
Eina_Iterator *it;
|
|
|
|
char path[PATH_MAX];
|
|
|
|
const char *s;
|
|
|
|
struct stat st;
|
|
|
|
Eina_Bool rm = EINA_TRUE;
|
|
|
|
|
|
|
|
mp = strrchr(argv[2], '/');
|
|
|
|
if (!mp) return ret;
|
|
|
|
snprintf(path, sizeof(path), "/media%s", mp);
|
|
|
|
if (stat(path, &st)) return ret;
|
|
|
|
if (!S_ISDIR(st.st_mode)) return ret;
|
|
|
|
it = eina_file_ls(path);
|
|
|
|
EINA_ITERATOR_FOREACH(it, s)
|
|
|
|
{
|
|
|
|
/* don't delete any directories with files in them */
|
|
|
|
rm = EINA_FALSE;
|
|
|
|
eina_stringshare_del(s);
|
|
|
|
}
|
|
|
|
if (rm)
|
|
|
|
{
|
|
|
|
if (rmdir(path))
|
|
|
|
printf("ERROR: COULD NOT UNLINK MOUNT POINT %s\n", path);
|
|
|
|
}
|
2011-05-16 03:33:57 -07:00
|
|
|
}
|
|
|
|
return ret;
|
2011-05-15 16:47:42 -07:00
|
|
|
}
|
2012-07-30 03:28:25 -07:00
|
|
|
#endif
|
2008-12-07 17:39:33 -08:00
|
|
|
eina_shutdown();
|
2011-05-15 15:11:30 -07:00
|
|
|
|
2006-09-03 01:51:32 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* local subsystem functions */
|
2012-07-30 03:28:25 -07:00
|
|
|
#ifdef HAVE_EEZE_MOUNT
|
2012-07-30 03:13:06 -07:00
|
|
|
static Eina_Bool
|
|
|
|
mountopts_check(const char *opts)
|
|
|
|
{
|
|
|
|
char buf[64];
|
|
|
|
const char *p;
|
|
|
|
char *end;
|
|
|
|
unsigned long muid;
|
|
|
|
Eina_Bool nosuid, nodev, noexec, nuid;
|
|
|
|
|
|
|
|
nosuid = nodev = noexec = nuid = EINA_FALSE;
|
|
|
|
|
|
|
|
/* these are the only possible options which can be present here; check them strictly */
|
|
|
|
if (eina_strlcpy(buf, opts, sizeof(buf)) >= sizeof(buf)) return EINA_FALSE;
|
|
|
|
for (p = buf; p && p[1]; p = strchr(p + 1, ','))
|
|
|
|
{
|
|
|
|
if (p[0] == ',') p++;
|
|
|
|
#define CMP(OPT) \
|
|
|
|
if (!strncmp(p, OPT, sizeof(OPT) - 1))
|
|
|
|
|
|
|
|
CMP("nosuid,")
|
2013-01-11 02:34:29 -08:00
|
|
|
{
|
|
|
|
nosuid = EINA_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-30 03:13:06 -07:00
|
|
|
CMP("nodev,")
|
2013-01-11 02:34:29 -08:00
|
|
|
{
|
|
|
|
nodev = EINA_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-30 03:13:06 -07:00
|
|
|
CMP("noexec,")
|
2013-01-11 02:34:29 -08:00
|
|
|
{
|
|
|
|
noexec = EINA_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-30 03:13:06 -07:00
|
|
|
CMP("utf8,") continue;
|
|
|
|
CMP("utf8=0,") continue;
|
|
|
|
CMP("utf8=1,") continue;
|
|
|
|
CMP("iocharset=utf8,") continue;
|
2012-09-03 22:19:49 -07:00
|
|
|
CMP("uid=")
|
2013-01-11 02:34:29 -08:00
|
|
|
{
|
|
|
|
p += 4;
|
|
|
|
errno = 0;
|
|
|
|
muid = strtoul(p, &end, 10);
|
|
|
|
if (muid == ULONG_MAX) return EINA_FALSE;
|
|
|
|
if (errno) return EINA_FALSE;
|
|
|
|
if (end[0] != ',') return EINA_FALSE;
|
|
|
|
if (muid != uid) return EINA_FALSE;
|
|
|
|
nuid = EINA_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-30 03:13:06 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
if ((!nosuid) || (!nodev) || (!noexec) || (!nuid)) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
check_uuid(const char *uuid)
|
|
|
|
{
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
for (p = uuid; p[0]; p++)
|
|
|
|
if ((!isalnum(*p)) && (*p != '-')) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
mount_args_check(int argc, char **argv, const char *action)
|
|
|
|
{
|
|
|
|
Eina_Bool opts = EINA_FALSE;
|
|
|
|
struct stat st;
|
|
|
|
const char *node;
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
|
|
|
|
if (!strcmp(action, "mount"))
|
|
|
|
{
|
|
|
|
/* will ALWAYS be:
|
2013-01-11 02:34:29 -08:00
|
|
|
/path/to/mount -o nosuid,uid=XYZ,[utf8,] UUID=XXXX-XXXX[-XXXX-XXXX] /media/$devnode
|
2012-07-30 03:13:06 -07:00
|
|
|
*/
|
|
|
|
if (argc != 6) return EINA_FALSE;
|
|
|
|
if (argv[2][0] == '-')
|
|
|
|
{
|
|
|
|
/* disallow any -options other than -o */
|
|
|
|
if (strcmp(argv[2], "-o")) return EINA_FALSE;
|
|
|
|
opts = mountopts_check(argv[3]);
|
|
|
|
}
|
|
|
|
if (!opts) return EINA_FALSE;
|
|
|
|
if (!strncmp(argv[4], "UUID=", sizeof("UUID=") - 1))
|
|
|
|
{
|
|
|
|
if (!check_uuid(argv[4] + 5)) return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (strncmp(argv[4], "/dev/", 5)) return EINA_FALSE;
|
|
|
|
if (stat(argv[4], &st)) return EINA_FALSE;
|
|
|
|
}
|
2013-01-11 02:34:29 -08:00
|
|
|
|
2012-07-30 03:13:06 -07:00
|
|
|
node = strrchr(argv[5], '/');
|
|
|
|
if (!node) return EINA_FALSE;
|
|
|
|
if (!node[1]) return EINA_FALSE;
|
|
|
|
if (node - argv[5] != 6) return EINA_FALSE;
|
|
|
|
snprintf(buf, sizeof(buf), "/dev%s", node);
|
|
|
|
if (stat(buf, &st)) return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else if (!strcmp(action, "umount"))
|
|
|
|
{
|
|
|
|
/* will ALWAYS be:
|
2013-01-11 02:34:29 -08:00
|
|
|
/path/to/umount /dev/$devnode
|
2012-07-30 03:13:06 -07:00
|
|
|
*/
|
|
|
|
if (argc != 3) return EINA_FALSE;
|
|
|
|
if (strncmp(argv[2], "/dev/", 5)) return EINA_FALSE;
|
|
|
|
if (stat(argv[2], &st)) return EINA_FALSE;
|
|
|
|
node = strrchr(argv[2], '/');
|
|
|
|
if (!node) return EINA_FALSE;
|
|
|
|
if (!node[1]) return EINA_FALSE;
|
|
|
|
if (node - argv[2] != 4) return EINA_FALSE;
|
2012-10-01 01:35:03 -07:00
|
|
|
/* this is good, but it prevents umounting user-mounted removable media;
|
|
|
|
* need to figure out a better way...
|
2013-01-11 02:34:29 -08:00
|
|
|
*
|
|
|
|
snprintf(buf, sizeof(buf), "/media%s", node);
|
|
|
|
if (stat(buf, &st)) return EINA_FALSE;
|
|
|
|
if (!S_ISDIR(st.st_mode)) return EINA_FALSE;
|
|
|
|
*/
|
2012-07-30 03:13:06 -07:00
|
|
|
}
|
|
|
|
else if (!strcmp(action, "eject"))
|
|
|
|
{
|
|
|
|
/* will ALWAYS be:
|
2013-01-11 02:34:29 -08:00
|
|
|
/path/to/eject /dev/$devnode
|
2012-07-30 03:13:06 -07:00
|
|
|
*/
|
|
|
|
if (argc != 3) return EINA_FALSE;
|
|
|
|
if (strncmp(argv[2], "/dev/", 5)) return EINA_FALSE;
|
|
|
|
if (stat(argv[2], &st)) return EINA_FALSE;
|
|
|
|
node = strrchr(argv[2], '/');
|
|
|
|
if (!node) return EINA_FALSE;
|
|
|
|
if (!node[1]) return EINA_FALSE;
|
2012-08-01 23:58:41 -07:00
|
|
|
if (node - argv[2] != 4) return EINA_FALSE;
|
2012-07-30 03:13:06 -07:00
|
|
|
}
|
|
|
|
else return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2013-01-11 02:34:29 -08:00
|
|
|
|
2012-07-30 03:28:25 -07:00
|
|
|
#endif
|
2012-07-30 03:13:06 -07:00
|
|
|
|
2006-09-03 01:51:32 -07:00
|
|
|
static int
|
2011-05-15 15:11:30 -07:00
|
|
|
auth_action_ok(char *a,
|
|
|
|
gid_t gid,
|
|
|
|
gid_t *gl,
|
|
|
|
int gn,
|
|
|
|
gid_t egid)
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
|
|
|
struct passwd *pw;
|
|
|
|
struct group *gp;
|
2006-09-27 23:35:43 -07:00
|
|
|
char *usr = NULL, **grp, *g;
|
|
|
|
int ret, i, j;
|
2006-09-03 01:51:32 -07:00
|
|
|
|
2006-09-03 16:09:14 -07:00
|
|
|
pw = getpwuid(uid);
|
2006-09-03 01:51:32 -07:00
|
|
|
if (!pw) return 0;
|
|
|
|
usr = pw->pw_name;
|
|
|
|
if (!usr) return 0;
|
2006-09-27 23:07:15 -07:00
|
|
|
grp = alloca(sizeof(char *) * (gn + 1 + 1));
|
|
|
|
j = 0;
|
2006-09-03 16:09:14 -07:00
|
|
|
gp = getgrgid(gid);
|
2006-09-27 23:07:15 -07:00
|
|
|
if (gp)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
grp[j] = gp->gr_name;
|
|
|
|
j++;
|
2006-09-27 23:07:15 -07:00
|
|
|
}
|
|
|
|
for (i = 0; i < gn; i++)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
if (gl[i] != egid)
|
|
|
|
{
|
|
|
|
gp = getgrgid(gl[i]);
|
|
|
|
if (gp)
|
|
|
|
{
|
|
|
|
g = alloca(strlen(gp->gr_name) + 1);
|
|
|
|
strcpy(g, gp->gr_name);
|
|
|
|
grp[j] = g;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
2006-09-27 23:07:15 -07:00
|
|
|
}
|
|
|
|
grp[j] = NULL;
|
2006-09-03 01:51:32 -07:00
|
|
|
/* first stage - check:
|
|
|
|
* PREFIX/etc/enlightenment/sysactions.conf
|
|
|
|
*/
|
|
|
|
ret = auth_etc_enlightenment_sysactions(a, usr, grp);
|
|
|
|
if (ret == 1) return 1;
|
2011-05-15 15:11:30 -07:00
|
|
|
else if (ret == -1)
|
|
|
|
return 0;
|
2006-09-03 01:51:32 -07:00
|
|
|
/* the DEFAULT - allow */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-05-15 15:11:30 -07:00
|
|
|
auth_etc_enlightenment_sysactions(char *a,
|
|
|
|
char *u,
|
|
|
|
char **g)
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
char file[4096], buf[4096], id[4096], ugname[4096], perm[4096], act[4096];
|
2006-09-27 23:07:15 -07:00
|
|
|
char *p, *pp, *s, **gp;
|
2012-08-10 03:14:23 -07:00
|
|
|
int ok = 0;
|
|
|
|
size_t len, line = 0;
|
2006-09-03 01:51:32 -07:00
|
|
|
int allow = 0;
|
|
|
|
int deny = 0;
|
2011-05-15 15:11:30 -07:00
|
|
|
|
2006-09-03 16:14:01 -07:00
|
|
|
snprintf(file, sizeof(file), "/etc/enlightenment/sysactions.conf");
|
|
|
|
f = fopen(file, "r");
|
|
|
|
if (!f)
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
snprintf(file, sizeof(file), PACKAGE_SYSCONF_DIR "/enlightenment/sysactions.conf");
|
|
|
|
f = fopen(file, "r");
|
|
|
|
if (!f) return 0;
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
2012-09-12 04:49:46 -07:00
|
|
|
|
|
|
|
auth_etc_enlightenment_sysactions_perm(file);
|
|
|
|
|
2006-09-03 01:51:32 -07:00
|
|
|
while (fgets(buf, sizeof(buf), f))
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
line++;
|
|
|
|
len = strlen(buf);
|
|
|
|
if (len < 1) continue;
|
|
|
|
if (buf[len - 1] == '\n') buf[len - 1] = 0;
|
|
|
|
/* format:
|
|
|
|
*
|
|
|
|
* # comment
|
|
|
|
* user: username [allow:|deny:] halt reboot ...
|
|
|
|
* group: groupname [allow:|deny:] suspend ...
|
|
|
|
*/
|
|
|
|
if (buf[0] == '#') continue;
|
|
|
|
p = buf;
|
|
|
|
p = get_word(p, id);
|
|
|
|
p = get_word(p, ugname);
|
|
|
|
pp = p;
|
|
|
|
p = get_word(p, perm);
|
|
|
|
allow = 0;
|
|
|
|
deny = 0;
|
|
|
|
if (!strcmp(id, "user:"))
|
|
|
|
{
|
|
|
|
if (!fnmatch(ugname, u, 0))
|
|
|
|
{
|
|
|
|
if (!strcmp(perm, "allow:")) allow = 1;
|
|
|
|
else if (!strcmp(perm, "deny:"))
|
|
|
|
deny = 1;
|
|
|
|
else
|
|
|
|
goto malformed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (!strcmp(id, "group:"))
|
|
|
|
{
|
2012-09-03 22:19:49 -07:00
|
|
|
Eina_Bool matched = EINA_FALSE;
|
2011-05-15 15:11:30 -07:00
|
|
|
|
|
|
|
for (gp = g; *gp; gp++)
|
|
|
|
{
|
|
|
|
if (!fnmatch(ugname, *gp, 0))
|
|
|
|
{
|
2012-09-03 22:19:49 -07:00
|
|
|
matched = EINA_TRUE;
|
2011-05-15 15:11:30 -07:00
|
|
|
if (!strcmp(perm, "allow:")) allow = 1;
|
|
|
|
else if (!strcmp(perm, "deny:"))
|
|
|
|
deny = 1;
|
|
|
|
else
|
|
|
|
goto malformed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!matched) continue;
|
|
|
|
}
|
|
|
|
else if (!strcmp(id, "action:"))
|
|
|
|
{
|
2013-01-11 02:34:29 -08:00
|
|
|
while ((*pp) && (isspace(*pp)))
|
|
|
|
pp++;
|
2011-05-15 15:11:30 -07:00
|
|
|
s = eina_hash_find(actions, ugname);
|
|
|
|
if (s) eina_hash_del(actions, ugname, s);
|
|
|
|
if (!actions) actions = eina_hash_string_superfast_new(free);
|
|
|
|
eina_hash_add(actions, ugname, strdup(pp));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (id[0] == 0)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
goto malformed;
|
|
|
|
|
|
|
|
for (;; )
|
|
|
|
{
|
|
|
|
p = get_word(p, act);
|
|
|
|
if (act[0] == 0) break;
|
|
|
|
if (!fnmatch(act, a, 0))
|
|
|
|
{
|
|
|
|
if (allow) ok = 1;
|
|
|
|
else if (deny)
|
|
|
|
ok = -1;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
malformed:
|
2012-08-10 03:14:23 -07:00
|
|
|
printf("WARNING: %s:%zu\n"
|
2011-05-15 15:11:30 -07:00
|
|
|
"LINE: '%s'\n"
|
|
|
|
"MALFORMED LINE. SKIPPED.\n",
|
|
|
|
file, line, buf);
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
2011-05-15 15:11:30 -07:00
|
|
|
done:
|
2006-09-03 01:51:32 -07:00
|
|
|
fclose(f);
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2012-09-12 04:49:46 -07:00
|
|
|
static void
|
|
|
|
auth_etc_enlightenment_sysactions_perm(char *path)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
if (stat(path, &st) == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((st.st_mode & S_IWGRP) || (st.st_mode & S_IXGRP) ||
|
|
|
|
(st.st_mode & S_IWOTH) || (st.st_mode & S_IXOTH))
|
|
|
|
{
|
2012-12-13 00:32:37 -08:00
|
|
|
printf("ERROR: CONFIGURATION FILE HAS BAD PERMISSIONS (writable by group and/or others)\n");
|
2012-09-12 04:49:46 -07:00
|
|
|
exit(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-03 01:51:32 -07:00
|
|
|
static char *
|
2011-05-15 15:11:30 -07:00
|
|
|
get_word(char *s,
|
|
|
|
char *d)
|
2006-09-03 01:51:32 -07:00
|
|
|
{
|
|
|
|
char *p1, *p2;
|
2011-05-15 15:11:30 -07:00
|
|
|
|
2006-09-03 01:51:32 -07:00
|
|
|
p1 = s;
|
|
|
|
p2 = d;
|
|
|
|
while (*p1)
|
|
|
|
{
|
2011-05-15 15:11:30 -07:00
|
|
|
if (p2 == d)
|
|
|
|
{
|
|
|
|
if (isspace(*p1))
|
|
|
|
{
|
|
|
|
p1++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isspace(*p1)) break;
|
|
|
|
*p2 = *p1;
|
|
|
|
p1++;
|
|
|
|
p2++;
|
2006-09-03 01:51:32 -07:00
|
|
|
}
|
|
|
|
*p2 = 0;
|
|
|
|
return p1;
|
|
|
|
}
|
2013-01-11 02:34:29 -08:00
|
|
|
|