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