bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack/***
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack This file is part of systemd.
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack Copyright 2014 Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack systemd is free software; you can redistribute it and/or modify it
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack under the terms of the GNU Lesser General Public License as published by
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack the Free Software Foundation; either version 2.1 of the License, or
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack (at your option) any later version.
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack systemd is distributed in the hope that it will be useful, but
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack WITHOUT ANY WARRANTY; without even the implied warranty of
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack Lesser General Public License for more details.
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack You should have received a copy of the GNU Lesser General Public License
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack along with systemd; If not, see <http://www.gnu.org/licenses/>.
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack***/
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack#include <stdlib.h>
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "bus-endpoint.h"
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering#include "bus-kernel.h"
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering#include "bus-policy.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "kdbus.h"
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poetteringint bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
b2086f601b313939db160aa028e66649ba81bd01David Herrmann struct kdbus_cmd *update;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering struct kdbus_item *n;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering BusEndpointPolicy *po;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering Iterator i;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering size_t size;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering int r;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
b2086f601b313939db160aa028e66649ba81bd01David Herrmann size = ALIGN8(offsetof(struct kdbus_cmd, items));
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering HASHMAP_FOREACH(po, ep->policy_hash, i) {
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering }
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering update = alloca0_align(size, 8);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering update->size = size;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n = update->items;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering HASHMAP_FOREACH(po, ep->policy_hash, i) {
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->type = KDBUS_ITEM_NAME;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering strcpy(n->str, po->name);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n = KDBUS_ITEM_NEXT(n);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->type = KDBUS_ITEM_POLICY_ACCESS;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->policy_access.type = KDBUS_POLICY_ACCESS_USER;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->policy_access.access = bus_kernel_translate_access(po->access);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n->policy_access.id = uid;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering n = KDBUS_ITEM_NEXT(n);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering }
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update);
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering if (r < 0)
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering return -errno;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering return 0;
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering}
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poettering
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poetteringint bus_endpoint_new(BusEndpoint **ep) {
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack assert(ep);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack *ep = new0(BusEndpoint, 1);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (!*ep)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return -ENOMEM;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return 0;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack}
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poetteringint bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access) {
96f2f3b1b5f44eb59d23d2abeac12b33a18e1e21Philippe De Swert _cleanup_free_ BusEndpointPolicy *po = NULL;
96f2f3b1b5f44eb59d23d2abeac12b33a18e1e21Philippe De Swert _cleanup_free_ char *key = NULL;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack int r;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack assert(ep);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack assert(name);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack assert(access > _BUS_POLICY_ACCESS_INVALID && access < _BUS_POLICY_ACCESS_MAX);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack /* check if we already have this name in the policy list. If we do, see if the new access level
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack * is higher than the exising one, and upgrade the entry in that case. Otherwise, do nothing.
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack */
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (ep->policy_hash) {
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack po = hashmap_get(ep->policy_hash, name);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (po) {
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (po->access < access)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack po->access = access;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return 0;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack }
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack } else {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt ep->policy_hash = hashmap_new(&string_hash_ops);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (!ep->policy_hash)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return -ENOMEM;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack }
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack po = new0(BusEndpointPolicy, 1);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (!po)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return -ENOMEM;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack key = strdup(name);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (!key)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return -ENOMEM;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack po->name = key;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack po->access = access;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack r = hashmap_put(ep->policy_hash, key, po);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (r < 0)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return r;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack po = NULL;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack key = NULL;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return 0;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack}
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
3c70e3bb022f0de3317f3600c9366a2f4597339eLennart Poetteringvoid bus_endpoint_free(BusEndpoint *endpoint) {
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack if (!endpoint)
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack return;
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack hashmap_free_free_free(endpoint->policy_hash);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack free(endpoint);
bb7dd0b04a6e89674100476eed0bbd05c6a4cbd8Daniel Mack}