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