Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <netdb.h>
4 : #include <nss.h>
5 :
6 : #include "sd-bus.h"
7 : #include "sd-login.h"
8 :
9 : #include "alloc-util.h"
10 : #include "bus-common-errors.h"
11 : #include "env-util.h"
12 : #include "errno-util.h"
13 : #include "format-util.h"
14 : #include "hostname-util.h"
15 : #include "in-addr-util.h"
16 : #include "macro.h"
17 : #include "memory-util.h"
18 : #include "nss-util.h"
19 : #include "signal-util.h"
20 : #include "string-util.h"
21 : #include "user-util.h"
22 :
23 : NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
24 : NSS_GETPW_PROTOTYPES(mymachines);
25 : NSS_GETGR_PROTOTYPES(mymachines);
26 :
27 : #define HOST_UID_LIMIT ((uid_t) UINT32_C(0x10000))
28 : #define HOST_GID_LIMIT ((gid_t) UINT32_C(0x10000))
29 :
30 0 : static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
31 0 : unsigned c = 0;
32 : int r;
33 :
34 0 : assert(m);
35 0 : assert(ret);
36 :
37 0 : while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
38 : int family;
39 :
40 0 : r = sd_bus_message_read(m, "i", &family);
41 0 : if (r < 0)
42 0 : return r;
43 :
44 0 : r = sd_bus_message_skip(m, "ay");
45 0 : if (r < 0)
46 0 : return r;
47 :
48 0 : r = sd_bus_message_exit_container(m);
49 0 : if (r < 0)
50 0 : return r;
51 :
52 0 : if (af != AF_UNSPEC && family != af)
53 0 : continue;
54 :
55 0 : c++;
56 : }
57 0 : if (r < 0)
58 0 : return r;
59 :
60 0 : r = sd_bus_message_rewind(m, false);
61 0 : if (r < 0)
62 0 : return r;
63 :
64 0 : *ret = c;
65 0 : return 0;
66 : }
67 :
68 0 : static bool avoid_deadlock(void) {
69 :
70 : /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager
71 : * code activating systemd-machined.service. After all, we shouldn't synchronously do lookups to
72 : * systemd-machined if we are required to finish before it can be started. This of course won't detect all
73 : * possible dead locks of this kind, but it should work for the most obvious cases. */
74 :
75 0 : if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */
76 0 : return false;
77 :
78 0 : return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-machined.service") &&
79 0 : streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system");
80 : }
81 :
82 0 : enum nss_status _nss_mymachines_gethostbyname4_r(
83 : const char *name,
84 : struct gaih_addrtuple **pat,
85 : char *buffer, size_t buflen,
86 : int *errnop, int *h_errnop,
87 : int32_t *ttlp) {
88 :
89 0 : struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
90 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
91 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
92 0 : _cleanup_free_ int *ifindices = NULL;
93 0 : _cleanup_free_ char *class = NULL;
94 : size_t l, ms, idx;
95 0 : unsigned i = 0, c = 0;
96 : char *r_name;
97 : int n_ifindices, r;
98 :
99 0 : PROTECT_ERRNO;
100 0 : BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
101 :
102 0 : assert(name);
103 0 : assert(pat);
104 0 : assert(buffer);
105 0 : assert(errnop);
106 0 : assert(h_errnop);
107 :
108 0 : r = sd_machine_get_class(name, &class);
109 0 : if (r < 0)
110 0 : goto fail;
111 0 : if (!streq(class, "container")) {
112 0 : r = -ENOTTY;
113 0 : goto fail;
114 : }
115 :
116 0 : n_ifindices = sd_machine_get_ifindices(name, &ifindices);
117 0 : if (n_ifindices < 0) {
118 0 : r = n_ifindices;
119 0 : goto fail;
120 : }
121 :
122 0 : if (avoid_deadlock()) {
123 0 : r = -EDEADLK;
124 0 : goto fail;
125 : }
126 :
127 0 : r = sd_bus_open_system(&bus);
128 0 : if (r < 0)
129 0 : goto fail;
130 :
131 0 : r = sd_bus_call_method(bus,
132 : "org.freedesktop.machine1",
133 : "/org/freedesktop/machine1",
134 : "org.freedesktop.machine1.Manager",
135 : "GetMachineAddresses",
136 : NULL,
137 : &reply,
138 : "s", name);
139 0 : if (r < 0)
140 0 : goto fail;
141 :
142 0 : r = sd_bus_message_enter_container(reply, 'a', "(iay)");
143 0 : if (r < 0)
144 0 : goto fail;
145 :
146 0 : r = count_addresses(reply, AF_UNSPEC, &c);
147 0 : if (r < 0)
148 0 : goto fail;
149 :
150 0 : if (c <= 0) {
151 0 : *h_errnop = HOST_NOT_FOUND;
152 0 : return NSS_STATUS_NOTFOUND;
153 : }
154 :
155 0 : l = strlen(name);
156 0 : ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
157 0 : if (buflen < ms) {
158 0 : UNPROTECT_ERRNO;
159 0 : *errnop = ERANGE;
160 0 : *h_errnop = NETDB_INTERNAL;
161 0 : return NSS_STATUS_TRYAGAIN;
162 : }
163 :
164 : /* First, append name */
165 0 : r_name = buffer;
166 0 : memcpy(r_name, name, l+1);
167 0 : idx = ALIGN(l+1);
168 :
169 : /* Second, append addresses */
170 0 : r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
171 0 : while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
172 : int family;
173 : const void *a;
174 : size_t sz;
175 :
176 0 : r = sd_bus_message_read(reply, "i", &family);
177 0 : if (r < 0)
178 0 : goto fail;
179 :
180 0 : r = sd_bus_message_read_array(reply, 'y', &a, &sz);
181 0 : if (r < 0)
182 0 : goto fail;
183 :
184 0 : r = sd_bus_message_exit_container(reply);
185 0 : if (r < 0)
186 0 : goto fail;
187 :
188 0 : if (!IN_SET(family, AF_INET, AF_INET6)) {
189 0 : r = -EAFNOSUPPORT;
190 0 : goto fail;
191 : }
192 :
193 0 : if (sz != FAMILY_ADDRESS_SIZE(family)) {
194 0 : r = -EINVAL;
195 0 : goto fail;
196 : }
197 :
198 0 : r_tuple = (struct gaih_addrtuple*) (buffer + idx);
199 0 : r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
200 0 : r_tuple->name = r_name;
201 0 : r_tuple->family = family;
202 0 : r_tuple->scopeid = n_ifindices == 1 ? ifindices[0] : 0;
203 0 : memcpy(r_tuple->addr, a, sz);
204 :
205 0 : idx += ALIGN(sizeof(struct gaih_addrtuple));
206 0 : i++;
207 : }
208 :
209 0 : assert(i == c);
210 :
211 0 : r = sd_bus_message_exit_container(reply);
212 0 : if (r < 0)
213 0 : goto fail;
214 :
215 0 : assert(idx == ms);
216 :
217 0 : if (*pat)
218 0 : **pat = *r_tuple_first;
219 : else
220 0 : *pat = r_tuple_first;
221 :
222 0 : if (ttlp)
223 0 : *ttlp = 0;
224 :
225 : /* Explicitly reset both *h_errnop and h_errno to work around
226 : * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
227 0 : *h_errnop = NETDB_SUCCESS;
228 0 : h_errno = 0;
229 :
230 0 : return NSS_STATUS_SUCCESS;
231 :
232 0 : fail:
233 0 : UNPROTECT_ERRNO;
234 0 : *errnop = -r;
235 0 : *h_errnop = NO_RECOVERY;
236 0 : return NSS_STATUS_UNAVAIL;
237 : }
238 :
239 0 : enum nss_status _nss_mymachines_gethostbyname3_r(
240 : const char *name,
241 : int af,
242 : struct hostent *result,
243 : char *buffer, size_t buflen,
244 : int *errnop, int *h_errnop,
245 : int32_t *ttlp,
246 : char **canonp) {
247 :
248 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
249 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
250 0 : _cleanup_free_ char *class = NULL;
251 0 : unsigned c = 0, i = 0;
252 : char *r_name, *r_aliases, *r_addr, *r_addr_list;
253 : size_t l, idx, ms, alen;
254 : int r;
255 :
256 0 : PROTECT_ERRNO;
257 0 : BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
258 :
259 0 : assert(name);
260 0 : assert(result);
261 0 : assert(buffer);
262 0 : assert(errnop);
263 0 : assert(h_errnop);
264 :
265 0 : if (af == AF_UNSPEC)
266 0 : af = AF_INET;
267 :
268 0 : if (af != AF_INET && af != AF_INET6) {
269 0 : r = -EAFNOSUPPORT;
270 0 : goto fail;
271 : }
272 :
273 0 : r = sd_machine_get_class(name, &class);
274 0 : if (r < 0)
275 0 : goto fail;
276 0 : if (!streq(class, "container")) {
277 0 : r = -ENOTTY;
278 0 : goto fail;
279 : }
280 :
281 0 : if (avoid_deadlock()) {
282 0 : r = -EDEADLK;
283 0 : goto fail;
284 : }
285 :
286 0 : r = sd_bus_open_system(&bus);
287 0 : if (r < 0)
288 0 : goto fail;
289 :
290 0 : r = sd_bus_call_method(bus,
291 : "org.freedesktop.machine1",
292 : "/org/freedesktop/machine1",
293 : "org.freedesktop.machine1.Manager",
294 : "GetMachineAddresses",
295 : NULL,
296 : &reply,
297 : "s", name);
298 0 : if (r < 0)
299 0 : goto fail;
300 :
301 0 : r = sd_bus_message_enter_container(reply, 'a', "(iay)");
302 0 : if (r < 0)
303 0 : goto fail;
304 :
305 0 : r = count_addresses(reply, af, &c);
306 0 : if (r < 0)
307 0 : goto fail;
308 :
309 0 : if (c <= 0) {
310 0 : *h_errnop = HOST_NOT_FOUND;
311 0 : return NSS_STATUS_NOTFOUND;
312 : }
313 :
314 0 : alen = FAMILY_ADDRESS_SIZE(af);
315 0 : l = strlen(name);
316 :
317 0 : ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
318 :
319 0 : if (buflen < ms) {
320 0 : UNPROTECT_ERRNO;
321 0 : *errnop = ERANGE;
322 0 : *h_errnop = NETDB_INTERNAL;
323 0 : return NSS_STATUS_TRYAGAIN;
324 : }
325 :
326 : /* First, append name */
327 0 : r_name = buffer;
328 0 : memcpy(r_name, name, l+1);
329 0 : idx = ALIGN(l+1);
330 :
331 : /* Second, create aliases array */
332 0 : r_aliases = buffer + idx;
333 0 : ((char**) r_aliases)[0] = NULL;
334 0 : idx += sizeof(char*);
335 :
336 : /* Third, append addresses */
337 0 : r_addr = buffer + idx;
338 0 : while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
339 : int family;
340 : const void *a;
341 : size_t sz;
342 :
343 0 : r = sd_bus_message_read(reply, "i", &family);
344 0 : if (r < 0)
345 0 : goto fail;
346 :
347 0 : r = sd_bus_message_read_array(reply, 'y', &a, &sz);
348 0 : if (r < 0)
349 0 : goto fail;
350 :
351 0 : r = sd_bus_message_exit_container(reply);
352 0 : if (r < 0)
353 0 : goto fail;
354 :
355 0 : if (family != af)
356 0 : continue;
357 :
358 0 : if (sz != alen) {
359 0 : r = -EINVAL;
360 0 : goto fail;
361 : }
362 :
363 0 : memcpy(r_addr + i*ALIGN(alen), a, alen);
364 0 : i++;
365 : }
366 :
367 0 : assert(i == c);
368 0 : idx += c * ALIGN(alen);
369 :
370 0 : r = sd_bus_message_exit_container(reply);
371 0 : if (r < 0)
372 0 : goto fail;
373 :
374 : /* Third, append address pointer array */
375 0 : r_addr_list = buffer + idx;
376 0 : for (i = 0; i < c; i++)
377 0 : ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
378 :
379 0 : ((char**) r_addr_list)[i] = NULL;
380 0 : idx += (c+1) * sizeof(char*);
381 :
382 0 : assert(idx == ms);
383 :
384 0 : result->h_name = r_name;
385 0 : result->h_aliases = (char**) r_aliases;
386 0 : result->h_addrtype = af;
387 0 : result->h_length = alen;
388 0 : result->h_addr_list = (char**) r_addr_list;
389 :
390 0 : if (ttlp)
391 0 : *ttlp = 0;
392 :
393 0 : if (canonp)
394 0 : *canonp = r_name;
395 :
396 : /* Explicitly reset both *h_errnop and h_errno to work around
397 : * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
398 0 : *h_errnop = NETDB_SUCCESS;
399 0 : h_errno = 0;
400 :
401 0 : return NSS_STATUS_SUCCESS;
402 :
403 0 : fail:
404 0 : UNPROTECT_ERRNO;
405 0 : *errnop = -r;
406 0 : *h_errnop = NO_RECOVERY;
407 0 : return NSS_STATUS_UNAVAIL;
408 : }
409 :
410 0 : NSS_GETHOSTBYNAME_FALLBACKS(mymachines);
411 :
412 0 : enum nss_status _nss_mymachines_getpwnam_r(
413 : const char *name,
414 : struct passwd *pwd,
415 : char *buffer, size_t buflen,
416 : int *errnop) {
417 :
418 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
419 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
420 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
421 : const char *p, *e, *machine;
422 : uint32_t mapped;
423 : uid_t uid;
424 : size_t l;
425 : int r;
426 :
427 0 : PROTECT_ERRNO;
428 0 : BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
429 :
430 0 : assert(name);
431 0 : assert(pwd);
432 :
433 0 : p = startswith(name, "vu-");
434 0 : if (!p)
435 0 : return NSS_STATUS_NOTFOUND;
436 :
437 0 : e = strrchr(p, '-');
438 0 : if (!e || e == p)
439 0 : return NSS_STATUS_NOTFOUND;
440 :
441 0 : if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
442 0 : return NSS_STATUS_NOTFOUND;
443 :
444 0 : r = parse_uid(e + 1, &uid);
445 0 : if (r < 0)
446 0 : return NSS_STATUS_NOTFOUND;
447 :
448 0 : machine = strndupa(p, e - p);
449 0 : if (!machine_name_is_valid(machine))
450 0 : return NSS_STATUS_NOTFOUND;
451 :
452 0 : if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
453 : /* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve
454 : * these UIDs, but that should be unproblematic as containers should never be able to connect to a bus
455 : * running on the host. */
456 0 : return NSS_STATUS_NOTFOUND;
457 :
458 0 : if (avoid_deadlock()) {
459 0 : r = -EDEADLK;
460 0 : goto fail;
461 : }
462 :
463 0 : r = sd_bus_open_system(&bus);
464 0 : if (r < 0)
465 0 : goto fail;
466 :
467 0 : r = sd_bus_call_method(bus,
468 : "org.freedesktop.machine1",
469 : "/org/freedesktop/machine1",
470 : "org.freedesktop.machine1.Manager",
471 : "MapFromMachineUser",
472 : &error,
473 : &reply,
474 : "su",
475 : machine, (uint32_t) uid);
476 0 : if (r < 0) {
477 0 : if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
478 0 : return NSS_STATUS_NOTFOUND;
479 :
480 0 : goto fail;
481 : }
482 :
483 0 : r = sd_bus_message_read(reply, "u", &mapped);
484 0 : if (r < 0)
485 0 : goto fail;
486 :
487 : /* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */
488 0 : if (mapped < HOST_UID_LIMIT || mapped == uid)
489 0 : return NSS_STATUS_NOTFOUND;
490 :
491 0 : l = strlen(name);
492 0 : if (buflen < l+1) {
493 0 : UNPROTECT_ERRNO;
494 0 : *errnop = ERANGE;
495 0 : return NSS_STATUS_TRYAGAIN;
496 : }
497 :
498 0 : memcpy(buffer, name, l+1);
499 :
500 0 : pwd->pw_name = buffer;
501 0 : pwd->pw_uid = mapped;
502 0 : pwd->pw_gid = GID_NOBODY;
503 0 : pwd->pw_gecos = buffer;
504 0 : pwd->pw_passwd = (char*) "*"; /* locked */
505 0 : pwd->pw_dir = (char*) "/";
506 0 : pwd->pw_shell = (char*) NOLOGIN;
507 :
508 0 : return NSS_STATUS_SUCCESS;
509 :
510 0 : fail:
511 0 : UNPROTECT_ERRNO;
512 0 : *errnop = -r;
513 0 : return NSS_STATUS_UNAVAIL;
514 : }
515 :
516 0 : enum nss_status _nss_mymachines_getpwuid_r(
517 : uid_t uid,
518 : struct passwd *pwd,
519 : char *buffer, size_t buflen,
520 : int *errnop) {
521 :
522 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
523 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
524 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
525 : const char *machine;
526 : uint32_t mapped;
527 : int r;
528 :
529 0 : PROTECT_ERRNO;
530 0 : BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
531 :
532 0 : if (!uid_is_valid(uid))
533 0 : return NSS_STATUS_NOTFOUND;
534 :
535 : /* We consider all uids < 65536 host uids */
536 0 : if (uid < HOST_UID_LIMIT)
537 0 : return NSS_STATUS_NOTFOUND;
538 :
539 0 : if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
540 0 : return NSS_STATUS_NOTFOUND;
541 :
542 0 : if (avoid_deadlock()) {
543 0 : r = -EDEADLK;
544 0 : goto fail;
545 : }
546 :
547 0 : r = sd_bus_open_system(&bus);
548 0 : if (r < 0)
549 0 : goto fail;
550 :
551 0 : r = sd_bus_call_method(bus,
552 : "org.freedesktop.machine1",
553 : "/org/freedesktop/machine1",
554 : "org.freedesktop.machine1.Manager",
555 : "MapToMachineUser",
556 : &error,
557 : &reply,
558 : "u",
559 : (uint32_t) uid);
560 0 : if (r < 0) {
561 0 : if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
562 0 : return NSS_STATUS_NOTFOUND;
563 :
564 0 : goto fail;
565 : }
566 :
567 0 : r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped);
568 0 : if (r < 0)
569 0 : goto fail;
570 :
571 0 : if (mapped == uid)
572 0 : return NSS_STATUS_NOTFOUND;
573 :
574 0 : if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
575 0 : UNPROTECT_ERRNO;
576 0 : *errnop = ERANGE;
577 0 : return NSS_STATUS_TRYAGAIN;
578 : }
579 :
580 0 : pwd->pw_name = buffer;
581 0 : pwd->pw_uid = uid;
582 0 : pwd->pw_gid = GID_NOBODY;
583 0 : pwd->pw_gecos = buffer;
584 0 : pwd->pw_passwd = (char*) "*"; /* locked */
585 0 : pwd->pw_dir = (char*) "/";
586 0 : pwd->pw_shell = (char*) NOLOGIN;
587 :
588 0 : return NSS_STATUS_SUCCESS;
589 :
590 0 : fail:
591 0 : UNPROTECT_ERRNO;
592 0 : *errnop = -r;
593 0 : return NSS_STATUS_UNAVAIL;
594 : }
595 :
596 : #pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess"
597 :
598 0 : enum nss_status _nss_mymachines_getgrnam_r(
599 : const char *name,
600 : struct group *gr,
601 : char *buffer, size_t buflen,
602 : int *errnop) {
603 :
604 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
605 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
606 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
607 : const char *p, *e, *machine;
608 : uint32_t mapped;
609 : uid_t gid;
610 : size_t l;
611 : int r;
612 :
613 0 : PROTECT_ERRNO;
614 0 : BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
615 :
616 0 : assert(name);
617 0 : assert(gr);
618 :
619 0 : p = startswith(name, "vg-");
620 0 : if (!p)
621 0 : return NSS_STATUS_NOTFOUND;
622 :
623 0 : e = strrchr(p, '-');
624 0 : if (!e || e == p)
625 0 : return NSS_STATUS_NOTFOUND;
626 :
627 0 : if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
628 0 : return NSS_STATUS_NOTFOUND;
629 :
630 0 : r = parse_gid(e + 1, &gid);
631 0 : if (r < 0)
632 0 : return NSS_STATUS_NOTFOUND;
633 :
634 0 : machine = strndupa(p, e - p);
635 0 : if (!machine_name_is_valid(machine))
636 0 : return NSS_STATUS_NOTFOUND;
637 :
638 0 : if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
639 0 : return NSS_STATUS_NOTFOUND;
640 :
641 0 : if (avoid_deadlock()) {
642 0 : r = -EDEADLK;
643 0 : goto fail;
644 : }
645 :
646 0 : r = sd_bus_open_system(&bus);
647 0 : if (r < 0)
648 0 : goto fail;
649 :
650 0 : r = sd_bus_call_method(bus,
651 : "org.freedesktop.machine1",
652 : "/org/freedesktop/machine1",
653 : "org.freedesktop.machine1.Manager",
654 : "MapFromMachineGroup",
655 : &error,
656 : &reply,
657 : "su",
658 : machine, (uint32_t) gid);
659 0 : if (r < 0) {
660 0 : if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
661 0 : return NSS_STATUS_NOTFOUND;
662 :
663 0 : goto fail;
664 : }
665 :
666 0 : r = sd_bus_message_read(reply, "u", &mapped);
667 0 : if (r < 0)
668 0 : goto fail;
669 :
670 0 : if (mapped < HOST_GID_LIMIT || mapped == gid)
671 0 : return NSS_STATUS_NOTFOUND;
672 :
673 0 : l = sizeof(char*) + strlen(name) + 1;
674 0 : if (buflen < l) {
675 0 : UNPROTECT_ERRNO;
676 0 : *errnop = ERANGE;
677 0 : return NSS_STATUS_TRYAGAIN;
678 : }
679 :
680 0 : memzero(buffer, sizeof(char*));
681 0 : strcpy(buffer + sizeof(char*), name);
682 :
683 0 : gr->gr_name = buffer + sizeof(char*);
684 0 : gr->gr_gid = mapped;
685 0 : gr->gr_passwd = (char*) "*"; /* locked */
686 0 : gr->gr_mem = (char**) buffer;
687 :
688 0 : return NSS_STATUS_SUCCESS;
689 :
690 0 : fail:
691 0 : UNPROTECT_ERRNO;
692 0 : *errnop = -r;
693 0 : return NSS_STATUS_UNAVAIL;
694 : }
695 :
696 0 : enum nss_status _nss_mymachines_getgrgid_r(
697 : gid_t gid,
698 : struct group *gr,
699 : char *buffer, size_t buflen,
700 : int *errnop) {
701 :
702 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
703 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
704 0 : _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
705 : const char *machine;
706 : uint32_t mapped;
707 : int r;
708 :
709 0 : PROTECT_ERRNO;
710 0 : BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
711 :
712 0 : if (!gid_is_valid(gid))
713 0 : return NSS_STATUS_NOTFOUND;
714 :
715 : /* We consider all gids < 65536 host gids */
716 0 : if (gid < HOST_GID_LIMIT)
717 0 : return NSS_STATUS_NOTFOUND;
718 :
719 0 : if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
720 0 : return NSS_STATUS_NOTFOUND;
721 :
722 0 : if (avoid_deadlock()) {
723 0 : r = -EDEADLK;
724 0 : goto fail;
725 : }
726 :
727 0 : r = sd_bus_open_system(&bus);
728 0 : if (r < 0)
729 0 : goto fail;
730 :
731 0 : r = sd_bus_call_method(bus,
732 : "org.freedesktop.machine1",
733 : "/org/freedesktop/machine1",
734 : "org.freedesktop.machine1.Manager",
735 : "MapToMachineGroup",
736 : &error,
737 : &reply,
738 : "u",
739 : (uint32_t) gid);
740 0 : if (r < 0) {
741 0 : if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
742 0 : return NSS_STATUS_NOTFOUND;
743 :
744 0 : goto fail;
745 : }
746 :
747 0 : r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped);
748 0 : if (r < 0)
749 0 : goto fail;
750 :
751 0 : if (mapped == gid)
752 0 : return NSS_STATUS_NOTFOUND;
753 :
754 0 : if (buflen < sizeof(char*) + 1) {
755 0 : UNPROTECT_ERRNO;
756 0 : *errnop = ERANGE;
757 0 : return NSS_STATUS_TRYAGAIN;
758 : }
759 :
760 0 : memzero(buffer, sizeof(char*));
761 0 : if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) {
762 0 : UNPROTECT_ERRNO;
763 0 : *errnop = ERANGE;
764 0 : return NSS_STATUS_TRYAGAIN;
765 : }
766 :
767 0 : gr->gr_name = buffer + sizeof(char*);
768 0 : gr->gr_gid = gid;
769 0 : gr->gr_passwd = (char*) "*"; /* locked */
770 0 : gr->gr_mem = (char**) buffer;
771 :
772 0 : return NSS_STATUS_SUCCESS;
773 :
774 0 : fail:
775 0 : UNPROTECT_ERRNO;
776 0 : *errnop = -r;
777 0 : return NSS_STATUS_UNAVAIL;
778 : }
|