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