Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include "alloc-util.h"
4 : : #include "bus-internal.h"
5 : : #include "bus-message.h"
6 : : #include "hexdecoct.h"
7 : : #include "string-util.h"
8 : :
9 : 1443 : bool object_path_is_valid(const char *p) {
10 : : const char *q;
11 : : bool slash;
12 : :
13 [ - + ]: 1443 : if (!p)
14 : 0 : return false;
15 : :
16 [ + + ]: 1443 : if (p[0] != '/')
17 : 12 : return false;
18 : :
19 [ + + ]: 1431 : if (p[1] == 0)
20 : 192 : return true;
21 : :
22 [ + + ]: 16167 : for (slash = true, q = p+1; *q; q++)
23 [ + + ]: 14944 : if (*q == '/') {
24 [ + + ]: 1730 : if (slash)
25 : 12 : return false;
26 : :
27 : 1718 : slash = true;
28 : : } else {
29 : : bool good;
30 : :
31 : 13214 : good =
32 [ - + ]: 12360 : (*q >= 'a' && *q <= 'z') ||
33 [ + + + + ]: 854 : (*q >= 'A' && *q <= 'Z') ||
34 [ + + + + : 26500 : (*q >= '0' && *q <= '9') ||
+ + ]
35 [ + + ]: 72 : *q == '_';
36 : :
37 [ + + ]: 13214 : if (!good)
38 : 4 : return false;
39 : :
40 : 13210 : slash = false;
41 : : }
42 : :
43 [ + + ]: 1223 : if (slash)
44 : 8 : return false;
45 : :
46 : 1215 : return (q - p) <= BUS_PATH_SIZE_MAX;
47 : : }
48 : :
49 : 156 : char* object_path_startswith(const char *a, const char *b) {
50 : : const char *p;
51 : :
52 [ + - ]: 156 : if (!object_path_is_valid(a) ||
53 [ + + ]: 156 : !object_path_is_valid(b))
54 : 4 : return NULL;
55 : :
56 [ + + ]: 152 : if (streq(b, "/"))
57 : 24 : return (char*) a + 1;
58 : :
59 : 128 : p = startswith(a, b);
60 [ + + ]: 128 : if (!p)
61 : 16 : return NULL;
62 : :
63 [ + + ]: 112 : if (*p == 0)
64 : 16 : return (char*) p;
65 : :
66 [ + - ]: 96 : if (*p == '/')
67 : 96 : return (char*) p + 1;
68 : :
69 : 0 : return NULL;
70 : : }
71 : :
72 : 911 : bool interface_name_is_valid(const char *p) {
73 : : const char *q;
74 : 911 : bool dot, found_dot = false;
75 : :
76 [ - + ]: 911 : if (isempty(p))
77 : 0 : return false;
78 : :
79 [ + + ]: 24323 : for (dot = true, q = p; *q; q++)
80 [ + + ]: 23412 : if (*q == '.') {
81 [ - + ]: 2330 : if (dot)
82 : 0 : return false;
83 : :
84 : 2330 : found_dot = dot = true;
85 : : } else {
86 : : bool good;
87 : :
88 : 21082 : good =
89 [ - + ]: 19444 : (*q >= 'a' && *q <= 'z') ||
90 [ + + - + ]: 1638 : (*q >= 'A' && *q <= 'Z') ||
91 [ + + + - : 42164 : (!dot && *q >= '0' && *q <= '9') ||
+ - - + ]
92 [ # # ]: 0 : *q == '_';
93 : :
94 [ - + ]: 21082 : if (!good)
95 : 0 : return false;
96 : :
97 : 21082 : dot = false;
98 : : }
99 : :
100 [ - + ]: 911 : if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
101 : 0 : return false;
102 : :
103 [ - + ]: 911 : if (dot)
104 : 0 : return false;
105 : :
106 [ - + ]: 911 : if (!found_dot)
107 : 0 : return false;
108 : :
109 : 911 : return true;
110 : : }
111 : :
112 : 1152 : bool service_name_is_valid(const char *p) {
113 : : const char *q;
114 : 1152 : bool dot, found_dot = false, unique;
115 : :
116 [ - + ]: 1152 : if (isempty(p))
117 : 0 : return false;
118 : :
119 : 1152 : unique = p[0] == ':';
120 : :
121 [ + + + + ]: 22016 : for (dot = true, q = unique ? p+1 : p; *q; q++)
122 [ + + ]: 20864 : if (*q == '.') {
123 [ - + ]: 2294 : if (dot)
124 : 0 : return false;
125 : :
126 : 2294 : found_dot = dot = true;
127 : : } else {
128 : : bool good;
129 : :
130 : 18570 : good =
131 [ - + ]: 15692 : (*q >= 'a' && *q <= 'z') ||
132 [ + + - + ]: 2878 : (*q >= 'A' && *q <= 'Z') ||
133 [ + + + + : 37148 : ((!dot || unique) && *q >= '0' && *q <= '9') ||
+ - + + -
+ ]
134 [ + - + - ]: 8 : IN_SET(*q, '_', '-');
135 : :
136 [ - + ]: 18570 : if (!good)
137 : 0 : return false;
138 : :
139 : 18570 : dot = false;
140 : : }
141 : :
142 [ - + ]: 1152 : if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
143 : 0 : return false;
144 : :
145 [ - + ]: 1152 : if (dot)
146 : 0 : return false;
147 : :
148 [ - + ]: 1152 : if (!found_dot)
149 : 0 : return false;
150 : :
151 : 1152 : return true;
152 : : }
153 : :
154 : 1407 : bool member_name_is_valid(const char *p) {
155 : : const char *q;
156 : :
157 [ - + ]: 1407 : if (isempty(p))
158 : 0 : return false;
159 : :
160 [ + + ]: 15063 : for (q = p; *q; q++) {
161 : : bool good;
162 : :
163 : 13656 : good =
164 [ - + ]: 11398 : (*q >= 'a' && *q <= 'z') ||
165 [ + + + + ]: 2258 : (*q >= 'A' && *q <= 'Z') ||
166 [ + + + - : 27344 : (*q >= '0' && *q <= '9') ||
+ + ]
167 [ + - ]: 32 : *q == '_';
168 : :
169 [ - + ]: 13656 : if (!good)
170 : 0 : return false;
171 : : }
172 : :
173 [ - + ]: 1407 : if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
174 : 0 : return false;
175 : :
176 : 1407 : return true;
177 : : }
178 : :
179 : : /*
180 : : * Complex pattern match
181 : : * This checks whether @a is a 'complex-prefix' of @b, or @b is a
182 : : * 'complex-prefix' of @a, based on strings that consist of labels with @c as
183 : : * separator. This function returns true if:
184 : : * - both strings are equal
185 : : * - either is a prefix of the other and ends with @c
186 : : * The second rule makes sure that either string needs to be fully included in
187 : : * the other, and the string which is considered the prefix needs to end with a
188 : : * separator.
189 : : */
190 : 88 : static bool complex_pattern_check(char c, const char *a, const char *b) {
191 : 88 : bool separator = false;
192 : :
193 [ - + # # ]: 88 : if (!a && !b)
194 : 0 : return true;
195 : :
196 [ + - - + ]: 88 : if (!a || !b)
197 : 0 : return false;
198 : :
199 : : for (;;) {
200 [ + + ]: 480 : if (*a != *b)
201 [ + + + + : 64 : return (separator && (*a == 0 || *b == 0));
+ - ]
202 : :
203 [ + + ]: 416 : if (*a == 0)
204 : 24 : return true;
205 : :
206 : 392 : separator = *a == c;
207 : :
208 : 392 : a++, b++;
209 : : }
210 : : }
211 : :
212 : 40 : bool namespace_complex_pattern(const char *pattern, const char *value) {
213 : 40 : return complex_pattern_check('.', pattern, value);
214 : : }
215 : :
216 : 48 : bool path_complex_pattern(const char *pattern, const char *value) {
217 : 48 : return complex_pattern_check('/', pattern, value);
218 : : }
219 : :
220 : : /*
221 : : * Simple pattern match
222 : : * This checks whether @a is a 'simple-prefix' of @b, based on strings that
223 : : * consist of labels with @c as separator. This function returns true, if:
224 : : * - if @a and @b are equal
225 : : * - if @a is a prefix of @b, and the first following character in @b (or the
226 : : * last character in @a) is @c
227 : : * The second rule basically makes sure that if @a is a prefix of @b, then @b
228 : : * must follow with a new label separated by @c. It cannot extend the label.
229 : : */
230 : 64 : static bool simple_pattern_check(char c, const char *a, const char *b) {
231 : 64 : bool separator = false;
232 : :
233 [ - + # # ]: 64 : if (!a && !b)
234 : 0 : return true;
235 : :
236 [ + - - + ]: 64 : if (!a || !b)
237 : 0 : return false;
238 : :
239 : : for (;;) {
240 [ + + ]: 340 : if (*a != *b)
241 [ + + + + : 52 : return *a == 0 && (*b == c || separator);
+ + ]
242 : :
243 [ + + ]: 288 : if (*a == 0)
244 : 12 : return true;
245 : :
246 : 276 : separator = *a == c;
247 : :
248 : 276 : a++, b++;
249 : : }
250 : : }
251 : :
252 : 44 : bool namespace_simple_pattern(const char *pattern, const char *value) {
253 : 44 : return simple_pattern_check('.', pattern, value);
254 : : }
255 : :
256 : 20 : bool path_simple_pattern(const char *pattern, const char *value) {
257 : 20 : return simple_pattern_check('/', pattern, value);
258 : : }
259 : :
260 : 136 : int bus_message_type_from_string(const char *s, uint8_t *u) {
261 [ + + ]: 136 : if (streq(s, "signal"))
262 : 132 : *u = SD_BUS_MESSAGE_SIGNAL;
263 [ + - ]: 4 : else if (streq(s, "method_call"))
264 : 4 : *u = SD_BUS_MESSAGE_METHOD_CALL;
265 [ # # ]: 0 : else if (streq(s, "error"))
266 : 0 : *u = SD_BUS_MESSAGE_METHOD_ERROR;
267 [ # # ]: 0 : else if (streq(s, "method_return"))
268 : 0 : *u = SD_BUS_MESSAGE_METHOD_RETURN;
269 : : else
270 : 0 : return -EINVAL;
271 : :
272 : 136 : return 0;
273 : : }
274 : :
275 : 156 : const char *bus_message_type_to_string(uint8_t u) {
276 [ + + ]: 156 : if (u == SD_BUS_MESSAGE_SIGNAL)
277 : 24 : return "signal";
278 [ + + ]: 132 : else if (u == SD_BUS_MESSAGE_METHOD_CALL)
279 : 80 : return "method_call";
280 [ - + ]: 52 : else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
281 : 0 : return "error";
282 [ + - ]: 52 : else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
283 : 52 : return "method_return";
284 : : else
285 : 0 : return NULL;
286 : : }
287 : :
288 : 28 : char *bus_address_escape(const char *v) {
289 : : const char *a;
290 : : char *r, *b;
291 : :
292 : 28 : r = new(char, strlen(v)*3+1);
293 [ - + ]: 28 : if (!r)
294 : 0 : return NULL;
295 : :
296 [ + + ]: 204 : for (a = v, b = r; *a; a++) {
297 : :
298 [ + - + + ]: 176 : if ((*a >= '0' && *a <= '9') ||
299 [ + + - + ]: 160 : (*a >= 'a' && *a <= 'z') ||
300 [ - + # # ]: 48 : (*a >= 'A' && *a <= 'Z') ||
301 [ - + ]: 48 : strchr("_-/.", *a))
302 : 128 : *(b++) = *a;
303 : : else {
304 : 48 : *(b++) = '%';
305 : 48 : *(b++) = hexchar(*a >> 4);
306 : 48 : *(b++) = hexchar(*a & 0xF);
307 : : }
308 : : }
309 : :
310 : 28 : *b = 0;
311 : 28 : return r;
312 : : }
313 : :
314 : 175 : int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
315 [ - + ]: 175 : assert(m);
316 : :
317 [ - + ]: 175 : if (r < 0) {
318 [ # # ]: 0 : if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
319 : 0 : sd_bus_reply_method_errno(m, r, error);
320 : :
321 [ - + ]: 175 : } else if (sd_bus_error_is_set(error)) {
322 [ # # ]: 0 : if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
323 : 0 : sd_bus_reply_method_error(m, error);
324 : : } else
325 : 175 : return r;
326 : :
327 [ # # ]: 0 : log_debug("Failed to process message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s: %s",
328 : : bus_message_type_to_string(m->header->type),
329 : : strna(sd_bus_message_get_sender(m)),
330 : : strna(sd_bus_message_get_destination(m)),
331 : : strna(sd_bus_message_get_path(m)),
332 : : strna(sd_bus_message_get_interface(m)),
333 : : strna(sd_bus_message_get_member(m)),
334 : : BUS_MESSAGE_COOKIE(m),
335 : : m->reply_cookie,
336 : : strna(m->root_container.signature),
337 : : strna(m->error.name),
338 : : strna(m->error.message),
339 : : bus_error_message(error, r));
340 : :
341 : 0 : return 1;
342 : : }
|