bus-policy.c revision bcf3295d2b0d87caefad2e73d221aac080d0c11e
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2013 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "xml.h"
#include "fileio.h"
#include "strv.h"
#include "conf-files.h"
#include "bus-internal.h"
#include "bus-policy.h"
static void policy_item_free(PolicyItem *i) {
assert(i);
free(i);
}
unsigned n_other = 0;
const char *q;
int r;
enum {
} state = STATE_OUTSIDE;
enum {
unsigned line = 0;
assert(p);
if (r < 0) {
if (r == -ENOENT)
return 0;
return r;
}
q = c;
for (;;) {
int t;
if (t < 0) {
return t;
}
switch (state) {
case STATE_OUTSIDE:
if (t == XML_TAG_OPEN) {
else {
return -EINVAL;
}
} else if (t == XML_END)
return 0;
return -EINVAL;
}
break;
case STATE_BUSCONFIG:
if (t == XML_TAG_OPEN) {
} else {
state = STATE_OTHER;
n_other = 0;
}
} else if (t == XML_TAG_CLOSE_EMPTY ||
return -EINVAL;
}
break;
case STATE_POLICY:
if (t == XML_ATTRIBUTE_NAME) {
else {
}
} else if (t == XML_TAG_CLOSE_EMPTY ||
else if (t == XML_TAG_OPEN) {
else {
return -EINVAL;
}
assert(!i);
if (!i)
return log_oom();
return -EINVAL;
}
break;
case STATE_POLICY_CONTEXT:
if (t == XML_ATTRIBUTE_VALUE) {
} else {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
case STATE_POLICY_USER:
if (t == XML_ATTRIBUTE_VALUE) {
policy_user = name;
} else {
return -EINVAL;
}
break;
case STATE_POLICY_GROUP:
if (t == XML_ATTRIBUTE_VALUE) {
policy_group = name;
} else {
return -EINVAL;
}
break;
if (t == XML_ATTRIBUTE_VALUE)
else {
return -EINVAL;
}
break;
case STATE_ALLOW_DENY:
assert(i);
if (t == XML_ATTRIBUTE_NAME) {
else {
break;
}
return -EINVAL;
}
const char *u;
assert(u);
u++;
if (streq(u, "interface"))
else if (streq(u, "member"))
else if (streq(u, "error"))
else if (streq(u, "path"))
else if (streq(u, "type"))
else {
break;
}
} else
} else if (t == XML_TAG_CLOSE_EMPTY ||
if (i->class == _POLICY_ITEM_CLASS_UNSET) {
return -EINVAL;
}
else if (policy_category == POLICY_CATEGORY_MANDATORY)
else if (policy_category == POLICY_CATEGORY_USER) {
if (r < 0)
return log_oom();
if (r < 0) {
return log_oom();
}
} else if (policy_category == POLICY_CATEGORY_GROUP) {
if (r < 0)
return log_oom();
if (r < 0) {
return log_oom();
}
}
i = NULL;
return -EINVAL;
}
break;
if (t == XML_ATTRIBUTE_VALUE) {
assert(i);
if (i->interface) {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
case STATE_ALLOW_DENY_MEMBER:
if (t == XML_ATTRIBUTE_VALUE) {
assert(i);
if (i->member) {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
case STATE_ALLOW_DENY_ERROR:
if (t == XML_ATTRIBUTE_VALUE) {
assert(i);
if (i->error) {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
case STATE_ALLOW_DENY_PATH:
if (t == XML_ATTRIBUTE_VALUE) {
assert(i);
if (i->path) {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
if (t == XML_ATTRIBUTE_VALUE) {
assert(i);
if (i->message_type != 0) {
return -EINVAL;
}
if (r < 0) {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
case STATE_ALLOW_DENY_NAME:
if (t == XML_ATTRIBUTE_VALUE) {
assert(i);
if (i->name) {
return -EINVAL;
}
} else {
return -EINVAL;
}
break;
if (t == XML_ATTRIBUTE_VALUE)
else {
return -EINVAL;
}
break;
case STATE_OTHER:
if (t == XML_TAG_OPEN)
n_other++;
else if (t == XML_TAG_CLOSE || t == XML_TAG_CLOSE_EMPTY) {
if (n_other == 0)
else
n_other--;
}
break;
}
}
}
int policy_load(Policy *p) {
_cleanup_strv_free_ char **l = NULL;
char **i;
int r;
assert(p);
file_load(p, "/etc/dbus-1/system.conf");
file_load(p, "/etc/dbus-1/system-local.conf");
if (r < 0) {
return r;
}
STRV_FOREACH(i, l)
file_load(p, *i);
return 0;
}
void policy_free(Policy *p) {
PolicyItem *i, *first;
if (!p)
return;
while ((i = p->default_items)) {
policy_item_free(i);
}
while ((i = p->mandatory_items)) {
policy_item_free(i);
}
while ((i = first)) {
policy_item_free(i);
}
policy_item_free(i);
}
while ((i = first)) {
policy_item_free(i);
}
policy_item_free(i);
}
hashmap_free(p->user_items);
hashmap_free(p->group_items);
}
static void dump_items(PolicyItem *i) {
if (!i)
return;
printf("Type: %s\n"
"Class: %s\n",
if (i->interface)
printf("Interface: %s\n",
i->interface);
if (i->member)
printf("Member: %s\n",
i->member);
if (i->error)
printf("Error: %s\n",
i->error);
if (i->path)
printf("Path: %s\n",
i->path);
if (i->name)
printf("Name: %s\n",
i->name);
if (i->message_type != 0)
printf("Message Type: %s\n",
if (i->uid_valid) {
_cleanup_free_ char *user;
printf("User: %s\n",
}
if (i->gid_valid) {
_cleanup_free_ char *group;
printf("Group: %s\n",
}
if (i->items_next) {
printf("--\n");
dump_items(i->items_next);
}
}
static void dump_hashmap_items(Hashmap *h) {
PolicyItem *i;
Iterator j;
char *k;
HASHMAP_FOREACH_KEY(i, k, h, j) {
printf("Item for %s", k);
dump_items(i);
}
}
void policy_dump(Policy *p) {
printf("→ Default Items:\n");
dump_items(p->default_items);
printf("→ Mandatory Items:\n");
printf("→ Group Items:\n");
printf("→ User Items:\n");
exit(0);
}
static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = {
[_POLICY_ITEM_TYPE_UNSET] = "unset",
[POLICY_ITEM_ALLOW] = "allow",
[POLICY_ITEM_DENY] = "deny",
};
static const char* const policy_item_class_table[_POLICY_ITEM_CLASS_MAX] = {
[_POLICY_ITEM_CLASS_UNSET] = "unset",
[POLICY_ITEM_SEND] = "send",
[POLICY_ITEM_RECV] = "recv",
[POLICY_ITEM_OWN] = "own",
[POLICY_ITEM_OWN_PREFIX] = "own-prefix",
[POLICY_ITEM_USER] = "user",
[POLICY_ITEM_GROUP] = "group",
};