]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/bus-policy.c
util-lib: move string table stuff into its own string-table.[ch]
[thirdparty/systemd.git] / src / core / bus-policy.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Daniel Mack
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdlib.h>
21
22 #include "bus-kernel.h"
23 #include "bus-policy.h"
24 #include "kdbus.h"
25 #include "string-table.h"
26 #include "user-util.h"
27 #include "util.h"
28
29 int bus_kernel_translate_access(BusPolicyAccess access) {
30 assert(access >= 0);
31 assert(access < _BUS_POLICY_ACCESS_MAX);
32
33 switch (access) {
34
35 case BUS_POLICY_ACCESS_SEE:
36 return KDBUS_POLICY_SEE;
37
38 case BUS_POLICY_ACCESS_TALK:
39 return KDBUS_POLICY_TALK;
40
41 case BUS_POLICY_ACCESS_OWN:
42 return KDBUS_POLICY_OWN;
43
44 default:
45 assert_not_reached("Unknown policy access");
46 }
47 }
48
49 int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
50 int r;
51
52 assert(policy);
53 assert(item);
54
55 switch (policy->type) {
56
57 case BUSNAME_POLICY_TYPE_USER: {
58 const char *user = policy->name;
59 uid_t uid;
60
61 r = get_user_creds(&user, &uid, NULL, NULL, NULL);
62 if (r < 0)
63 return r;
64
65 item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
66 item->policy_access.id = uid;
67 break;
68 }
69
70 case BUSNAME_POLICY_TYPE_GROUP: {
71 const char *group = policy->name;
72 gid_t gid;
73
74 r = get_group_creds(&group, &gid);
75 if (r < 0)
76 return r;
77
78 item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
79 item->policy_access.id = gid;
80 break;
81 }
82
83 default:
84 assert_not_reached("Unknown policy type");
85 }
86
87 item->policy_access.access = bus_kernel_translate_access(policy->access);
88
89 return 0;
90 }
91
92 int bus_kernel_make_starter(
93 int fd,
94 const char *name,
95 bool activating,
96 bool accept_fd,
97 BusNamePolicy *policy,
98 BusPolicyAccess world_policy) {
99
100 struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) };
101 struct kdbus_cmd_hello *hello;
102 struct kdbus_item *n;
103 size_t policy_cnt = 0;
104 BusNamePolicy *po;
105 size_t size;
106 int r;
107
108 assert(fd >= 0);
109 assert(name);
110
111 LIST_FOREACH(policy, po, policy)
112 policy_cnt++;
113
114 if (world_policy >= 0)
115 policy_cnt++;
116
117 size = offsetof(struct kdbus_cmd_hello, items) +
118 ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) +
119 policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
120
121 hello = alloca0_align(size, 8);
122
123 n = hello->items;
124 strcpy(n->str, name);
125 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
126 n->type = KDBUS_ITEM_NAME;
127 n = KDBUS_ITEM_NEXT(n);
128
129 LIST_FOREACH(policy, po, policy) {
130 n->type = KDBUS_ITEM_POLICY_ACCESS;
131 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
132
133 r = bus_kernel_translate_policy(po, n);
134 if (r < 0)
135 return r;
136
137 n = KDBUS_ITEM_NEXT(n);
138 }
139
140 if (world_policy >= 0) {
141 n->type = KDBUS_ITEM_POLICY_ACCESS;
142 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
143 n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
144 n->policy_access.access = bus_kernel_translate_access(world_policy);
145 }
146
147 hello->size = size;
148 hello->flags =
149 (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
150 (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
151 hello->pool_size = KDBUS_POOL_SIZE;
152 hello->attach_flags_send = _KDBUS_ATTACH_ANY;
153 hello->attach_flags_recv = _KDBUS_ATTACH_ANY;
154
155 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
156 if (errno == ENOTTY) /* Major API change */
157 return -ESOCKTNOSUPPORT;
158 return -errno;
159 }
160
161 /* not interested in any output values */
162 cmd_free.offset = hello->offset;
163 (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free);
164
165 /* The higher 32bit of the bus_flags fields are considered
166 * 'incompatible flags'. Refuse them all for now. */
167 if (hello->bus_flags > 0xFFFFFFFFULL)
168 return -ESOCKTNOSUPPORT;
169
170 return fd;
171 }
172
173 static const char* const bus_policy_access_table[_BUS_POLICY_ACCESS_MAX] = {
174 [BUS_POLICY_ACCESS_SEE] = "see",
175 [BUS_POLICY_ACCESS_TALK] = "talk",
176 [BUS_POLICY_ACCESS_OWN] = "own",
177 };
178
179 DEFINE_STRING_TABLE_LOOKUP(bus_policy_access, BusPolicyAccess);