-
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
#include "dbus-unit.h"
#include "bus-errors.h"
#include "dbus-common.h"
+#include "audit.h"
#include <stdio.h>
#include <string.h>
check will be called.
*/
-static const char * const unit_methods[][2] = {{ "DisableUnitFiles", "disable" },
- { "EnableUnitFiles", "enable" },
- { "GetUnit", "status" },
- { "GetUnitFileState", "status" },
- { "Kill", "stop" },
- { "KillUnit", "stop" },
- { "LinkUnitFiles", "enable" },
- { "MaskUnitFiles", "disable" },
- { "PresetUnitFiles", "enable" },
- { "ReenableUnitFiles", "enable" },
- { "Reexecute", "start" },
- { "ReloadOrRestart", "start" },
- { "ReloadOrRestartUnit", "start" },
- { "ReloadOrTryRestart", "start" },
- { "ReloadOrTryRestartUnit", "start" },
- { "ReloadUnit", "reload" },
- { "ResetFailedUnit", "stop" },
- { "Restart", "start" },
- { "RestartUnit", "start" },
- { "Start", "start" },
- { "StartUnit", "start" },
- { "StartUnitReplace", "start" },
- { "Stop", "stop" },
- { "StopUnit", "stop" },
- { "TryRestart", "start" },
- { "TryRestartUnit", "start" },
- { "UnmaskUnitFiles", "enable" },
- { NULL, NULL }
-};
-
-static const char * const system_methods[][2] = { { "ClearJobs", "reboot" },
- { "CreateSnapshot", "status" },
- { "Dump", "status" },
- { "Exit", "halt" },
- { "FlushDevices", "halt" },
- { "Get", "status" },
- { "GetAll", "status" },
- { "GetJob", "status" },
- { "GetSeat", "status" },
- { "GetSession", "status" },
- { "GetSessionByPID", "status" },
- { "GetUnitByPID", "status" },
- { "GetUser", "status" },
- { "Halt", "halt" },
- { "Introspect", "status" },
- { "KExec", "reboot" },
- { "KillSession", "halt" },
- { "KillUser", "halt" },
- { "LoadUnit", "reload" },
- { "ListJobs", "status" },
- { "ListSeats", "status" },
- { "ListSessions", "status" },
- { "ListUnits", "status" },
- { "ListUnitFiles", "status" },
- { "ListUsers", "status" },
- { "LockSession", "halt" },
- { "PowerOff", "halt" },
- { "Reboot", "reboot" },
- { "Reload", "reload" },
- { "Reexecute", "reload" },
- { "ResetFailed", "reload" },
- { "Subscribe", "status" },
- { "SwithcRoot", "reboot" },
- { "SetEnvironment", "status" },
- { "SetUserLinger", "halt" },
- { "TerminateSeat", "halt" },
- { "TerminateSession", "halt" },
- { "TerminateUser", "halt" },
- { "Unsubscribe", "status" },
- { "UnsetEnvironment", "status" },
- { "UnsetAndSetEnvironment", "status" },
- { NULL, NULL }
-};
+static const char unit_methods[] =
+ "DisableUnitFiles\0" "disable\0"
+ "EnableUnitFiles\0" "enable\0"
+ "GetUnit\0" "status\0"
+ "GetUnitFileState\0" "status\0"
+ "Kill\0" "stop\0"
+ "KillUnit\0" "stop\0"
+ "LinkUnitFiles\0" "enable\0"
+ "MaskUnitFiles\0" "disable\0"
+ "PresetUnitFiles\0" "enable\0"
+ "ReenableUnitFiles\0" "enable\0"
+ "ReloadOrRestart\0" "start\0"
+ "ReloadOrRestartUnit\0" "start\0"
+ "ReloadOrTryRestart\0" "start\0"
+ "ReloadOrTryRestartUnit\0" "start\0"
+ "Reload\0" "reload\0"
+ "ReloadUnit\0" "reload\0"
+ "ResetFailedUnit\0" "stop\0"
+ "Restart\0" "start\0"
+ "RestartUnit\0" "start\0"
+ "Start\0" "start\0"
+ "StartUnit\0" "start\0"
+ "StartUnitReplace\0" "start\0"
+ "Stop\0" "stop\0"
+ "StopUnit\0" "stop\0"
+ "TryRestart\0" "start\0"
+ "TryRestartUnit\0" "start\0"
+ "UnmaskUnitFiles\0" "enable\0";
+
+static const char system_methods[] =
+ "ClearJobs\0" "reboot\0"
+ "CreateSnapshot\0" "status\0"
+ "Dump\0" "status\0"
+ "Exit\0" "halt\0"
+ "FlushDevices\0" "halt\0"
+ "Get\0" "status\0"
+ "GetAll\0" "status\0"
+ "GetJob\0" "status\0"
+ "GetSeat\0" "status\0"
+ "GetSession\0" "status\0"
+ "GetSessionByPID\0" "status\0"
+ "GetUnitByPID\0" "status\0"
+ "GetUser\0" "status\0"
+ "Halt\0" "halt\0"
+ "Introspect\0" "status\0"
+ "KExec\0" "reboot\0"
+ "KillSession\0" "halt\0"
+ "KillUser\0" "halt\0"
+ "LoadUnit\0" "reload\0"
+ "ListJobs\0" "status\0"
+ "ListSeats\0" "status\0"
+ "ListSessions\0" "status\0"
+ "ListUnits\0" "status\0"
+ "ListUnitFiles\0" "status\0"
+ "ListUsers\0" "status\0"
+ "LockSession\0" "halt\0"
+ "PowerOff\0" "halt\0"
+ "Reboot\0" "reboot\0"
+ "Reload\0" "reload\0"
+ "Reexecute\0" "reload\0"
+ "ResetFailed\0" "reload\0"
+ "Subscribe\0" "status\0"
+ "SwithcRoot\0" "reboot\0"
+ "SetEnvironment\0" "status\0"
+ "SetUserLinger\0" "halt\0"
+ "TerminateSeat\0" "halt\0"
+ "TerminateSession\0" "halt\0"
+ "TerminateUser\0" "halt\0"
+ "Unsubscribe\0" "status\0"
+ "UnsetEnvironment\0" "status\0"
+ "UnsetAndSetEnvironment\0" "status\0";
/*
If the admin toggles the selinux enforcment mode this callback
return r;
}
-static int get_cmdline(pid_t pid, char **cmdline) {
- char buf[PATH_MAX];
- FILE *f;
- int count;
- int n;
-
- snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
- f = fopen(buf, "re");
- if (!f) {
- return -errno;
- }
- count = fread(buf, 1, sizeof(buf), f);
- fclose(f);
- if (! count) {
- return -errno;
- }
- for (n = 0; n < count - 1; n++)
- {
- if (buf[n] == '\0')
- buf[n] = ' ';
- }
- (*cmdline) = strdup(buf);
- if (! (*cmdline)) {
- return -errno;
- }
- return 0;
-}
-
-static int get_pid_id(pid_t pid, const char *file, uid_t *id) {
- char buf[PATH_MAX];
- int r = 0;
- FILE *f;
- snprintf(buf, sizeof(buf), "/proc/%lu/%s", (unsigned long) pid, file);
- f = fopen(buf, "re");
- if (!f)
- return -errno;
- fscanf(f, "%d", id);
- if (ferror(f))
- r = -errno;
- fclose(f);
- return r;
-}
-
/* This mimics dbus_bus_get_unix_user() */
static int bus_get_audit_data(
DBusConnection *connection,
DBusError *error) {
pid_t pid;
- DBusMessage *m = NULL, *reply = NULL;
- int r = -1;
-
- m = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "GetConnectionUnixProcessID");
- if (!m) {
- r = -errno;
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- goto finish;
- }
-
- r = dbus_message_append_args(
- m,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID);
- if (!r) {
- r = -errno;
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- goto finish;
- }
-
- reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
- if (!reply) {
- r = -errno;
- goto finish;
- }
-
- r = dbus_set_error_from_message(error, reply);
- if (!r) {
- r = -errno;
- goto finish;
- }
+ int r;
- r = dbus_message_get_args(
- reply, error,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_INVALID);
- if (!r) {
- r = -errno;
- goto finish;
- }
+ pid = bus_get_unix_process_id(connection, name, error);
+ if (pid <= 0)
+ return -EINVAL;
- r = get_pid_id(pid, "loginuid", &(audit->loginuid));
- if (r)
- goto finish;
+ r = audit_loginuid_from_pid(pid, &audit->loginuid);
+ if (r < 0)
+ return r;
- r = get_pid_id(pid, "uid", &(audit->uid));
- if (r)
- goto finish;
+ r = get_process_uid(pid, &audit->uid);
+ if (r < 0)
+ return r;
- r = get_pid_id(pid, "gid", &(audit->gid));
- if (r)
- goto finish;
+ r = get_process_gid(pid, &audit->gid);
+ if (r < 0)
+ return r;
- r = get_cmdline(pid, &(audit->cmdline));
- if (r)
- goto finish;
+ r = get_process_cmdline(pid, LINE_MAX, true, &audit->cmdline);
+ if (r < 0)
+ return r;
- r = 0;
-finish:
- if (m)
- dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
- return r;
+ return 0;
}
/*
DBusError *error) {
const char *sender;
- int r = -1;
+ int r;
sender = dbus_message_get_sender(message);
- if (sender) {
- r = bus_get_audit_data(
- connection,
- sender,
- audit,
- error);
- if (r)
- goto finish;
- } else {
+ if (sender)
+ return bus_get_audit_data(connection, sender, audit, error);
+ else {
int fd;
struct ucred ucred;
socklen_t len;
- r = dbus_connection_get_unix_fd(connection, &fd);
- if (!r) {
- r = -EINVAL;
- goto finish;
- }
+
+ if (!dbus_connection_get_unix_fd(connection, &fd))
+ return -EINVAL;
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
if (r < 0) {
- r = -errno;
log_error("Failed to determine peer credentials: %m");
- goto finish;
+ return -errno;
}
+
audit->uid = ucred.uid;
audit->gid = ucred.gid;
- r = get_pid_id(ucred.pid, "loginuid", &(audit->loginuid));
- if (r)
- goto finish;
-
- r = get_cmdline(ucred.pid, &(audit->cmdline));
- if (r)
- goto finish;
- }
+ r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid);
+ if (r < 0)
+ return r;
- r = 0;
+ r = get_process_cmdline(ucred.pid, LINE_MAX, true, &audit->cmdline);
+ if (r < 0)
+ return r;
-finish:
- return r;
+ return 0;
+ }
}
/*
This function returns the SELinux permission to check and whether or not the
check requires a unit file.
*/
-static void selinux_perm_lookup(const char *method, const char **perm, int *require_unit)
-{
- int i;
- *require_unit = -1;
-
- for (i = 0; unit_methods[i][0]; i++) {
- if (streq(method, unit_methods[i][0])) {
- *perm = unit_methods[i][1];
- *require_unit = 1;
- break;
+static void selinux_perm_lookup(const char *method, const char **perm, bool *require_unit) {
+ const char *m, *p;
+
+ NULSTR_FOREACH_PAIR(m, p, unit_methods)
+ if (streq(method, m)) {
+ *perm = p;
+ *require_unit = true;
+ return;
}
- }
- if (*require_unit < 0) {
- for (i = 0; system_methods[i][0]; i++) {
- if (streq(method, system_methods[i][0])) {
- *perm = system_methods[i][1];
- *require_unit = 0;
- break;
- }
+ NULSTR_FOREACH_PAIR(m, p, system_methods)
+ if (streq(method, m)) {
+ *perm = p;
+ *require_unit = false;
+ return;
}
- }
- if (*require_unit < 0) {
- *require_unit = 0;
- *perm = "undefined";
- }
+
+ *require_unit = false;
+ *perm = "undefined";
}
/*
int r = 0;
const char *tclass = NULL;
struct auditstruct audit;
- audit.uid = audit.loginuid = audit.gid = -1;
+
+ audit.uid = audit.loginuid = (uid_t) -1;
+ audit.gid = (gid_t) -1;
audit.cmdline = NULL;
audit.path = path;
(void) get_audit_data(connection, message, &audit, error);
- errno=0;
+ errno= 0;
r = selinux_check_access(scon, fcon, tclass, perm, &audit);
- if ( r < 0) {
+ if (r < 0) {
r = -errno;
log_error("SELinux Denied \"%s\"", audit.cmdline);
int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error) {
const char *perm;
- int require_unit;
- const char *member = dbus_message_get_member(message);
+ bool require_unit;
+ const char *member;
int r;
r = selinux_init(m, error);
- if (r)
+ if (r < 0)
return r;
if (! selinux_enabled)
return 0;
+ member = dbus_message_get_member(message);
+
selinux_perm_lookup(member, &perm, &require_unit);
log_debug("SELinux dbus-unit Look %s up perm %s require_unit %d", member, perm, require_unit);
r = selinux_access_check(connection, message, m, error, perm, path);
- if ((r < 0) && (!selinux_enforcing)) {
+ if (r < 0 && !selinux_enforcing) {
dbus_error_init(error);
r = 0;
}
int selinux_manager_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, DBusError *error) {
int r = -1;
const char *member;
- int require_unit;
+ bool require_unit;
const char *perm;
char *path = NULL;
r = selinux_init(m, error);
- if (r)
+ if (r < 0)
return r;
if (! selinux_enabled)
const char *name;
Unit *u;
- r = dbus_message_get_args(
+ if (!dbus_message_get_args(
message,
error,
DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID);
- if (!r)
+ DBUS_TYPE_INVALID)) {
+ r = -EINVAL;
goto finish;
+ }
- u = manager_get_unit(m, name);
- if ( !u ) {
- if ((r = manager_load_unit(m, name, NULL, error, &u)) < 0) {
- r = -errno;
- dbus_set_error(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- goto finish;
- }
+ r = manager_load_unit(m, name, NULL, error, &u);
+ if (r < 0) {
+ dbus_set_error(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ goto finish;
}
path = u->source_path ? u->source_path : u->fragment_path;
return 0;
}
-void selinux_access_finish(void) {}
+void selinux_access_finish(void) {
+}
#endif