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