18 /* local subsystem functions */
19 #ifdef HAVE_EEZE_MOUNT
20 static Eina_Bool mountopts_check(const char *opts);
21 static Eina_Bool mount_args_check(int argc, char **argv, const char *action);
23 static int auth_action_ok(char *a,
28 static int auth_etc_enlightenment_sysactions(char *a,
31 static void auth_etc_enlightenment_sysactions_perm(char *path);
32 static char *get_word(char *s,
35 /* local subsystem globals */
36 static Eina_Hash *actions = NULL;
37 static uid_t uid = -1;
39 /* externally accessible functions */
46 char *action = NULL, *cmd;
47 #ifdef HAVE_EEZE_MOUNT
48 Eina_Bool mnt = EINA_FALSE;
51 gid_t gid, gl[65536], egid;
53 for (i = 1; i < argc; i++)
55 if ((!strcmp(argv[i], "-h")) ||
56 (!strcmp(argv[i], "-help")) ||
57 (!strcmp(argv[i], "--help")))
60 "This is an internal tool for Enlightenment.\n"
68 if ((argc == 3) && (!strcmp(argv[1], "-t")))
73 #ifdef HAVE_EEZE_MOUNT
78 s = strrchr(argv[1], '/');
79 if ((!s) || (!s[1])) exit(1); /* eeze always uses complete path */
81 if (strcmp(s, "mount") && strcmp(s, "umount") && strcmp(s, "eject")) exit(1);
101 gn = getgroups(65536, gl);
104 printf("ERROR: MEMBER OF MORE THAN 65536 GROUPS\n");
109 printf("ERROR: UNABLE TO ASSUME ROOT PRIVILEGES\n");
114 printf("ERROR: UNABLE TO ASSUME ROOT GROUP PRIVILEGES\n");
120 if (!auth_action_ok(action, gid, gl, gn, egid))
122 printf("ERROR: ACTION NOT ALLOWED: %s\n", action);
125 /* we can add more levels of auth here */
127 /* when mounting, this will match the exact path to the exe,
128 * as required in sysactions.conf
129 * this is intentionally pedantic for security
131 cmd = eina_hash_find(actions, action);
134 printf("ERROR: UNDEFINED ACTION: %s\n", action);
138 #ifdef HAVE_EEZE_MOUNT
143 #ifdef HAVE_EEZE_MOUNT
147 const char *mp = NULL;
148 Eina_Strbuf *buf = NULL;
150 if (!mount_args_check(argc, argv, act)) exit(40);
151 /* all options are deemed safe at this point, so away we go! */
152 if (!strcmp(act, "mount"))
157 if (stat("/media", &s))
162 if (mkdir("/media", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
164 printf("ERROR: COULD NOT CREATE DIRECTORY /media\n");
169 else if (!S_ISDIR(s.st_mode))
171 printf("ERROR: NOT A DIRECTORY: /media\n");
180 if (mkdir(mp, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
182 printf("ERROR: COULD NOT CREATE DIRECTORY %s\n", mp);
187 else if (!S_ISDIR(s.st_mode))
189 printf("ERROR: NOT A DIRECTORY: %s\n", mp);
193 buf = eina_strbuf_new();
195 for (i = 1; i < argc; i++)
196 eina_strbuf_append_printf(buf, "%s ", argv[i]);
197 ret = system(eina_strbuf_string_get(buf));
198 if ((!strcmp(act, "umount")) && (!ret))
204 Eina_Bool rm = EINA_TRUE;
206 mp = strrchr(argv[2], '/');
208 snprintf(path, sizeof(path), "/media%s", mp);
209 if (stat(path, &st)) return ret;
210 if (!S_ISDIR(st.st_mode)) return ret;
211 it = eina_file_ls(path);
212 EINA_ITERATOR_FOREACH(it, s)
214 /* don't delete any directories with files in them */
216 eina_stringshare_del(s);
221 printf("ERROR: COULD NOT UNLINK MOUNT POINT %s\n", path);
232 /* local subsystem functions */
233 #ifdef HAVE_EEZE_MOUNT
235 mountopts_check(const char *opts)
241 Eina_Bool nosuid, nodev, noexec, nuid;
243 nosuid = nodev = noexec = nuid = EINA_FALSE;
245 /* these are the only possible options which can be present here; check them strictly */
246 if (eina_strlcpy(buf, opts, sizeof(buf)) >= sizeof(buf)) return EINA_FALSE;
247 for (p = buf; p && p[1]; p = strchr(p + 1, ','))
249 if (p[0] == ',') p++;
251 if (!strncmp(p, OPT, sizeof(OPT) - 1))
268 CMP("utf8,") continue;
269 CMP("utf8=0,") continue;
270 CMP("utf8=1,") continue;
271 CMP("iocharset=utf8,") continue;
276 muid = strtoul(p, &end, 10);
277 if (muid == ULONG_MAX) return EINA_FALSE;
278 if (errno) return EINA_FALSE;
279 if (end[0] != ',') return EINA_FALSE;
280 if (muid != uid) return EINA_FALSE;
286 if ((!nosuid) || (!nodev) || (!noexec) || (!nuid)) return EINA_FALSE;
291 check_uuid(const char *uuid)
295 for (p = uuid; p[0]; p++)
296 if ((!isalnum(*p)) && (*p != '-')) return EINA_FALSE;
301 mount_args_check(int argc, char **argv, const char *action)
303 Eina_Bool opts = EINA_FALSE;
308 if (!strcmp(action, "mount"))
311 /path/to/mount -o nosuid,uid=XYZ,[utf8,] UUID=XXXX-XXXX[-XXXX-XXXX] /media/$devnode
313 if (argc != 6) return EINA_FALSE;
314 if (argv[2][0] == '-')
316 /* disallow any -options other than -o */
317 if (strcmp(argv[2], "-o")) return EINA_FALSE;
318 opts = mountopts_check(argv[3]);
320 if (!opts) return EINA_FALSE;
321 if (!strncmp(argv[4], "UUID=", sizeof("UUID=") - 1))
323 if (!check_uuid(argv[4] + 5)) return EINA_FALSE;
327 if (strncmp(argv[4], "/dev/", 5)) return EINA_FALSE;
328 if (stat(argv[4], &st)) return EINA_FALSE;
331 node = strrchr(argv[5], '/');
332 if (!node) return EINA_FALSE;
333 if (!node[1]) return EINA_FALSE;
334 if (node - argv[5] != 6) return EINA_FALSE;
335 snprintf(buf, sizeof(buf), "/dev%s", node);
336 if (stat(buf, &st)) return EINA_FALSE;
338 else if (!strcmp(action, "umount"))
341 /path/to/umount /dev/$devnode
343 if (argc != 3) return EINA_FALSE;
344 if (strncmp(argv[2], "/dev/", 5)) return EINA_FALSE;
345 if (stat(argv[2], &st)) return EINA_FALSE;
346 node = strrchr(argv[2], '/');
347 if (!node) return EINA_FALSE;
348 if (!node[1]) return EINA_FALSE;
349 if (node - argv[2] != 4) return EINA_FALSE;
350 snprintf(buf, sizeof(buf), "/media%s", node);
351 if (stat(buf, &st)) return EINA_FALSE;
352 if (!S_ISDIR(st.st_mode)) return EINA_FALSE;
354 else if (!strcmp(action, "eject"))
357 /path/to/eject /dev/$devnode
359 if (argc != 3) return EINA_FALSE;
360 if (strncmp(argv[2], "/dev/", 5)) return EINA_FALSE;
361 if (stat(argv[2], &st)) return EINA_FALSE;
362 node = strrchr(argv[2], '/');
363 if (!node) return EINA_FALSE;
364 if (!node[1]) return EINA_FALSE;
365 if (node - argv[2] != 4) return EINA_FALSE;
367 else return EINA_FALSE;
373 auth_action_ok(char *a,
381 char *usr = NULL, **grp, *g;
388 grp = alloca(sizeof(char *) * (gn + 1 + 1));
393 grp[j] = gp->gr_name;
396 for (i = 0; i < gn; i++)
400 gp = getgrgid(gl[i]);
403 g = alloca(strlen(gp->gr_name) + 1);
404 strcpy(g, gp->gr_name);
411 /* first stage - check:
412 * PREFIX/etc/enlightenment/sysactions.conf
414 ret = auth_etc_enlightenment_sysactions(a, usr, grp);
415 if (ret == 1) return 1;
418 /* the DEFAULT - allow */
423 auth_etc_enlightenment_sysactions(char *a,
428 char file[4096], buf[4096], id[4096], ugname[4096], perm[4096], act[4096];
429 char *p, *pp, *s, **gp;
431 size_t len, line = 0;
435 snprintf(file, sizeof(file), "/etc/enlightenment/sysactions.conf");
436 f = fopen(file, "r");
439 snprintf(file, sizeof(file), PACKAGE_SYSCONF_DIR "/enlightenment/sysactions.conf");
440 f = fopen(file, "r");
444 auth_etc_enlightenment_sysactions_perm(file);
446 while (fgets(buf, sizeof(buf), f))
450 if (len < 1) continue;
451 if (buf[len - 1] == '\n') buf[len - 1] = 0;
455 * user: username [allow:|deny:] halt reboot ...
456 * group: groupname [allow:|deny:] suspend ...
458 if (buf[0] == '#') continue;
461 p = get_word(p, ugname);
463 p = get_word(p, perm);
466 if (!strcmp(id, "user:"))
468 if (!fnmatch(ugname, u, 0))
470 if (!strcmp(perm, "allow:")) allow = 1;
471 else if (!strcmp(perm, "deny:"))
479 else if (!strcmp(id, "group:"))
481 Eina_Bool matched = EINA_FALSE;
483 for (gp = g; *gp; gp++)
485 if (!fnmatch(ugname, *gp, 0))
488 if (!strcmp(perm, "allow:")) allow = 1;
489 else if (!strcmp(perm, "deny:"))
495 if (!matched) continue;
497 else if (!strcmp(id, "action:"))
499 while ((*pp) && (isspace(*pp))) pp++;
500 s = eina_hash_find(actions, ugname);
501 if (s) eina_hash_del(actions, ugname, s);
502 if (!actions) actions = eina_hash_string_superfast_new(free);
503 eina_hash_add(actions, ugname, strdup(pp));
513 p = get_word(p, act);
514 if (act[0] == 0) break;
515 if (!fnmatch(act, a, 0))
526 printf("WARNING: %s:%zu\n"
528 "MALFORMED LINE. SKIPPED.\n",
537 auth_etc_enlightenment_sysactions_perm(char *path)
540 if (stat(path, &st) == -1)
543 if ((st.st_mode & S_IWGRP) || (st.st_mode & S_IXGRP) ||
544 (st.st_mode & S_IWOTH) || (st.st_mode & S_IXOTH))
546 printf("ERROR: CONFIGURATION FILE HAS BAD PERMISSIONS\n");
569 if (isspace(*p1)) break;