1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "bus-common-errors.h"
30 #include "hostname-util.h"
31 #include "in-addr-util.h"
34 #include "string-util.h"
37 NSS_GETHOSTBYNAME_PROTOTYPES(mymachines
);
38 NSS_GETPW_PROTOTYPES(mymachines
);
39 NSS_GETGR_PROTOTYPES(mymachines
);
41 static int count_addresses(sd_bus_message
*m
, int af
, unsigned *ret
) {
48 while ((r
= sd_bus_message_enter_container(m
, 'r', "iay")) > 0) {
51 r
= sd_bus_message_read(m
, "i", &family
);
55 r
= sd_bus_message_skip(m
, "ay");
59 r
= sd_bus_message_exit_container(m
);
63 if (af
!= AF_UNSPEC
&& family
!= af
)
71 r
= sd_bus_message_rewind(m
, false);
79 enum nss_status
_nss_mymachines_gethostbyname4_r(
81 struct gaih_addrtuple
**pat
,
82 char *buffer
, size_t buflen
,
83 int *errnop
, int *h_errnop
,
86 struct gaih_addrtuple
*r_tuple
, *r_tuple_first
= NULL
;
87 _cleanup_bus_message_unref_ sd_bus_message
* reply
= NULL
;
88 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
89 _cleanup_free_
int *ifindices
= NULL
;
90 _cleanup_free_
char *class = NULL
;
92 unsigned i
= 0, c
= 0;
102 r
= sd_machine_get_class(name
, &class);
105 if (!streq(class, "container")) {
110 n_ifindices
= sd_machine_get_ifindices(name
, &ifindices
);
111 if (n_ifindices
< 0) {
116 r
= sd_bus_open_system(&bus
);
120 r
= sd_bus_call_method(bus
,
121 "org.freedesktop.machine1",
122 "/org/freedesktop/machine1",
123 "org.freedesktop.machine1.Manager",
124 "GetMachineAddresses",
131 r
= sd_bus_message_enter_container(reply
, 'a', "(iay)");
135 r
= count_addresses(reply
, AF_UNSPEC
, &c
);
141 *h_errnop
= HOST_NOT_FOUND
;
142 return NSS_STATUS_NOTFOUND
;
146 ms
= ALIGN(l
+1) + ALIGN(sizeof(struct gaih_addrtuple
)) * c
;
149 *h_errnop
= TRY_AGAIN
;
150 return NSS_STATUS_TRYAGAIN
;
153 /* First, append name */
155 memcpy(r_name
, name
, l
+1);
158 /* Second, append addresses */
159 r_tuple_first
= (struct gaih_addrtuple
*) (buffer
+ idx
);
160 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iay")) > 0) {
165 r
= sd_bus_message_read(reply
, "i", &family
);
169 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
173 r
= sd_bus_message_exit_container(reply
);
177 if (!IN_SET(family
, AF_INET
, AF_INET6
)) {
182 if (sz
!= FAMILY_ADDRESS_SIZE(family
)) {
187 r_tuple
= (struct gaih_addrtuple
*) (buffer
+ idx
);
188 r_tuple
->next
= i
== c
-1 ? NULL
: (struct gaih_addrtuple
*) ((char*) r_tuple
+ ALIGN(sizeof(struct gaih_addrtuple
)));
189 r_tuple
->name
= r_name
;
190 r_tuple
->family
= family
;
191 r_tuple
->scopeid
= n_ifindices
== 1 ? ifindices
[0] : 0;
192 memcpy(r_tuple
->addr
, a
, sz
);
194 idx
+= ALIGN(sizeof(struct gaih_addrtuple
));
200 r
= sd_bus_message_exit_container(reply
);
207 **pat
= *r_tuple_first
;
209 *pat
= r_tuple_first
;
214 /* Explicitly reset all error variables */
216 *h_errnop
= NETDB_SUCCESS
;
219 return NSS_STATUS_SUCCESS
;
224 return NSS_STATUS_UNAVAIL
;
227 enum nss_status
_nss_mymachines_gethostbyname3_r(
230 struct hostent
*result
,
231 char *buffer
, size_t buflen
,
232 int *errnop
, int *h_errnop
,
236 _cleanup_bus_message_unref_ sd_bus_message
* reply
= NULL
;
237 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
238 _cleanup_free_
char *class = NULL
;
239 unsigned c
= 0, i
= 0;
240 char *r_name
, *r_aliases
, *r_addr
, *r_addr_list
;
241 size_t l
, idx
, ms
, alen
;
253 if (af
!= AF_INET
&& af
!= AF_INET6
) {
258 r
= sd_machine_get_class(name
, &class);
261 if (!streq(class, "container")) {
266 r
= sd_bus_open_system(&bus
);
270 r
= sd_bus_call_method(bus
,
271 "org.freedesktop.machine1",
272 "/org/freedesktop/machine1",
273 "org.freedesktop.machine1.Manager",
274 "GetMachineAddresses",
281 r
= sd_bus_message_enter_container(reply
, 'a', "(iay)");
285 r
= count_addresses(reply
, af
, &c
);
291 *h_errnop
= HOST_NOT_FOUND
;
292 return NSS_STATUS_NOTFOUND
;
295 alen
= FAMILY_ADDRESS_SIZE(af
);
298 ms
= ALIGN(l
+1) + c
* ALIGN(alen
) + (c
+2) * sizeof(char*);
302 *h_errnop
= NO_RECOVERY
;
303 return NSS_STATUS_TRYAGAIN
;
306 /* First, append name */
308 memcpy(r_name
, name
, l
+1);
311 /* Second, create aliases array */
312 r_aliases
= buffer
+ idx
;
313 ((char**) r_aliases
)[0] = NULL
;
314 idx
+= sizeof(char*);
316 /* Third, append addresses */
317 r_addr
= buffer
+ idx
;
318 while ((r
= sd_bus_message_enter_container(reply
, 'r', "iay")) > 0) {
323 r
= sd_bus_message_read(reply
, "i", &family
);
327 r
= sd_bus_message_read_array(reply
, 'y', &a
, &sz
);
331 r
= sd_bus_message_exit_container(reply
);
343 memcpy(r_addr
+ i
*ALIGN(alen
), a
, alen
);
348 idx
+= c
* ALIGN(alen
);
350 r
= sd_bus_message_exit_container(reply
);
354 /* Third, append address pointer array */
355 r_addr_list
= buffer
+ idx
;
356 for (i
= 0; i
< c
; i
++)
357 ((char**) r_addr_list
)[i
] = r_addr
+ i
*ALIGN(alen
);
359 ((char**) r_addr_list
)[i
] = NULL
;
360 idx
+= (c
+1) * sizeof(char*);
364 result
->h_name
= r_name
;
365 result
->h_aliases
= (char**) r_aliases
;
366 result
->h_addrtype
= af
;
367 result
->h_length
= alen
;
368 result
->h_addr_list
= (char**) r_addr_list
;
376 /* Explicitly reset all error variables */
378 *h_errnop
= NETDB_SUCCESS
;
381 return NSS_STATUS_SUCCESS
;
386 return NSS_STATUS_UNAVAIL
;
389 NSS_GETHOSTBYNAME_FALLBACKS(mymachines
);
391 enum nss_status
_nss_mymachines_getpwnam_r(
394 char *buffer
, size_t buflen
,
397 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
398 _cleanup_bus_message_unref_ sd_bus_message
* reply
= NULL
;
399 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
400 const char *p
, *e
, *machine
;
409 p
= startswith(name
, "vu-");
417 r
= parse_uid(e
+ 1, &uid
);
421 machine
= strndupa(p
, e
- p
);
422 if (!machine_name_is_valid(machine
))
425 r
= sd_bus_open_system(&bus
);
429 r
= sd_bus_call_method(bus
,
430 "org.freedesktop.machine1",
431 "/org/freedesktop/machine1",
432 "org.freedesktop.machine1.Manager",
433 "MapFromMachineUser",
437 machine
, (uint32_t) uid
);
439 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_USER_MAPPING
))
445 r
= sd_bus_message_read(reply
, "u", &mapped
);
452 return NSS_STATUS_TRYAGAIN
;
455 memcpy(buffer
, name
, l
+1);
457 pwd
->pw_name
= buffer
;
458 pwd
->pw_uid
= mapped
;
459 pwd
->pw_gid
= 65534; /* nobody */
460 pwd
->pw_gecos
= buffer
;
461 pwd
->pw_passwd
= (char*) "*"; /* locked */
462 pwd
->pw_dir
= (char*) "/";
463 pwd
->pw_shell
= (char*) "/sbin/nologin";
466 return NSS_STATUS_SUCCESS
;
470 return NSS_STATUS_NOTFOUND
;
474 return NSS_STATUS_UNAVAIL
;
477 enum nss_status
_nss_mymachines_getpwuid_r(
480 char *buffer
, size_t buflen
,
483 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
484 _cleanup_bus_message_unref_ sd_bus_message
* reply
= NULL
;
485 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
486 const char *machine
, *object
;
490 if (!uid_is_valid(uid
)) {
495 /* We consider all uids < 65536 host uids */
499 r
= sd_bus_open_system(&bus
);
503 r
= sd_bus_call_method(bus
,
504 "org.freedesktop.machine1",
505 "/org/freedesktop/machine1",
506 "org.freedesktop.machine1.Manager",
513 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_USER_MAPPING
))
519 r
= sd_bus_message_read(reply
, "sou", &machine
, &object
, &mapped
);
523 if (snprintf(buffer
, buflen
, "vu-%s-" UID_FMT
, machine
, (uid_t
) mapped
) >= (int) buflen
) {
525 return NSS_STATUS_TRYAGAIN
;
528 pwd
->pw_name
= buffer
;
530 pwd
->pw_gid
= 65534; /* nobody */
531 pwd
->pw_gecos
= buffer
;
532 pwd
->pw_passwd
= (char*) "*"; /* locked */
533 pwd
->pw_dir
= (char*) "/";
534 pwd
->pw_shell
= (char*) "/sbin/nologin";
537 return NSS_STATUS_SUCCESS
;
541 return NSS_STATUS_NOTFOUND
;
545 return NSS_STATUS_UNAVAIL
;
548 enum nss_status
_nss_mymachines_getgrnam_r(
551 char *buffer
, size_t buflen
,
554 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
555 _cleanup_bus_message_unref_ sd_bus_message
* reply
= NULL
;
556 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
557 const char *p
, *e
, *machine
;
566 p
= startswith(name
, "vg-");
574 r
= parse_gid(e
+ 1, &gid
);
578 machine
= strndupa(p
, e
- p
);
579 if (!machine_name_is_valid(machine
))
582 r
= sd_bus_open_system(&bus
);
586 r
= sd_bus_call_method(bus
,
587 "org.freedesktop.machine1",
588 "/org/freedesktop/machine1",
589 "org.freedesktop.machine1.Manager",
590 "MapFromMachineGroup",
594 machine
, (uint32_t) gid
);
596 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
))
602 r
= sd_bus_message_read(reply
, "u", &mapped
);
606 l
= sizeof(char*) + strlen(name
) + 1;
609 return NSS_STATUS_TRYAGAIN
;
612 memzero(buffer
, sizeof(char*));
613 strcpy(buffer
+ sizeof(char*), name
);
615 gr
->gr_name
= buffer
+ sizeof(char*);
617 gr
->gr_passwd
= (char*) "*"; /* locked */
618 gr
->gr_mem
= (char**) buffer
;
621 return NSS_STATUS_SUCCESS
;
625 return NSS_STATUS_NOTFOUND
;
629 return NSS_STATUS_UNAVAIL
;
632 enum nss_status
_nss_mymachines_getgrgid_r(
635 char *buffer
, size_t buflen
,
638 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
639 _cleanup_bus_message_unref_ sd_bus_message
* reply
= NULL
;
640 _cleanup_bus_flush_close_unref_ sd_bus
*bus
= NULL
;
641 const char *machine
, *object
;
645 if (!gid_is_valid(gid
)) {
650 /* We consider all gids < 65536 host gids */
654 r
= sd_bus_open_system(&bus
);
658 r
= sd_bus_call_method(bus
,
659 "org.freedesktop.machine1",
660 "/org/freedesktop/machine1",
661 "org.freedesktop.machine1.Manager",
668 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
))
674 r
= sd_bus_message_read(reply
, "sou", &machine
, &object
, &mapped
);
678 if (buflen
< sizeof(char*) + 1) {
680 return NSS_STATUS_TRYAGAIN
;
683 memzero(buffer
, sizeof(char*));
684 if (snprintf(buffer
+ sizeof(char*), buflen
- sizeof(char*), "vg-%s-" GID_FMT
, machine
, (gid_t
) mapped
) >= (int) buflen
) {
686 return NSS_STATUS_TRYAGAIN
;
689 gr
->gr_name
= buffer
+ sizeof(char*);
691 gr
->gr_passwd
= (char*) "*"; /* locked */
692 gr
->gr_mem
= (char**) buffer
;
695 return NSS_STATUS_SUCCESS
;
699 return NSS_STATUS_NOTFOUND
;
703 return NSS_STATUS_UNAVAIL
;