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