]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nss-mymachines/nss-mymachines.c
Merge pull request #16491 from keszybz/udev-logging
[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"
9b71e4ab 11#include "bus-locator.h"
6e32c03e 12#include "env-util.h"
2b2fec7d 13#include "errno-util.h"
ca78ad1d 14#include "format-util.h"
25300b5a 15#include "hostname-util.h"
07630cea
LP
16#include "in-addr-util.h"
17#include "macro.h"
0a970718 18#include "memory-util.h"
07630cea 19#include "nss-util.h"
0c5eb056 20#include "signal-util.h"
07630cea 21#include "string-util.h"
cabb0bc6
LP
22
23NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
c01ff965
LP
24NSS_GETPW_PROTOTYPES(mymachines);
25NSS_GETGR_PROTOTYPES(mymachines);
cabb0bc6 26
0dd25fb9 27static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
cabb0bc6
LP
28 unsigned c = 0;
29 int r;
30
31 assert(m);
32 assert(ret);
33
3a6fb33c 34 while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
0dd25fb9 35 int family;
cabb0bc6 36
0dd25fb9 37 r = sd_bus_message_read(m, "i", &family);
cabb0bc6
LP
38 if (r < 0)
39 return r;
40
41 r = sd_bus_message_skip(m, "ay");
42 if (r < 0)
43 return r;
44
45 r = sd_bus_message_exit_container(m);
46 if (r < 0)
47 return r;
48
49 if (af != AF_UNSPEC && family != af)
50 continue;
51
313cefa1 52 c++;
cabb0bc6
LP
53 }
54 if (r < 0)
55 return r;
56
57 r = sd_bus_message_rewind(m, false);
58 if (r < 0)
59 return r;
60
61 *ret = c;
62 return 0;
63}
64
2f28018c
LP
65static bool avoid_deadlock(void) {
66
67 /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager
68 * code activating systemd-machined.service. After all, we shouldn't synchronously do lookups to
69 * systemd-machined if we are required to finish before it can be started. This of course won't detect all
70 * possible dead locks of this kind, but it should work for the most obvious cases. */
71
72 if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */
73 return false;
74
75 return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-machined.service") &&
76 streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system");
77}
78
cabb0bc6
LP
79enum nss_status _nss_mymachines_gethostbyname4_r(
80 const char *name,
81 struct gaih_addrtuple **pat,
82 char *buffer, size_t buflen,
83 int *errnop, int *h_errnop,
84 int32_t *ttlp) {
85
86 struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
4afd3348
LP
87 _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
88 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
634af566 89 _cleanup_free_ int *ifindices = NULL;
cabb0bc6
LP
90 _cleanup_free_ char *class = NULL;
91 size_t l, ms, idx;
92 unsigned i = 0, c = 0;
93 char *r_name;
634af566 94 int n_ifindices, r;
cabb0bc6 95
06202b9e 96 PROTECT_ERRNO;
0c5eb056
LP
97 BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
98
cabb0bc6
LP
99 assert(name);
100 assert(pat);
101 assert(buffer);
102 assert(errnop);
103 assert(h_errnop);
104
105 r = sd_machine_get_class(name, &class);
106 if (r < 0)
107 goto fail;
108 if (!streq(class, "container")) {
109 r = -ENOTTY;
110 goto fail;
111 }
112
634af566
LP
113 n_ifindices = sd_machine_get_ifindices(name, &ifindices);
114 if (n_ifindices < 0) {
115 r = n_ifindices;
cabb0bc6
LP
116 goto fail;
117 }
118
2f28018c
LP
119 if (avoid_deadlock()) {
120 r = -EDEADLK;
121 goto fail;
122 }
123
cabb0bc6
LP
124 r = sd_bus_open_system(&bus);
125 if (r < 0)
126 goto fail;
127
7b389878 128 r = bus_call_method(bus, bus_machine_mgr, "GetMachineAddresses", NULL, &reply, "s", name);
cabb0bc6
LP
129 if (r < 0)
130 goto fail;
131
0dd25fb9 132 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
cabb0bc6
LP
133 if (r < 0)
134 goto fail;
135
136 r = count_addresses(reply, AF_UNSPEC, &c);
137 if (r < 0)
138 goto fail;
139
140 if (c <= 0) {
cabb0bc6
LP
141 *h_errnop = HOST_NOT_FOUND;
142 return NSS_STATUS_NOTFOUND;
143 }
144
145 l = strlen(name);
146 ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
147 if (buflen < ms) {
cdccd29f 148 UNPROTECT_ERRNO;
0192cbdb 149 *errnop = ERANGE;
cda458a5 150 *h_errnop = NETDB_INTERNAL;
cabb0bc6
LP
151 return NSS_STATUS_TRYAGAIN;
152 }
153
154 /* First, append name */
155 r_name = buffer;
156 memcpy(r_name, name, l+1);
157 idx = ALIGN(l+1);
158
159 /* Second, append addresses */
160 r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
0dd25fb9
LP
161 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
162 int family;
cabb0bc6
LP
163 const void *a;
164 size_t sz;
165
0dd25fb9 166 r = sd_bus_message_read(reply, "i", &family);
cabb0bc6
LP
167 if (r < 0)
168 goto fail;
169
170 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
171 if (r < 0)
172 goto fail;
173
174 r = sd_bus_message_exit_container(reply);
175 if (r < 0)
176 goto fail;
177
555bd6e9
LP
178 if (!IN_SET(family, AF_INET, AF_INET6)) {
179 r = -EAFNOSUPPORT;
180 goto fail;
181 }
182
9d485985 183 if (sz != FAMILY_ADDRESS_SIZE(family)) {
cabb0bc6
LP
184 r = -EINVAL;
185 goto fail;
186 }
187
188 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
189 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
190 r_tuple->name = r_name;
191 r_tuple->family = family;
634af566 192 r_tuple->scopeid = n_ifindices == 1 ? ifindices[0] : 0;
cabb0bc6
LP
193 memcpy(r_tuple->addr, a, sz);
194
195 idx += ALIGN(sizeof(struct gaih_addrtuple));
196 i++;
197 }
198
199 assert(i == c);
200
201 r = sd_bus_message_exit_container(reply);
202 if (r < 0)
203 goto fail;
204
205 assert(idx == ms);
206
207 if (*pat)
208 **pat = *r_tuple_first;
209 else
210 *pat = r_tuple_first;
211
212 if (ttlp)
213 *ttlp = 0;
214
06202b9e
YW
215 /* Explicitly reset both *h_errnop and h_errno to work around
216 * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
e70df46b
LP
217 *h_errnop = NETDB_SUCCESS;
218 h_errno = 0;
219
cabb0bc6
LP
220 return NSS_STATUS_SUCCESS;
221
222fail:
cdccd29f 223 UNPROTECT_ERRNO;
0192cbdb 224 *errnop = -r;
2b0c1bfd 225 *h_errnop = NO_RECOVERY;
cabb0bc6
LP
226 return NSS_STATUS_UNAVAIL;
227}
228
229enum nss_status _nss_mymachines_gethostbyname3_r(
230 const char *name,
231 int af,
232 struct hostent *result,
233 char *buffer, size_t buflen,
234 int *errnop, int *h_errnop,
235 int32_t *ttlp,
236 char **canonp) {
237
4afd3348
LP
238 _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
239 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
cabb0bc6
LP
240 _cleanup_free_ char *class = NULL;
241 unsigned c = 0, i = 0;
242 char *r_name, *r_aliases, *r_addr, *r_addr_list;
243 size_t l, idx, ms, alen;
244 int r;
245
06202b9e 246 PROTECT_ERRNO;
0c5eb056
LP
247 BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
248
cabb0bc6
LP
249 assert(name);
250 assert(result);
251 assert(buffer);
252 assert(errnop);
253 assert(h_errnop);
254
255 if (af == AF_UNSPEC)
256 af = AF_INET;
257
258 if (af != AF_INET && af != AF_INET6) {
259 r = -EAFNOSUPPORT;
260 goto fail;
261 }
262
263 r = sd_machine_get_class(name, &class);
264 if (r < 0)
265 goto fail;
266 if (!streq(class, "container")) {
267 r = -ENOTTY;
268 goto fail;
269 }
270
2f28018c
LP
271 if (avoid_deadlock()) {
272 r = -EDEADLK;
273 goto fail;
274 }
275
cabb0bc6
LP
276 r = sd_bus_open_system(&bus);
277 if (r < 0)
278 goto fail;
279
7b389878 280 r = bus_call_method(bus, bus_machine_mgr, "GetMachineAddresses", NULL, &reply, "s", name);
cabb0bc6
LP
281 if (r < 0)
282 goto fail;
283
0dd25fb9 284 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
cabb0bc6
LP
285 if (r < 0)
286 goto fail;
287
288 r = count_addresses(reply, af, &c);
289 if (r < 0)
290 goto fail;
291
292 if (c <= 0) {
cabb0bc6
LP
293 *h_errnop = HOST_NOT_FOUND;
294 return NSS_STATUS_NOTFOUND;
295 }
296
9d485985 297 alen = FAMILY_ADDRESS_SIZE(af);
cabb0bc6
LP
298 l = strlen(name);
299
66a16e7e 300 ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
cabb0bc6
LP
301
302 if (buflen < ms) {
cdccd29f 303 UNPROTECT_ERRNO;
0192cbdb 304 *errnop = ERANGE;
cda458a5 305 *h_errnop = NETDB_INTERNAL;
cabb0bc6
LP
306 return NSS_STATUS_TRYAGAIN;
307 }
308
309 /* First, append name */
310 r_name = buffer;
311 memcpy(r_name, name, l+1);
312 idx = ALIGN(l+1);
313
314 /* Second, create aliases array */
315 r_aliases = buffer + idx;
316 ((char**) r_aliases)[0] = NULL;
317 idx += sizeof(char*);
318
319 /* Third, append addresses */
320 r_addr = buffer + idx;
0dd25fb9
LP
321 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
322 int family;
cabb0bc6
LP
323 const void *a;
324 size_t sz;
325
0dd25fb9 326 r = sd_bus_message_read(reply, "i", &family);
cabb0bc6
LP
327 if (r < 0)
328 goto fail;
329
330 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
331 if (r < 0)
332 goto fail;
333
334 r = sd_bus_message_exit_container(reply);
335 if (r < 0)
336 goto fail;
337
338 if (family != af)
339 continue;
340
341 if (sz != alen) {
342 r = -EINVAL;
343 goto fail;
344 }
345
346 memcpy(r_addr + i*ALIGN(alen), a, alen);
347 i++;
348 }
349
350 assert(i == c);
351 idx += c * ALIGN(alen);
352
353 r = sd_bus_message_exit_container(reply);
354 if (r < 0)
355 goto fail;
356
357 /* Third, append address pointer array */
358 r_addr_list = buffer + idx;
359 for (i = 0; i < c; i++)
360 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
361
362 ((char**) r_addr_list)[i] = NULL;
363 idx += (c+1) * sizeof(char*);
364
365 assert(idx == ms);
366
367 result->h_name = r_name;
368 result->h_aliases = (char**) r_aliases;
369 result->h_addrtype = af;
370 result->h_length = alen;
371 result->h_addr_list = (char**) r_addr_list;
372
373 if (ttlp)
374 *ttlp = 0;
375
376 if (canonp)
377 *canonp = r_name;
378
06202b9e
YW
379 /* Explicitly reset both *h_errnop and h_errno to work around
380 * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
e70df46b
LP
381 *h_errnop = NETDB_SUCCESS;
382 h_errno = 0;
383
cabb0bc6
LP
384 return NSS_STATUS_SUCCESS;
385
386fail:
cdccd29f 387 UNPROTECT_ERRNO;
0192cbdb 388 *errnop = -r;
2b0c1bfd 389 *h_errnop = NO_RECOVERY;
cabb0bc6
LP
390 return NSS_STATUS_UNAVAIL;
391}
392
c01ff965
LP
393NSS_GETHOSTBYNAME_FALLBACKS(mymachines);
394
395enum nss_status _nss_mymachines_getpwnam_r(
396 const char *name,
397 struct passwd *pwd,
398 char *buffer, size_t buflen,
399 int *errnop) {
400
38ccb557 401 return NSS_STATUS_NOTFOUND;
c01ff965
LP
402}
403
404enum nss_status _nss_mymachines_getpwuid_r(
405 uid_t uid,
406 struct passwd *pwd,
407 char *buffer, size_t buflen,
408 int *errnop) {
409
38ccb557 410 return NSS_STATUS_NOTFOUND;
c01ff965
LP
411}
412
413enum nss_status _nss_mymachines_getgrnam_r(
414 const char *name,
415 struct group *gr,
416 char *buffer, size_t buflen,
417 int *errnop) {
418
38ccb557 419 return NSS_STATUS_NOTFOUND;
c01ff965
LP
420}
421
422enum nss_status _nss_mymachines_getgrgid_r(
423 gid_t gid,
424 struct group *gr,
425 char *buffer, size_t buflen,
426 int *errnop) {
427
38ccb557 428 return NSS_STATUS_NOTFOUND;
c01ff965 429}