1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #include <config.h>
26
27 #include "dbus-internals.h"
28 #include "dbus-sysdeps.h"
29 #include "dbus-sysdeps-unix.h"
30 #include "dbus-threads.h"
31 #include "dbus-protocol.h"
32 #include "dbus-transport.h"
33 #include "dbus-string.h"
34 #include "dbus-userdb.h"
35 #include "dbus-list.h"
36 #include "dbus-credentials.h"
37 #include "dbus-nonce.h"
38
39 #include <sys/types.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <signal.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <fcntl.h>
46 #include <sys/socket.h>
47 #include <dirent.h>
48 #include <sys/un.h>
49 #include <pwd.h>
50 #include <time.h>
51 #include <locale.h>
52 #include <sys/time.h>
53 #include <sys/stat.h>
54 #include <sys/wait.h>
55 #include <netinet/in.h>
56 #include <netdb.h>
57 #include <grp.h>
58 #include <cutils/sockets.h>
59
60 #ifdef HAVE_ERRNO_H
61 #include <errno.h>
62 #endif
63 #ifdef HAVE_WRITEV
64 #include <sys/uio.h>
65 #endif
66 #ifdef HAVE_POLL
67 #include <sys/poll.h>
68 #endif
69 #ifdef HAVE_BACKTRACE
70 #include <execinfo.h>
71 #endif
72 #ifdef HAVE_GETPEERUCRED
73 #include <ucred.h>
74 #endif
75
76 #ifdef HAVE_ADT
77 #include <bsm/adt.h>
78 #endif
79
80 // Android specific atomic operation header.
81 #ifdef ANDROID_ATOMIC
82 #include <cutils/atomic.h>
83 #endif
84
85 #include "sd-daemon.h"
86
87 #ifndef O_BINARY
88 #define O_BINARY 0
89 #endif
90
91 #ifndef AI_ADDRCONFIG
92 #define AI_ADDRCONFIG 0
93 #endif
94
95 #ifndef HAVE_SOCKLEN_T
96 #define socklen_t int
97 #endif
98
99 static dbus_bool_t
_dbus_open_socket(int * fd_p,int domain,int type,int protocol,DBusError * error)100 _dbus_open_socket (int *fd_p,
101 int domain,
102 int type,
103 int protocol,
104 DBusError *error)
105 {
106 #ifdef SOCK_CLOEXEC
107 dbus_bool_t cloexec_done;
108
109 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
110 cloexec_done = *fd_p >= 0;
111
112 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
113 if (*fd_p < 0 && errno == EINVAL)
114 #endif
115 {
116 *fd_p = socket (domain, type, protocol);
117 }
118
119 if (*fd_p >= 0)
120 {
121 #ifdef SOCK_CLOEXEC
122 if (!cloexec_done)
123 #endif
124 {
125 _dbus_fd_set_close_on_exec(*fd_p);
126 }
127
128 _dbus_verbose ("socket fd %d opened\n", *fd_p);
129 return TRUE;
130 }
131 else
132 {
133 dbus_set_error(error,
134 _dbus_error_from_errno (errno),
135 "Failed to open socket: %s",
136 _dbus_strerror (errno));
137 return FALSE;
138 }
139 }
140
141 dbus_bool_t
_dbus_open_tcp_socket(int * fd,DBusError * error)142 _dbus_open_tcp_socket (int *fd,
143 DBusError *error)
144 {
145 return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
146 }
147
148 /**
149 * Opens a UNIX domain socket (as in the socket() call).
150 * Does not bind the socket.
151 *
152 * This will set FD_CLOEXEC for the socket returned
153 *
154 * @param fd return location for socket descriptor
155 * @param error return location for an error
156 * @returns #FALSE if error is set
157 */
158 dbus_bool_t
_dbus_open_unix_socket(int * fd,DBusError * error)159 _dbus_open_unix_socket (int *fd,
160 DBusError *error)
161 {
162 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
163 }
164
165 /**
166 * Closes a socket. Should not be used on non-socket
167 * file descriptors or handles.
168 *
169 * @param fd the socket
170 * @param error return location for an error
171 * @returns #FALSE if error is set
172 */
173 dbus_bool_t
_dbus_close_socket(int fd,DBusError * error)174 _dbus_close_socket (int fd,
175 DBusError *error)
176 {
177 return _dbus_close (fd, error);
178 }
179
180 /**
181 * Like _dbus_read(), but only works on sockets so is
182 * available on Windows.
183 *
184 * @param fd the socket
185 * @param buffer string to append data to
186 * @param count max amount of data to read
187 * @returns number of bytes appended to the string
188 */
189 int
_dbus_read_socket(int fd,DBusString * buffer,int count)190 _dbus_read_socket (int fd,
191 DBusString *buffer,
192 int count)
193 {
194 return _dbus_read (fd, buffer, count);
195 }
196
197 /**
198 * Like _dbus_write(), but only supports sockets
199 * and is thus available on Windows.
200 *
201 * @param fd the file descriptor to write
202 * @param buffer the buffer to write data from
203 * @param start the first byte in the buffer to write
204 * @param len the number of bytes to try to write
205 * @returns the number of bytes written or -1 on error
206 */
207 int
_dbus_write_socket(int fd,const DBusString * buffer,int start,int len)208 _dbus_write_socket (int fd,
209 const DBusString *buffer,
210 int start,
211 int len)
212 {
213 #ifdef MSG_NOSIGNAL
214 const char *data;
215 int bytes_written;
216
217 data = _dbus_string_get_const_data_len (buffer, start, len);
218
219 again:
220
221 bytes_written = send (fd, data, len, MSG_NOSIGNAL);
222
223 if (bytes_written < 0 && errno == EINTR)
224 goto again;
225
226 return bytes_written;
227
228 #else
229 return _dbus_write (fd, buffer, start, len);
230 #endif
231 }
232
233 /**
234 * Like _dbus_read_socket() but also tries to read unix fds from the
235 * socket. When there are more fds to read than space in the array
236 * passed this function will fail with ENOSPC.
237 *
238 * @param fd the socket
239 * @param buffer string to append data to
240 * @param count max amount of data to read
241 * @param fds array to place read file descriptors in
242 * @param n_fds on input space in fds array, on output how many fds actually got read
243 * @returns number of bytes appended to string
244 */
245 int
_dbus_read_socket_with_unix_fds(int fd,DBusString * buffer,int count,int * fds,int * n_fds)246 _dbus_read_socket_with_unix_fds (int fd,
247 DBusString *buffer,
248 int count,
249 int *fds,
250 int *n_fds) {
251 #ifndef HAVE_UNIX_FD_PASSING
252 int r;
253
254 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
255 return r;
256
257 *n_fds = 0;
258 return r;
259
260 #else
261 int bytes_read;
262 int start;
263 struct msghdr m;
264 struct iovec iov;
265
266 _dbus_assert (count >= 0);
267 _dbus_assert (*n_fds >= 0);
268
269 start = _dbus_string_get_length (buffer);
270
271 if (!_dbus_string_lengthen (buffer, count))
272 {
273 errno = ENOMEM;
274 return -1;
275 }
276
277 _DBUS_ZERO(iov);
278 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
279 iov.iov_len = count;
280
281 _DBUS_ZERO(m);
282 m.msg_iov = &iov;
283 m.msg_iovlen = 1;
284
285 /* Hmm, we have no clue how long the control data will actually be
286 that is queued for us. The least we can do is assume that the
287 caller knows. Hence let's make space for the number of fds that
288 we shall read at max plus the cmsg header. */
289 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
290
291 /* It's probably safe to assume that systems with SCM_RIGHTS also
292 know alloca() */
293 m.msg_control = alloca(m.msg_controllen);
294 memset(m.msg_control, 0, m.msg_controllen);
295
296 again:
297
298 bytes_read = recvmsg(fd, &m, 0
299 #ifdef MSG_CMSG_CLOEXEC
300 |MSG_CMSG_CLOEXEC
301 #endif
302 );
303
304 if (bytes_read < 0)
305 {
306 if (errno == EINTR)
307 goto again;
308 else
309 {
310 /* put length back (note that this doesn't actually realloc anything) */
311 _dbus_string_set_length (buffer, start);
312 return -1;
313 }
314 }
315 else
316 {
317 struct cmsghdr *cm;
318 dbus_bool_t found = FALSE;
319
320 if (m.msg_flags & MSG_CTRUNC)
321 {
322 /* Hmm, apparently the control data was truncated. The bad
323 thing is that we might have completely lost a couple of fds
324 without chance to recover them. Hence let's treat this as a
325 serious error. */
326
327 errno = ENOSPC;
328 _dbus_string_set_length (buffer, start);
329 return -1;
330 }
331
332 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
333 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
334 {
335 unsigned i;
336
337 _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
338 *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
339
340 memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
341 found = TRUE;
342
343 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
344 worked, hence we need to go through this list and set
345 CLOEXEC everywhere in any case */
346 for (i = 0; i < *n_fds; i++)
347 _dbus_fd_set_close_on_exec(fds[i]);
348
349 break;
350 }
351
352 if (!found)
353 *n_fds = 0;
354
355 /* put length back (doesn't actually realloc) */
356 _dbus_string_set_length (buffer, start + bytes_read);
357
358 #if 0
359 if (bytes_read > 0)
360 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
361 #endif
362
363 return bytes_read;
364 }
365 #endif
366 }
367
368 int
_dbus_write_socket_with_unix_fds(int fd,const DBusString * buffer,int start,int len,const int * fds,int n_fds)369 _dbus_write_socket_with_unix_fds(int fd,
370 const DBusString *buffer,
371 int start,
372 int len,
373 const int *fds,
374 int n_fds) {
375
376 #ifndef HAVE_UNIX_FD_PASSING
377
378 if (n_fds > 0) {
379 errno = ENOTSUP;
380 return -1;
381 }
382
383 return _dbus_write_socket(fd, buffer, start, len);
384 #else
385 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
386 #endif
387 }
388
389 int
_dbus_write_socket_with_unix_fds_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2,const int * fds,int n_fds)390 _dbus_write_socket_with_unix_fds_two(int fd,
391 const DBusString *buffer1,
392 int start1,
393 int len1,
394 const DBusString *buffer2,
395 int start2,
396 int len2,
397 const int *fds,
398 int n_fds) {
399
400 #ifndef HAVE_UNIX_FD_PASSING
401
402 if (n_fds > 0) {
403 errno = ENOTSUP;
404 return -1;
405 }
406
407 return _dbus_write_socket_two(fd,
408 buffer1, start1, len1,
409 buffer2, start2, len2);
410 #else
411
412 struct msghdr m;
413 struct cmsghdr *cm;
414 struct iovec iov[2];
415 int bytes_written;
416
417 _dbus_assert (len1 >= 0);
418 _dbus_assert (len2 >= 0);
419 _dbus_assert (n_fds >= 0);
420
421 _DBUS_ZERO(iov);
422 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
423 iov[0].iov_len = len1;
424
425 if (buffer2)
426 {
427 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
428 iov[1].iov_len = len2;
429 }
430
431 _DBUS_ZERO(m);
432 m.msg_iov = iov;
433 m.msg_iovlen = buffer2 ? 2 : 1;
434
435 if (n_fds > 0)
436 {
437 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
438 m.msg_control = alloca(m.msg_controllen);
439 memset(m.msg_control, 0, m.msg_controllen);
440
441 cm = CMSG_FIRSTHDR(&m);
442 cm->cmsg_level = SOL_SOCKET;
443 cm->cmsg_type = SCM_RIGHTS;
444 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
445 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
446 }
447
448 again:
449
450 bytes_written = sendmsg (fd, &m, 0
451 #ifdef MSG_NOSIGNAL
452 |MSG_NOSIGNAL
453 #endif
454 );
455
456 if (bytes_written < 0 && errno == EINTR)
457 goto again;
458
459 #if 0
460 if (bytes_written > 0)
461 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
462 #endif
463
464 return bytes_written;
465 #endif
466 }
467
468 /**
469 * Like _dbus_write_two() but only works on sockets and is thus
470 * available on Windows.
471 *
472 * @param fd the file descriptor
473 * @param buffer1 first buffer
474 * @param start1 first byte to write in first buffer
475 * @param len1 number of bytes to write from first buffer
476 * @param buffer2 second buffer, or #NULL
477 * @param start2 first byte to write in second buffer
478 * @param len2 number of bytes to write in second buffer
479 * @returns total bytes written from both buffers, or -1 on error
480 */
481 int
_dbus_write_socket_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2)482 _dbus_write_socket_two (int fd,
483 const DBusString *buffer1,
484 int start1,
485 int len1,
486 const DBusString *buffer2,
487 int start2,
488 int len2)
489 {
490 #ifdef MSG_NOSIGNAL
491 struct iovec vectors[2];
492 const char *data1;
493 const char *data2;
494 int bytes_written;
495 struct msghdr m;
496
497 _dbus_assert (buffer1 != NULL);
498 _dbus_assert (start1 >= 0);
499 _dbus_assert (start2 >= 0);
500 _dbus_assert (len1 >= 0);
501 _dbus_assert (len2 >= 0);
502
503 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
504
505 if (buffer2 != NULL)
506 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
507 else
508 {
509 data2 = NULL;
510 start2 = 0;
511 len2 = 0;
512 }
513
514 vectors[0].iov_base = (char*) data1;
515 vectors[0].iov_len = len1;
516 vectors[1].iov_base = (char*) data2;
517 vectors[1].iov_len = len2;
518
519 _DBUS_ZERO(m);
520 m.msg_iov = vectors;
521 m.msg_iovlen = data2 ? 2 : 1;
522
523 again:
524
525 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
526
527 if (bytes_written < 0 && errno == EINTR)
528 goto again;
529
530 return bytes_written;
531
532 #else
533 return _dbus_write_two (fd, buffer1, start1, len1,
534 buffer2, start2, len2);
535 #endif
536 }
537
538 dbus_bool_t
_dbus_socket_is_invalid(int fd)539 _dbus_socket_is_invalid (int fd)
540 {
541 return fd < 0 ? TRUE : FALSE;
542 }
543
544 /**
545 * Thin wrapper around the read() system call that appends
546 * the data it reads to the DBusString buffer. It appends
547 * up to the given count, and returns the same value
548 * and same errno as read(). The only exception is that
549 * _dbus_read() handles EINTR for you. Also, _dbus_read() can
550 * return ENOMEM, even though regular UNIX read doesn't.
551 *
552 * Unlike _dbus_read_socket(), _dbus_read() is not available
553 * on Windows.
554 *
555 * @param fd the file descriptor to read from
556 * @param buffer the buffer to append data to
557 * @param count the amount of data to read
558 * @returns the number of bytes read or -1
559 */
560 int
_dbus_read(int fd,DBusString * buffer,int count)561 _dbus_read (int fd,
562 DBusString *buffer,
563 int count)
564 {
565 int bytes_read;
566 int start;
567 char *data;
568
569 _dbus_assert (count >= 0);
570
571 start = _dbus_string_get_length (buffer);
572
573 if (!_dbus_string_lengthen (buffer, count))
574 {
575 errno = ENOMEM;
576 return -1;
577 }
578
579 data = _dbus_string_get_data_len (buffer, start, count);
580
581 again:
582
583 bytes_read = read (fd, data, count);
584
585 if (bytes_read < 0)
586 {
587 if (errno == EINTR)
588 goto again;
589 else
590 {
591 /* put length back (note that this doesn't actually realloc anything) */
592 _dbus_string_set_length (buffer, start);
593 return -1;
594 }
595 }
596 else
597 {
598 /* put length back (doesn't actually realloc) */
599 _dbus_string_set_length (buffer, start + bytes_read);
600
601 #if 0
602 if (bytes_read > 0)
603 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
604 #endif
605
606 return bytes_read;
607 }
608 }
609
610 /**
611 * Thin wrapper around the write() system call that writes a part of a
612 * DBusString and handles EINTR for you.
613 *
614 * @param fd the file descriptor to write
615 * @param buffer the buffer to write data from
616 * @param start the first byte in the buffer to write
617 * @param len the number of bytes to try to write
618 * @returns the number of bytes written or -1 on error
619 */
620 int
_dbus_write(int fd,const DBusString * buffer,int start,int len)621 _dbus_write (int fd,
622 const DBusString *buffer,
623 int start,
624 int len)
625 {
626 const char *data;
627 int bytes_written;
628
629 data = _dbus_string_get_const_data_len (buffer, start, len);
630
631 again:
632
633 bytes_written = write (fd, data, len);
634
635 if (bytes_written < 0 && errno == EINTR)
636 goto again;
637
638 #if 0
639 if (bytes_written > 0)
640 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
641 #endif
642
643 return bytes_written;
644 }
645
646 /**
647 * Like _dbus_write() but will use writev() if possible
648 * to write both buffers in sequence. The return value
649 * is the number of bytes written in the first buffer,
650 * plus the number written in the second. If the first
651 * buffer is written successfully and an error occurs
652 * writing the second, the number of bytes in the first
653 * is returned (i.e. the error is ignored), on systems that
654 * don't have writev. Handles EINTR for you.
655 * The second buffer may be #NULL.
656 *
657 * @param fd the file descriptor
658 * @param buffer1 first buffer
659 * @param start1 first byte to write in first buffer
660 * @param len1 number of bytes to write from first buffer
661 * @param buffer2 second buffer, or #NULL
662 * @param start2 first byte to write in second buffer
663 * @param len2 number of bytes to write in second buffer
664 * @returns total bytes written from both buffers, or -1 on error
665 */
666 int
_dbus_write_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2)667 _dbus_write_two (int fd,
668 const DBusString *buffer1,
669 int start1,
670 int len1,
671 const DBusString *buffer2,
672 int start2,
673 int len2)
674 {
675 _dbus_assert (buffer1 != NULL);
676 _dbus_assert (start1 >= 0);
677 _dbus_assert (start2 >= 0);
678 _dbus_assert (len1 >= 0);
679 _dbus_assert (len2 >= 0);
680
681 #ifdef HAVE_WRITEV
682 {
683 struct iovec vectors[2];
684 const char *data1;
685 const char *data2;
686 int bytes_written;
687
688 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
689
690 if (buffer2 != NULL)
691 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
692 else
693 {
694 data2 = NULL;
695 start2 = 0;
696 len2 = 0;
697 }
698
699 vectors[0].iov_base = (char*) data1;
700 vectors[0].iov_len = len1;
701 vectors[1].iov_base = (char*) data2;
702 vectors[1].iov_len = len2;
703
704 again:
705
706 bytes_written = writev (fd,
707 vectors,
708 data2 ? 2 : 1);
709
710 if (bytes_written < 0 && errno == EINTR)
711 goto again;
712
713 return bytes_written;
714 }
715 #else /* HAVE_WRITEV */
716 {
717 int ret1;
718
719 ret1 = _dbus_write (fd, buffer1, start1, len1);
720 if (ret1 == len1 && buffer2 != NULL)
721 {
722 ret2 = _dbus_write (fd, buffer2, start2, len2);
723 if (ret2 < 0)
724 ret2 = 0; /* we can't report an error as the first write was OK */
725
726 return ret1 + ret2;
727 }
728 else
729 return ret1;
730 }
731 #endif /* !HAVE_WRITEV */
732 }
733
734 #define _DBUS_MAX_SUN_PATH_LENGTH 99
735
736 /**
737 * @def _DBUS_MAX_SUN_PATH_LENGTH
738 *
739 * Maximum length of the path to a UNIX domain socket,
740 * sockaddr_un::sun_path member. POSIX requires that all systems
741 * support at least 100 bytes here, including the nul termination.
742 * We use 99 for the max value to allow for the nul.
743 *
744 * We could probably also do sizeof (addr.sun_path)
745 * but this way we are the same on all platforms
746 * which is probably a good idea.
747 */
748
749 /**
750 * Creates a socket and connects it to the UNIX domain socket at the
751 * given path. The connection fd is returned, and is set up as
752 * nonblocking.
753 *
754 * Uses abstract sockets instead of filesystem-linked sockets if
755 * requested (it's possible only on Linux; see "man 7 unix" on Linux).
756 * On non-Linux abstract socket usage always fails.
757 *
758 * This will set FD_CLOEXEC for the socket returned.
759 *
760 * @param path the path to UNIX domain socket
761 * @param abstract #TRUE to use abstract namespace
762 * @param error return location for error code
763 * @returns connection file descriptor or -1 on error
764 */
765 int
_dbus_connect_unix_socket(const char * path,dbus_bool_t abstract,DBusError * error)766 _dbus_connect_unix_socket (const char *path,
767 dbus_bool_t abstract,
768 DBusError *error)
769 {
770 int fd;
771 size_t path_len;
772 struct sockaddr_un addr;
773
774 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
775
776 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
777 path, abstract);
778
779
780 if (!_dbus_open_unix_socket (&fd, error))
781 {
782 _DBUS_ASSERT_ERROR_IS_SET(error);
783 return -1;
784 }
785 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
786
787 _DBUS_ZERO (addr);
788 addr.sun_family = AF_UNIX;
789 path_len = strlen (path);
790
791 if (abstract)
792 {
793 #ifdef HAVE_ABSTRACT_SOCKETS
794 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
795 path_len++; /* Account for the extra nul byte added to the start of sun_path */
796
797 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
798 {
799 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
800 "Abstract socket name too long\n");
801 _dbus_close (fd, NULL);
802 return -1;
803 }
804
805 strncpy (&addr.sun_path[1], path, path_len);
806 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
807 #else /* HAVE_ABSTRACT_SOCKETS */
808 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
809 "Operating system does not support abstract socket namespace\n");
810 _dbus_close (fd, NULL);
811 return -1;
812 #endif /* ! HAVE_ABSTRACT_SOCKETS */
813 }
814 else
815 {
816 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
817 {
818 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
819 "Socket name too long\n");
820 _dbus_close (fd, NULL);
821 return -1;
822 }
823
824 strncpy (addr.sun_path, path, path_len);
825 }
826
827 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
828 {
829 dbus_set_error (error,
830 _dbus_error_from_errno (errno),
831 "Failed to connect to socket %s: %s",
832 path, _dbus_strerror (errno));
833
834 _dbus_close (fd, NULL);
835 fd = -1;
836
837 return -1;
838 }
839
840 if (!_dbus_set_fd_nonblocking (fd, error))
841 {
842 _DBUS_ASSERT_ERROR_IS_SET (error);
843
844 _dbus_close (fd, NULL);
845 fd = -1;
846
847 return -1;
848 }
849
850 return fd;
851 }
852
853 /**
854 * Enables or disables the reception of credentials on the given socket during
855 * the next message transmission. This is only effective if the #LOCAL_CREDS
856 * system feature exists, in which case the other side of the connection does
857 * not have to do anything special to send the credentials.
858 *
859 * @param fd socket on which to change the #LOCAL_CREDS flag.
860 * @param on whether to enable or disable the #LOCAL_CREDS flag.
861 */
862 static dbus_bool_t
_dbus_set_local_creds(int fd,dbus_bool_t on)863 _dbus_set_local_creds (int fd, dbus_bool_t on)
864 {
865 dbus_bool_t retval = TRUE;
866
867 #if defined(HAVE_CMSGCRED)
868 /* NOOP just to make sure only one codepath is used
869 * and to prefer CMSGCRED
870 */
871 #elif defined(LOCAL_CREDS)
872 int val = on ? 1 : 0;
873 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
874 {
875 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
876 retval = FALSE;
877 }
878 else
879 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
880 on ? "enabled" : "disabled", fd);
881 #endif
882
883 return retval;
884 }
885
886 /**
887 * Creates a socket and binds it to the given path,
888 * then listens on the socket. The socket is
889 * set to be nonblocking.
890 *
891 * Uses abstract sockets instead of filesystem-linked
892 * sockets if requested (it's possible only on Linux;
893 * see "man 7 unix" on Linux).
894 * On non-Linux abstract socket usage always fails.
895 *
896 * This will set FD_CLOEXEC for the socket returned
897 *
898 * @param path the socket name
899 * @param abstract #TRUE to use abstract namespace
900 * @param error return location for errors
901 * @returns the listening file descriptor or -1 on error
902 */
903 int
_dbus_listen_unix_socket(const char * path,dbus_bool_t abstract,DBusError * error)904 _dbus_listen_unix_socket (const char *path,
905 dbus_bool_t abstract,
906 DBusError *error)
907 {
908 int listen_fd;
909 struct sockaddr_un addr;
910 size_t path_len;
911 unsigned int reuseaddr;
912
913 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
914
915 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
916 path, abstract);
917 #ifdef ANDROID_MANAGED_SOCKET
918 if (strncmp (path, ANDROID_SOCKET_DIR"/", strlen(ANDROID_SOCKET_DIR"/")) == 0)
919 {
920 const char* suffix;
921 /* init has created a socket for us, pick it up from environ */
922 suffix = &path[strlen (ANDROID_SOCKET_DIR"/")];
923 listen_fd = android_get_control_socket (suffix);
924 if (listen_fd == -1)
925 {
926 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
927 "Could not obtain fd for android socket %s\n", suffix);
928 return -1;
929 }
930
931 _dbus_verbose ("Obtained fd for android socket %s\n", suffix);
932 }
933 else
934 {
935 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
936 "Not an android socket: %s\n", path);
937 return -1;
938 }
939 #else
940
941 if (!_dbus_open_unix_socket (&listen_fd, error))
942 {
943 _DBUS_ASSERT_ERROR_IS_SET(error);
944 return -1;
945 }
946 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
947
948 _DBUS_ZERO (addr);
949 addr.sun_family = AF_UNIX;
950 path_len = strlen (path);
951
952 if (abstract)
953 {
954 #ifdef HAVE_ABSTRACT_SOCKETS
955 /* remember that abstract names aren't nul-terminated so we rely
956 * on sun_path being filled in with zeroes above.
957 */
958 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
959 path_len++; /* Account for the extra nul byte added to the start of sun_path */
960
961 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
962 {
963 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
964 "Abstract socket name too long\n");
965 _dbus_close (listen_fd, NULL);
966 return -1;
967 }
968
969 strncpy (&addr.sun_path[1], path, path_len);
970 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
971 #else /* HAVE_ABSTRACT_SOCKETS */
972 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
973 "Operating system does not support abstract socket namespace\n");
974 _dbus_close (listen_fd, NULL);
975 return -1;
976 #endif /* ! HAVE_ABSTRACT_SOCKETS */
977 }
978 else
979 {
980 /* Discussed security implications of this with Nalin,
981 * and we couldn't think of where it would kick our ass, but
982 * it still seems a bit sucky. It also has non-security suckage;
983 * really we'd prefer to exit if the socket is already in use.
984 * But there doesn't seem to be a good way to do this.
985 *
986 * Just to be extra careful, I threw in the stat() - clearly
987 * the stat() can't *fix* any security issue, but it at least
988 * avoids inadvertent/accidental data loss.
989 */
990 {
991 struct stat sb;
992
993 if (stat (path, &sb) == 0 &&
994 S_ISSOCK (sb.st_mode))
995 unlink (path);
996 }
997
998 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
999 {
1000 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1001 "Abstract socket name too long\n");
1002 _dbus_close (listen_fd, NULL);
1003 return -1;
1004 }
1005
1006 strncpy (addr.sun_path, path, path_len);
1007 }
1008
1009 reuseaddr = 1;
1010 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1011 {
1012 _dbus_warn ("Failed to set socket option\"%s\": %s",
1013 path, _dbus_strerror (errno));
1014 }
1015
1016 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1017 {
1018 dbus_set_error (error, _dbus_error_from_errno (errno),
1019 "Failed to bind socket \"%s\": %s",
1020 path, _dbus_strerror (errno));
1021 _dbus_close (listen_fd, NULL);
1022 return -1;
1023 }
1024
1025 #endif /* android init managed sockets */
1026
1027 if (listen (listen_fd, 30 /* backlog */) < 0)
1028 {
1029 dbus_set_error (error, _dbus_error_from_errno (errno),
1030 "Failed to listen on socket \"%s\": %s",
1031 path, _dbus_strerror (errno));
1032 _dbus_close (listen_fd, NULL);
1033 return -1;
1034 }
1035
1036 if (!_dbus_set_local_creds (listen_fd, TRUE))
1037 {
1038 dbus_set_error (error, _dbus_error_from_errno (errno),
1039 "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
1040 path, _dbus_strerror (errno));
1041 close (listen_fd);
1042 return -1;
1043 }
1044
1045 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1046 {
1047 _DBUS_ASSERT_ERROR_IS_SET (error);
1048 _dbus_close (listen_fd, NULL);
1049 return -1;
1050 }
1051
1052 #ifndef ANDROID_MANAGED_SOCKET
1053 /* Try opening up the permissions, but if we can't, just go ahead
1054 * and continue, maybe it will be good enough.
1055 */
1056 if (!abstract && chmod (path, 0777) < 0)
1057 _dbus_warn ("Could not set mode 0777 on socket %s\n",
1058 path);
1059 #endif
1060
1061 return listen_fd;
1062 }
1063
1064 /**
1065 * Acquires one or more sockets passed in from systemd. The sockets
1066 * are set to be nonblocking.
1067 *
1068 * This will set FD_CLOEXEC for the sockets returned.
1069 *
1070 * @oaram fds the file descriptors
1071 * @param error return location for errors
1072 * @returns the number of file descriptors
1073 */
1074 int
_dbus_listen_systemd_sockets(int ** fds,DBusError * error)1075 _dbus_listen_systemd_sockets (int **fds,
1076 DBusError *error)
1077 {
1078 int r, n;
1079 unsigned fd;
1080 int *new_fds;
1081
1082 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1083
1084 n = sd_listen_fds (TRUE);
1085 if (n < 0)
1086 {
1087 dbus_set_error (error, _dbus_error_from_errno (-n),
1088 "Failed to acquire systemd socket: %s",
1089 _dbus_strerror (-n));
1090 return -1;
1091 }
1092
1093 if (n <= 0)
1094 {
1095 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1096 "No socket received.");
1097 return -1;
1098 }
1099
1100 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1101 {
1102 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1103 if (r < 0)
1104 {
1105 dbus_set_error (error, _dbus_error_from_errno (-r),
1106 "Failed to verify systemd socket type: %s",
1107 _dbus_strerror (-r));
1108 return -1;
1109 }
1110
1111 if (!r)
1112 {
1113 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1114 "Passed socket has wrong type.");
1115 return -1;
1116 }
1117 }
1118
1119 /* OK, the file descriptors are all good, so let's take posession of
1120 them then. */
1121
1122 new_fds = dbus_new (int, n);
1123 if (!new_fds)
1124 {
1125 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1126 "Failed to allocate file handle array.");
1127 goto fail;
1128 }
1129
1130 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1131 {
1132 if (!_dbus_set_local_creds (fd, TRUE))
1133 {
1134 dbus_set_error (error, _dbus_error_from_errno (errno),
1135 "Failed to enable LOCAL_CREDS on systemd socket: %s",
1136 _dbus_strerror (errno));
1137 goto fail;
1138 }
1139
1140 if (!_dbus_set_fd_nonblocking (fd, error))
1141 {
1142 _DBUS_ASSERT_ERROR_IS_SET (error);
1143 goto fail;
1144 }
1145
1146 new_fds[fd - SD_LISTEN_FDS_START] = fd;
1147 }
1148
1149 *fds = new_fds;
1150 return n;
1151
1152 fail:
1153
1154 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1155 {
1156 _dbus_close (fd, NULL);
1157 }
1158
1159 dbus_free (new_fds);
1160 return -1;
1161 }
1162
1163 /**
1164 * Creates a socket and connects to a socket at the given host
1165 * and port. The connection fd is returned, and is set up as
1166 * nonblocking.
1167 *
1168 * This will set FD_CLOEXEC for the socket returned
1169 *
1170 * @param host the host name to connect to
1171 * @param port the port to connect to
1172 * @param family the address family to listen on, NULL for all
1173 * @param error return location for error code
1174 * @returns connection file descriptor or -1 on error
1175 */
1176 int
_dbus_connect_tcp_socket(const char * host,const char * port,const char * family,DBusError * error)1177 _dbus_connect_tcp_socket (const char *host,
1178 const char *port,
1179 const char *family,
1180 DBusError *error)
1181 {
1182 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1183 }
1184
1185 int
_dbus_connect_tcp_socket_with_nonce(const char * host,const char * port,const char * family,const char * noncefile,DBusError * error)1186 _dbus_connect_tcp_socket_with_nonce (const char *host,
1187 const char *port,
1188 const char *family,
1189 const char *noncefile,
1190 DBusError *error)
1191 {
1192 int saved_errno = 0;
1193 int fd = -1, res;
1194 struct addrinfo hints;
1195 struct addrinfo *ai, *tmp;
1196
1197 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1198
1199 if (!_dbus_open_tcp_socket (&fd, error))
1200 {
1201 _DBUS_ASSERT_ERROR_IS_SET(error);
1202 return -1;
1203 }
1204
1205 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1206
1207 _DBUS_ZERO (hints);
1208
1209 if (!family)
1210 hints.ai_family = AF_UNSPEC;
1211 else if (!strcmp(family, "ipv4"))
1212 hints.ai_family = AF_INET;
1213 else if (!strcmp(family, "ipv6"))
1214 hints.ai_family = AF_INET6;
1215 else
1216 {
1217 dbus_set_error (error,
1218 DBUS_ERROR_BAD_ADDRESS,
1219 "Unknown address family %s", family);
1220 return -1;
1221 }
1222 hints.ai_protocol = IPPROTO_TCP;
1223 hints.ai_socktype = SOCK_STREAM;
1224 hints.ai_flags = AI_ADDRCONFIG;
1225
1226 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1227 {
1228 dbus_set_error (error,
1229 _dbus_error_from_errno (errno),
1230 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1231 host, port, gai_strerror(res), res);
1232 _dbus_close (fd, NULL);
1233 return -1;
1234 }
1235
1236 tmp = ai;
1237 while (tmp)
1238 {
1239 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1240 {
1241 freeaddrinfo(ai);
1242 _DBUS_ASSERT_ERROR_IS_SET(error);
1243 return -1;
1244 }
1245 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1246
1247 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1248 {
1249 saved_errno = errno;
1250 _dbus_close(fd, NULL);
1251 fd = -1;
1252 tmp = tmp->ai_next;
1253 continue;
1254 }
1255
1256 break;
1257 }
1258 freeaddrinfo(ai);
1259
1260 if (fd == -1)
1261 {
1262 dbus_set_error (error,
1263 _dbus_error_from_errno (saved_errno),
1264 "Failed to connect to socket \"%s:%s\" %s",
1265 host, port, _dbus_strerror(saved_errno));
1266 return -1;
1267 }
1268
1269 if (noncefile != NULL)
1270 {
1271 DBusString noncefileStr;
1272 dbus_bool_t ret;
1273 _dbus_string_init_const (&noncefileStr, noncefile);
1274 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1275 _dbus_string_free (&noncefileStr);
1276
1277 if (!ret)
1278 {
1279 _dbus_close (fd, NULL);
1280 return -1;
1281 }
1282 }
1283
1284 if (!_dbus_set_fd_nonblocking (fd, error))
1285 {
1286 _dbus_close (fd, NULL);
1287 return -1;
1288 }
1289
1290 return fd;
1291 }
1292
1293 /**
1294 * Creates a socket and binds it to the given path, then listens on
1295 * the socket. The socket is set to be nonblocking. In case of port=0
1296 * a random free port is used and returned in the port parameter.
1297 * If inaddr_any is specified, the hostname is ignored.
1298 *
1299 * This will set FD_CLOEXEC for the socket returned
1300 *
1301 * @param host the host name to listen on
1302 * @param port the port to listen on, if zero a free port will be used
1303 * @param family the address family to listen on, NULL for all
1304 * @param retport string to return the actual port listened on
1305 * @param fds_p location to store returned file descriptors
1306 * @param error return location for errors
1307 * @returns the number of listening file descriptors or -1 on error
1308 */
1309 int
_dbus_listen_tcp_socket(const char * host,const char * port,const char * family,DBusString * retport,int ** fds_p,DBusError * error)1310 _dbus_listen_tcp_socket (const char *host,
1311 const char *port,
1312 const char *family,
1313 DBusString *retport,
1314 int **fds_p,
1315 DBusError *error)
1316 {
1317 int saved_errno;
1318 int nlisten_fd = 0, *listen_fd = NULL, res, i;
1319 struct addrinfo hints;
1320 struct addrinfo *ai, *tmp;
1321 unsigned int reuseaddr;
1322
1323 *fds_p = NULL;
1324 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1325
1326 _DBUS_ZERO (hints);
1327
1328 if (!family)
1329 hints.ai_family = AF_UNSPEC;
1330 else if (!strcmp(family, "ipv4"))
1331 hints.ai_family = AF_INET;
1332 else if (!strcmp(family, "ipv6"))
1333 hints.ai_family = AF_INET6;
1334 else
1335 {
1336 dbus_set_error (error,
1337 DBUS_ERROR_BAD_ADDRESS,
1338 "Unknown address family %s", family);
1339 return -1;
1340 }
1341
1342 hints.ai_protocol = IPPROTO_TCP;
1343 hints.ai_socktype = SOCK_STREAM;
1344 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1345
1346 redo_lookup_with_port:
1347 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1348 {
1349 dbus_set_error (error,
1350 _dbus_error_from_errno (errno),
1351 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1352 host ? host : "*", port, gai_strerror(res), res);
1353 return -1;
1354 }
1355
1356 tmp = ai;
1357 while (tmp)
1358 {
1359 int fd = -1, *newlisten_fd;
1360 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1361 {
1362 _DBUS_ASSERT_ERROR_IS_SET(error);
1363 goto failed;
1364 }
1365 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1366
1367 reuseaddr = 1;
1368 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1369 {
1370 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1371 host ? host : "*", port, _dbus_strerror (errno));
1372 }
1373
1374 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1375 {
1376 saved_errno = errno;
1377 _dbus_close(fd, NULL);
1378 if (saved_errno == EADDRINUSE)
1379 {
1380 /* Depending on kernel policy, it may or may not
1381 be neccessary to bind to both IPv4 & 6 addresses
1382 so ignore EADDRINUSE here */
1383 tmp = tmp->ai_next;
1384 continue;
1385 }
1386 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1387 "Failed to bind socket \"%s:%s\": %s",
1388 host ? host : "*", port, _dbus_strerror (saved_errno));
1389 goto failed;
1390 }
1391
1392 if (listen (fd, 30 /* backlog */) < 0)
1393 {
1394 saved_errno = errno;
1395 _dbus_close (fd, NULL);
1396 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1397 "Failed to listen on socket \"%s:%s\": %s",
1398 host ? host : "*", port, _dbus_strerror (saved_errno));
1399 goto failed;
1400 }
1401
1402 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
1403 if (!newlisten_fd)
1404 {
1405 saved_errno = errno;
1406 _dbus_close (fd, NULL);
1407 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1408 "Failed to allocate file handle array: %s",
1409 _dbus_strerror (saved_errno));
1410 goto failed;
1411 }
1412 listen_fd = newlisten_fd;
1413 listen_fd[nlisten_fd] = fd;
1414 nlisten_fd++;
1415
1416 if (!_dbus_string_get_length(retport))
1417 {
1418 /* If the user didn't specify a port, or used 0, then
1419 the kernel chooses a port. After the first address
1420 is bound to, we need to force all remaining addresses
1421 to use the same port */
1422 if (!port || !strcmp(port, "0"))
1423 {
1424 struct sockaddr_storage addr;
1425 socklen_t addrlen;
1426 char portbuf[50];
1427
1428 addrlen = sizeof(addr);
1429 getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1430
1431 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
1432 portbuf, sizeof(portbuf),
1433 NI_NUMERICHOST)) != 0)
1434 {
1435 dbus_set_error (error, _dbus_error_from_errno (errno),
1436 "Failed to resolve port \"%s:%s\": %s (%s)",
1437 host ? host : "*", port, gai_strerror(res), res);
1438 goto failed;
1439 }
1440 if (!_dbus_string_append(retport, portbuf))
1441 {
1442 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1443 goto failed;
1444 }
1445
1446 /* Release current address list & redo lookup */
1447 port = _dbus_string_get_const_data(retport);
1448 freeaddrinfo(ai);
1449 goto redo_lookup_with_port;
1450 }
1451 else
1452 {
1453 if (!_dbus_string_append(retport, port))
1454 {
1455 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1456 goto failed;
1457 }
1458 }
1459 }
1460
1461 tmp = tmp->ai_next;
1462 }
1463 freeaddrinfo(ai);
1464 ai = NULL;
1465
1466 if (!nlisten_fd)
1467 {
1468 errno = EADDRINUSE;
1469 dbus_set_error (error, _dbus_error_from_errno (errno),
1470 "Failed to bind socket \"%s:%s\": %s",
1471 host ? host : "*", port, _dbus_strerror (errno));
1472 return -1;
1473 }
1474
1475 for (i = 0 ; i < nlisten_fd ; i++)
1476 {
1477 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
1478 {
1479 goto failed;
1480 }
1481 }
1482
1483 *fds_p = listen_fd;
1484
1485 return nlisten_fd;
1486
1487 failed:
1488 if (ai)
1489 freeaddrinfo(ai);
1490 for (i = 0 ; i < nlisten_fd ; i++)
1491 _dbus_close(listen_fd[i], NULL);
1492 dbus_free(listen_fd);
1493 return -1;
1494 }
1495
1496 static dbus_bool_t
write_credentials_byte(int server_fd,DBusError * error)1497 write_credentials_byte (int server_fd,
1498 DBusError *error)
1499 {
1500 int bytes_written;
1501 char buf[1] = { '\0' };
1502 #if defined(HAVE_CMSGCRED)
1503 union {
1504 struct cmsghdr hdr;
1505 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1506 } cmsg;
1507 struct iovec iov;
1508 struct msghdr msg;
1509 iov.iov_base = buf;
1510 iov.iov_len = 1;
1511
1512 _DBUS_ZERO(msg);
1513 msg.msg_iov = &iov;
1514 msg.msg_iovlen = 1;
1515
1516 msg.msg_control = (caddr_t) &cmsg;
1517 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1518 _DBUS_ZERO(cmsg);
1519 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1520 cmsg.hdr.cmsg_level = SOL_SOCKET;
1521 cmsg.hdr.cmsg_type = SCM_CREDS;
1522 #endif
1523
1524 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1525
1526 again:
1527
1528 #if defined(HAVE_CMSGCRED)
1529 bytes_written = sendmsg (server_fd, &msg, 0);
1530 #else
1531 bytes_written = write (server_fd, buf, 1);
1532 #endif
1533
1534 if (bytes_written < 0 && errno == EINTR)
1535 goto again;
1536
1537 if (bytes_written < 0)
1538 {
1539 dbus_set_error (error, _dbus_error_from_errno (errno),
1540 "Failed to write credentials byte: %s",
1541 _dbus_strerror (errno));
1542 return FALSE;
1543 }
1544 else if (bytes_written == 0)
1545 {
1546 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1547 "wrote zero bytes writing credentials byte");
1548 return FALSE;
1549 }
1550 else
1551 {
1552 _dbus_assert (bytes_written == 1);
1553 _dbus_verbose ("wrote credentials byte\n");
1554 return TRUE;
1555 }
1556 }
1557
1558 /**
1559 * Reads a single byte which must be nul (an error occurs otherwise),
1560 * and reads unix credentials if available. Clears the credentials
1561 * object, then adds pid/uid if available, so any previous credentials
1562 * stored in the object are lost.
1563 *
1564 * Return value indicates whether a byte was read, not whether
1565 * we got valid credentials. On some systems, such as Linux,
1566 * reading/writing the byte isn't actually required, but we do it
1567 * anyway just to avoid multiple codepaths.
1568 *
1569 * Fails if no byte is available, so you must select() first.
1570 *
1571 * The point of the byte is that on some systems we have to
1572 * use sendmsg()/recvmsg() to transmit credentials.
1573 *
1574 * @param client_fd the client file descriptor
1575 * @param credentials object to add client credentials to
1576 * @param error location to store error code
1577 * @returns #TRUE on success
1578 */
1579 dbus_bool_t
_dbus_read_credentials_socket(int client_fd,DBusCredentials * credentials,DBusError * error)1580 _dbus_read_credentials_socket (int client_fd,
1581 DBusCredentials *credentials,
1582 DBusError *error)
1583 {
1584 struct msghdr msg;
1585 struct iovec iov;
1586 char buf;
1587 dbus_uid_t uid_read;
1588 dbus_pid_t pid_read;
1589 int bytes_read;
1590
1591 #ifdef HAVE_CMSGCRED
1592 union {
1593 struct cmsghdr hdr;
1594 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1595 } cmsg;
1596
1597 #elif defined(LOCAL_CREDS)
1598 struct {
1599 struct cmsghdr hdr;
1600 struct sockcred cred;
1601 } cmsg;
1602 #endif
1603
1604 uid_read = DBUS_UID_UNSET;
1605 pid_read = DBUS_PID_UNSET;
1606
1607 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1608
1609 /* The POSIX spec certainly doesn't promise this, but
1610 * we need these assertions to fail as soon as we're wrong about
1611 * it so we can do the porting fixups
1612 */
1613 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
1614 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
1615 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
1616
1617 _dbus_credentials_clear (credentials);
1618
1619 /* Systems supporting LOCAL_CREDS are configured to have this feature
1620 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
1621 * the connection. Therefore, the received message must carry the
1622 * credentials information without doing anything special.
1623 */
1624
1625 iov.iov_base = &buf;
1626 iov.iov_len = 1;
1627
1628 _DBUS_ZERO(msg);
1629 msg.msg_iov = &iov;
1630 msg.msg_iovlen = 1;
1631
1632 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
1633 _DBUS_ZERO(cmsg);
1634 msg.msg_control = (caddr_t) &cmsg;
1635 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1636 #endif
1637
1638 again:
1639 bytes_read = recvmsg (client_fd, &msg, 0);
1640
1641 if (bytes_read < 0)
1642 {
1643 if (errno == EINTR)
1644 goto again;
1645
1646 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1647 * normally only call read_credentials if the socket was ready
1648 * for reading
1649 */
1650
1651 dbus_set_error (error, _dbus_error_from_errno (errno),
1652 "Failed to read credentials byte: %s",
1653 _dbus_strerror (errno));
1654 return FALSE;
1655 }
1656 else if (bytes_read == 0)
1657 {
1658 /* this should not happen unless we are using recvmsg wrong,
1659 * so is essentially here for paranoia
1660 */
1661 dbus_set_error (error, DBUS_ERROR_FAILED,
1662 "Failed to read credentials byte (zero-length read)");
1663 return FALSE;
1664 }
1665 else if (buf != '\0')
1666 {
1667 dbus_set_error (error, DBUS_ERROR_FAILED,
1668 "Credentials byte was not nul");
1669 return FALSE;
1670 }
1671
1672 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
1673 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
1674 || cmsg.hdr.cmsg_type != SCM_CREDS)
1675 {
1676 dbus_set_error (error, DBUS_ERROR_FAILED,
1677 "Message from recvmsg() was not SCM_CREDS");
1678 return FALSE;
1679 }
1680 #endif
1681
1682 _dbus_verbose ("read credentials byte\n");
1683
1684 {
1685 #ifdef SO_PEERCRED
1686 struct ucred cr;
1687 int cr_len = sizeof (cr);
1688
1689 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
1690 cr_len == sizeof (cr))
1691 {
1692 pid_read = cr.pid;
1693 uid_read = cr.uid;
1694 }
1695 else
1696 {
1697 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
1698 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
1699 }
1700 #elif defined(HAVE_CMSGCRED)
1701 struct cmsgcred *cred;
1702
1703 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
1704 pid_read = cred->cmcred_pid;
1705 uid_read = cred->cmcred_euid;
1706 #elif defined(LOCAL_CREDS)
1707 pid_read = DBUS_PID_UNSET;
1708 uid_read = cmsg.cred.sc_uid;
1709 /* Since we have already got the credentials from this socket, we can
1710 * disable its LOCAL_CREDS flag if it was ever set. */
1711 _dbus_set_local_creds (client_fd, FALSE);
1712 #elif defined(HAVE_GETPEEREID)
1713 uid_t euid;
1714 gid_t egid;
1715 if (getpeereid (client_fd, &euid, &egid) == 0)
1716 {
1717 uid_read = euid;
1718 }
1719 else
1720 {
1721 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
1722 }
1723 #elif defined(HAVE_GETPEERUCRED)
1724 ucred_t * ucred = NULL;
1725 if (getpeerucred (client_fd, &ucred) == 0)
1726 {
1727 pid_read = ucred_getpid (ucred);
1728 uid_read = ucred_geteuid (ucred);
1729 #ifdef HAVE_ADT
1730 /* generate audit session data based on socket ucred */
1731 adt_session_data_t *adth = NULL;
1732 adt_export_data_t *data = NULL;
1733 size_t size = 0;
1734 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
1735 {
1736 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
1737 }
1738 else
1739 {
1740 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
1741 {
1742 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
1743 }
1744 else
1745 {
1746 size = adt_export_session_data (adth, &data);
1747 if (size <= 0)
1748 {
1749 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
1750 }
1751 else
1752 {
1753 _dbus_credentials_add_adt_audit_data (credentials, data, size);
1754 free (data);
1755 }
1756 }
1757 (void) adt_end_session (adth);
1758 }
1759 #endif /* HAVE_ADT */
1760 }
1761 else
1762 {
1763 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
1764 }
1765 if (ucred != NULL)
1766 ucred_free (ucred);
1767 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
1768 _dbus_verbose ("Socket credentials not supported on this OS\n");
1769 #endif
1770 }
1771
1772 _dbus_verbose ("Credentials:"
1773 " pid "DBUS_PID_FORMAT
1774 " uid "DBUS_UID_FORMAT
1775 "\n",
1776 pid_read,
1777 uid_read);
1778
1779 if (pid_read != DBUS_PID_UNSET)
1780 {
1781 if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
1782 {
1783 _DBUS_SET_OOM (error);
1784 return FALSE;
1785 }
1786 }
1787
1788 if (uid_read != DBUS_UID_UNSET)
1789 {
1790 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
1791 {
1792 _DBUS_SET_OOM (error);
1793 return FALSE;
1794 }
1795 }
1796
1797 return TRUE;
1798 }
1799
1800 /**
1801 * Sends a single nul byte with our UNIX credentials as ancillary
1802 * data. Returns #TRUE if the data was successfully written. On
1803 * systems that don't support sending credentials, just writes a byte,
1804 * doesn't send any credentials. On some systems, such as Linux,
1805 * reading/writing the byte isn't actually required, but we do it
1806 * anyway just to avoid multiple codepaths.
1807 *
1808 * Fails if no byte can be written, so you must select() first.
1809 *
1810 * The point of the byte is that on some systems we have to
1811 * use sendmsg()/recvmsg() to transmit credentials.
1812 *
1813 * @param server_fd file descriptor for connection to server
1814 * @param error return location for error code
1815 * @returns #TRUE if the byte was sent
1816 */
1817 dbus_bool_t
_dbus_send_credentials_socket(int server_fd,DBusError * error)1818 _dbus_send_credentials_socket (int server_fd,
1819 DBusError *error)
1820 {
1821 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1822
1823 if (write_credentials_byte (server_fd, error))
1824 return TRUE;
1825 else
1826 return FALSE;
1827 }
1828
1829 /**
1830 * Accepts a connection on a listening socket.
1831 * Handles EINTR for you.
1832 *
1833 * This will enable FD_CLOEXEC for the returned socket.
1834 *
1835 * @param listen_fd the listen file descriptor
1836 * @returns the connection fd of the client, or -1 on error
1837 */
1838 int
_dbus_accept(int listen_fd)1839 _dbus_accept (int listen_fd)
1840 {
1841 int client_fd;
1842 struct sockaddr addr;
1843 socklen_t addrlen;
1844 #ifdef HAVE_ACCEPT4
1845 dbus_bool_t cloexec_done;
1846 #endif
1847
1848 addrlen = sizeof (addr);
1849
1850 retry:
1851
1852 #ifdef HAVE_ACCEPT4
1853 /* We assume that if accept4 is available SOCK_CLOEXEC is too */
1854 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
1855 cloexec_done = client_fd >= 0;
1856
1857 if (client_fd < 0 && errno == ENOSYS)
1858 #endif
1859 {
1860 client_fd = accept (listen_fd, &addr, &addrlen);
1861 }
1862
1863 if (client_fd < 0)
1864 {
1865 if (errno == EINTR)
1866 goto retry;
1867 }
1868
1869 _dbus_verbose ("client fd %d accepted\n", client_fd);
1870
1871 #ifdef HAVE_ACCEPT4
1872 if (!cloexec_done)
1873 #endif
1874 {
1875 _dbus_fd_set_close_on_exec(client_fd);
1876 }
1877
1878 return client_fd;
1879 }
1880
1881 /**
1882 * Checks to make sure the given directory is
1883 * private to the user
1884 *
1885 * @param dir the name of the directory
1886 * @param error error return
1887 * @returns #FALSE on failure
1888 **/
1889 dbus_bool_t
_dbus_check_dir_is_private_to_user(DBusString * dir,DBusError * error)1890 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
1891 {
1892 const char *directory;
1893 struct stat sb;
1894
1895 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1896
1897 directory = _dbus_string_get_const_data (dir);
1898
1899 if (stat (directory, &sb) < 0)
1900 {
1901 dbus_set_error (error, _dbus_error_from_errno (errno),
1902 "%s", _dbus_strerror (errno));
1903
1904 return FALSE;
1905 }
1906
1907 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
1908 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
1909 {
1910 dbus_set_error (error, DBUS_ERROR_FAILED,
1911 "%s directory is not private to the user", directory);
1912 return FALSE;
1913 }
1914
1915 return TRUE;
1916 }
1917
1918 static dbus_bool_t
fill_user_info_from_passwd(struct passwd * p,DBusUserInfo * info,DBusError * error)1919 fill_user_info_from_passwd (struct passwd *p,
1920 DBusUserInfo *info,
1921 DBusError *error)
1922 {
1923 _dbus_assert (p->pw_name != NULL);
1924 _dbus_assert (p->pw_dir != NULL);
1925
1926 info->uid = p->pw_uid;
1927 info->primary_gid = p->pw_gid;
1928 info->username = _dbus_strdup (p->pw_name);
1929 info->homedir = _dbus_strdup (p->pw_dir);
1930
1931 if (info->username == NULL ||
1932 info->homedir == NULL)
1933 {
1934 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1935 return FALSE;
1936 }
1937
1938 return TRUE;
1939 }
1940
1941 static dbus_bool_t
fill_user_info(DBusUserInfo * info,dbus_uid_t uid,const DBusString * username,DBusError * error)1942 fill_user_info (DBusUserInfo *info,
1943 dbus_uid_t uid,
1944 const DBusString *username,
1945 DBusError *error)
1946 {
1947 const char *username_c;
1948
1949 /* exactly one of username/uid provided */
1950 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
1951 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
1952
1953 info->uid = DBUS_UID_UNSET;
1954 info->primary_gid = DBUS_GID_UNSET;
1955 info->group_ids = NULL;
1956 info->n_group_ids = 0;
1957 info->username = NULL;
1958 info->homedir = NULL;
1959
1960 if (username != NULL)
1961 username_c = _dbus_string_get_const_data (username);
1962 else
1963 username_c = NULL;
1964
1965 /* For now assuming that the getpwnam() and getpwuid() flavors
1966 * are always symmetrical, if not we have to add more configure
1967 * checks
1968 */
1969
1970 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
1971 {
1972 struct passwd *p;
1973 int result;
1974 size_t buflen;
1975 char *buf;
1976 struct passwd p_str;
1977
1978 /* retrieve maximum needed size for buf */
1979 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
1980
1981 /* sysconf actually returns a long, but everything else expects size_t,
1982 * so just recast here.
1983 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
1984 */
1985 if ((long) buflen <= 0)
1986 buflen = 1024;
1987
1988 result = -1;
1989 while (1)
1990 {
1991 buf = dbus_malloc (buflen);
1992 if (buf == NULL)
1993 {
1994 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1995 return FALSE;
1996 }
1997
1998 p = NULL;
1999 #ifdef HAVE_POSIX_GETPWNAM_R
2000 if (uid != DBUS_UID_UNSET)
2001 result = getpwuid_r (uid, &p_str, buf, buflen,
2002 &p);
2003 else
2004 result = getpwnam_r (username_c, &p_str, buf, buflen,
2005 &p);
2006 #else
2007 if (uid != DBUS_UID_UNSET)
2008 p = getpwuid_r (uid, &p_str, buf, buflen);
2009 else
2010 p = getpwnam_r (username_c, &p_str, buf, buflen);
2011 result = 0;
2012 #endif /* !HAVE_POSIX_GETPWNAM_R */
2013 //Try a bigger buffer if ERANGE was returned
2014 if (result == ERANGE && buflen < 512 * 1024)
2015 {
2016 dbus_free (buf);
2017 buflen *= 2;
2018 }
2019 else
2020 {
2021 break;
2022 }
2023 }
2024 if (result == 0 && p == &p_str)
2025 {
2026 if (!fill_user_info_from_passwd (p, info, error))
2027 {
2028 dbus_free (buf);
2029 return FALSE;
2030 }
2031 dbus_free (buf);
2032 }
2033 else
2034 {
2035 dbus_set_error (error, _dbus_error_from_errno (errno),
2036 "User \"%s\" unknown or no memory to allocate password entry\n",
2037 username_c ? username_c : "???");
2038 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2039 dbus_free (buf);
2040 return FALSE;
2041 }
2042 }
2043 #else /* ! HAVE_GETPWNAM_R */
2044 {
2045 /* I guess we're screwed on thread safety here */
2046 struct passwd *p;
2047
2048 if (uid != DBUS_UID_UNSET)
2049 p = getpwuid (uid);
2050 else
2051 p = getpwnam (username_c);
2052
2053 if (p != NULL)
2054 {
2055 if (!fill_user_info_from_passwd (p, info, error))
2056 {
2057 return FALSE;
2058 }
2059 }
2060 else
2061 {
2062 dbus_set_error (error, _dbus_error_from_errno (errno),
2063 "User \"%s\" unknown or no memory to allocate password entry\n",
2064 username_c ? username_c : "???");
2065 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2066 return FALSE;
2067 }
2068 }
2069 #endif /* ! HAVE_GETPWNAM_R */
2070
2071 /* Fill this in so we can use it to get groups */
2072 username_c = info->username;
2073
2074 #ifdef HAVE_GETGROUPLIST
2075 {
2076 gid_t *buf;
2077 int buf_count;
2078 int i;
2079 int initial_buf_count;
2080
2081 initial_buf_count = 17;
2082 buf_count = initial_buf_count;
2083 buf = dbus_new (gid_t, buf_count);
2084 if (buf == NULL)
2085 {
2086 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2087 goto failed;
2088 }
2089
2090 if (getgrouplist (username_c,
2091 info->primary_gid,
2092 buf, &buf_count) < 0)
2093 {
2094 gid_t *new;
2095 /* Presumed cause of negative return code: buf has insufficient
2096 entries to hold the entire group list. The Linux behavior in this
2097 case is to pass back the actual number of groups in buf_count, but
2098 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2099 So as a hack, try to help out a bit by guessing a larger
2100 number of groups, within reason.. might still fail, of course,
2101 but we can at least print a more informative message. I looked up
2102 the "right way" to do this by downloading Apple's own source code
2103 for the "id" command, and it turns out that they use an
2104 undocumented library function getgrouplist_2 (!) which is not
2105 declared in any header in /usr/include (!!). That did not seem
2106 like the way to go here.
2107 */
2108 if (buf_count == initial_buf_count)
2109 {
2110 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2111 }
2112 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2113 if (new == NULL)
2114 {
2115 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2116 dbus_free (buf);
2117 goto failed;
2118 }
2119
2120 buf = new;
2121
2122 errno = 0;
2123 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2124 {
2125 if (errno == 0)
2126 {
2127 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2128 username_c, buf_count, buf_count);
2129 }
2130 else
2131 {
2132 dbus_set_error (error,
2133 _dbus_error_from_errno (errno),
2134 "Failed to get groups for username \"%s\" primary GID "
2135 DBUS_GID_FORMAT ": %s\n",
2136 username_c, info->primary_gid,
2137 _dbus_strerror (errno));
2138 dbus_free (buf);
2139 goto failed;
2140 }
2141 }
2142 }
2143
2144 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2145 if (info->group_ids == NULL)
2146 {
2147 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2148 dbus_free (buf);
2149 goto failed;
2150 }
2151
2152 for (i = 0; i < buf_count; ++i)
2153 info->group_ids[i] = buf[i];
2154
2155 info->n_group_ids = buf_count;
2156
2157 dbus_free (buf);
2158 }
2159 #else /* HAVE_GETGROUPLIST */
2160 {
2161 /* We just get the one group ID */
2162 info->group_ids = dbus_new (dbus_gid_t, 1);
2163 if (info->group_ids == NULL)
2164 {
2165 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2166 goto failed;
2167 }
2168
2169 info->n_group_ids = 1;
2170
2171 (info->group_ids)[0] = info->primary_gid;
2172 }
2173 #endif /* HAVE_GETGROUPLIST */
2174
2175 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2176
2177 return TRUE;
2178
2179 failed:
2180 _DBUS_ASSERT_ERROR_IS_SET (error);
2181 return FALSE;
2182 }
2183
2184 /**
2185 * Gets user info for the given username.
2186 *
2187 * @param info user info object to initialize
2188 * @param username the username
2189 * @param error error return
2190 * @returns #TRUE on success
2191 */
2192 dbus_bool_t
_dbus_user_info_fill(DBusUserInfo * info,const DBusString * username,DBusError * error)2193 _dbus_user_info_fill (DBusUserInfo *info,
2194 const DBusString *username,
2195 DBusError *error)
2196 {
2197 return fill_user_info (info, DBUS_UID_UNSET,
2198 username, error);
2199 }
2200
2201 /**
2202 * Gets user info for the given user ID.
2203 *
2204 * @param info user info object to initialize
2205 * @param uid the user ID
2206 * @param error error return
2207 * @returns #TRUE on success
2208 */
2209 dbus_bool_t
_dbus_user_info_fill_uid(DBusUserInfo * info,dbus_uid_t uid,DBusError * error)2210 _dbus_user_info_fill_uid (DBusUserInfo *info,
2211 dbus_uid_t uid,
2212 DBusError *error)
2213 {
2214 return fill_user_info (info, uid,
2215 NULL, error);
2216 }
2217
2218 /**
2219 * Adds the credentials of the current process to the
2220 * passed-in credentials object.
2221 *
2222 * @param credentials credentials to add to
2223 * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
2224 */
2225 dbus_bool_t
_dbus_credentials_add_from_current_process(DBusCredentials * credentials)2226 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2227 {
2228 /* The POSIX spec certainly doesn't promise this, but
2229 * we need these assertions to fail as soon as we're wrong about
2230 * it so we can do the porting fixups
2231 */
2232 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
2233 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
2234 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
2235
2236 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
2237 return FALSE;
2238 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2239 return FALSE;
2240
2241 return TRUE;
2242 }
2243
2244 /**
2245 * Append to the string the identity we would like to have when we
2246 * authenticate, on UNIX this is the current process UID and on
2247 * Windows something else, probably a Windows SID string. No escaping
2248 * is required, that is done in dbus-auth.c. The username here
2249 * need not be anything human-readable, it can be the machine-readable
2250 * form i.e. a user id.
2251 *
2252 * @param str the string to append to
2253 * @returns #FALSE on no memory
2254 */
2255 dbus_bool_t
_dbus_append_user_from_current_process(DBusString * str)2256 _dbus_append_user_from_current_process (DBusString *str)
2257 {
2258 return _dbus_string_append_uint (str,
2259 _dbus_geteuid ());
2260 }
2261
2262 /**
2263 * Gets our process ID
2264 * @returns process ID
2265 */
2266 dbus_pid_t
_dbus_getpid(void)2267 _dbus_getpid (void)
2268 {
2269 return getpid ();
2270 }
2271
2272 /** Gets our UID
2273 * @returns process UID
2274 */
2275 dbus_uid_t
_dbus_getuid(void)2276 _dbus_getuid (void)
2277 {
2278 return getuid ();
2279 }
2280
2281 /** Gets our effective UID
2282 * @returns process effective UID
2283 */
2284 dbus_uid_t
_dbus_geteuid(void)2285 _dbus_geteuid (void)
2286 {
2287 return geteuid ();
2288 }
2289
2290 /**
2291 * The only reason this is separate from _dbus_getpid() is to allow it
2292 * on Windows for logging but not for other purposes.
2293 *
2294 * @returns process ID to put in log messages
2295 */
2296 unsigned long
_dbus_pid_for_log(void)2297 _dbus_pid_for_log (void)
2298 {
2299 return getpid ();
2300 }
2301
2302 /**
2303 * Gets a UID from a UID string.
2304 *
2305 * @param uid_str the UID in string form
2306 * @param uid UID to fill in
2307 * @returns #TRUE if successfully filled in UID
2308 */
2309 dbus_bool_t
_dbus_parse_uid(const DBusString * uid_str,dbus_uid_t * uid)2310 _dbus_parse_uid (const DBusString *uid_str,
2311 dbus_uid_t *uid)
2312 {
2313 int end;
2314 long val;
2315
2316 if (_dbus_string_get_length (uid_str) == 0)
2317 {
2318 _dbus_verbose ("UID string was zero length\n");
2319 return FALSE;
2320 }
2321
2322 val = -1;
2323 end = 0;
2324 if (!_dbus_string_parse_int (uid_str, 0, &val,
2325 &end))
2326 {
2327 _dbus_verbose ("could not parse string as a UID\n");
2328 return FALSE;
2329 }
2330
2331 if (end != _dbus_string_get_length (uid_str))
2332 {
2333 _dbus_verbose ("string contained trailing stuff after UID\n");
2334 return FALSE;
2335 }
2336
2337 *uid = val;
2338
2339 return TRUE;
2340 }
2341
2342 #if !DBUS_USE_SYNC
2343 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
2344 #endif
2345
2346 /**
2347 * Atomically increments an integer
2348 *
2349 * @param atomic pointer to the integer to increment
2350 * @returns the value before incrementing
2351 */
2352 dbus_int32_t
_dbus_atomic_inc(DBusAtomic * atomic)2353 _dbus_atomic_inc (DBusAtomic *atomic)
2354 {
2355 #if DBUS_USE_SYNC
2356 return __sync_add_and_fetch(&atomic->value, 1)-1;
2357 #elif defined(ANDROID_ATOMIC)
2358 return android_atomic_inc (&(atomic->value));
2359 #else
2360 dbus_int32_t res;
2361 _DBUS_LOCK (atomic);
2362 res = atomic->value;
2363 atomic->value += 1;
2364 _DBUS_UNLOCK (atomic);
2365 return res;
2366 #endif
2367 }
2368
2369 /**
2370 * Atomically decrement an integer
2371 *
2372 * @param atomic pointer to the integer to decrement
2373 * @returns the value before decrementing
2374 */
2375 dbus_int32_t
_dbus_atomic_dec(DBusAtomic * atomic)2376 _dbus_atomic_dec (DBusAtomic *atomic)
2377 {
2378 #if DBUS_USE_SYNC
2379 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2380 #elif defined(ANDROID_ATOMIC)
2381 return android_atomic_dec (&(atomic->value));
2382 #else
2383 dbus_int32_t res;
2384
2385 _DBUS_LOCK (atomic);
2386 res = atomic->value;
2387 atomic->value -= 1;
2388 _DBUS_UNLOCK (atomic);
2389 return res;
2390 #endif
2391 }
2392
2393 #ifdef DBUS_BUILD_TESTS
2394 /** Gets our GID
2395 * @returns process GID
2396 */
2397 dbus_gid_t
_dbus_getgid(void)2398 _dbus_getgid (void)
2399 {
2400 return getgid ();
2401 }
2402 #endif
2403
2404 /**
2405 * Wrapper for poll().
2406 *
2407 * @param fds the file descriptors to poll
2408 * @param n_fds number of descriptors in the array
2409 * @param timeout_milliseconds timeout or -1 for infinite
2410 * @returns numbers of fds with revents, or <0 on error
2411 */
2412 int
_dbus_poll(DBusPollFD * fds,int n_fds,int timeout_milliseconds)2413 _dbus_poll (DBusPollFD *fds,
2414 int n_fds,
2415 int timeout_milliseconds)
2416 {
2417 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2418 /* This big thing is a constant expression and should get optimized
2419 * out of existence. So it's more robust than a configure check at
2420 * no cost.
2421 */
2422 if (_DBUS_POLLIN == POLLIN &&
2423 _DBUS_POLLPRI == POLLPRI &&
2424 _DBUS_POLLOUT == POLLOUT &&
2425 _DBUS_POLLERR == POLLERR &&
2426 _DBUS_POLLHUP == POLLHUP &&
2427 _DBUS_POLLNVAL == POLLNVAL &&
2428 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
2429 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
2430 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
2431 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
2432 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
2433 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
2434 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
2435 {
2436 return poll ((struct pollfd*) fds,
2437 n_fds,
2438 timeout_milliseconds);
2439 }
2440 else
2441 {
2442 /* We have to convert the DBusPollFD to an array of
2443 * struct pollfd, poll, and convert back.
2444 */
2445 _dbus_warn ("didn't implement poll() properly for this system yet\n");
2446 return -1;
2447 }
2448 #else /* ! HAVE_POLL */
2449
2450 fd_set read_set, write_set, err_set;
2451 int max_fd = 0;
2452 int i;
2453 struct timeval tv;
2454 int ready;
2455
2456 FD_ZERO (&read_set);
2457 FD_ZERO (&write_set);
2458 FD_ZERO (&err_set);
2459
2460 for (i = 0; i < n_fds; i++)
2461 {
2462 DBusPollFD *fdp = &fds[i];
2463
2464 if (fdp->events & _DBUS_POLLIN)
2465 FD_SET (fdp->fd, &read_set);
2466
2467 if (fdp->events & _DBUS_POLLOUT)
2468 FD_SET (fdp->fd, &write_set);
2469
2470 FD_SET (fdp->fd, &err_set);
2471
2472 max_fd = MAX (max_fd, fdp->fd);
2473 }
2474
2475 tv.tv_sec = timeout_milliseconds / 1000;
2476 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2477
2478 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2479 timeout_milliseconds < 0 ? NULL : &tv);
2480
2481 if (ready > 0)
2482 {
2483 for (i = 0; i < n_fds; i++)
2484 {
2485 DBusPollFD *fdp = &fds[i];
2486
2487 fdp->revents = 0;
2488
2489 if (FD_ISSET (fdp->fd, &read_set))
2490 fdp->revents |= _DBUS_POLLIN;
2491
2492 if (FD_ISSET (fdp->fd, &write_set))
2493 fdp->revents |= _DBUS_POLLOUT;
2494
2495 if (FD_ISSET (fdp->fd, &err_set))
2496 fdp->revents |= _DBUS_POLLERR;
2497 }
2498 }
2499
2500 return ready;
2501 #endif
2502 }
2503
2504 /**
2505 * Get current time, as in gettimeofday(). Use the monotonic clock if
2506 * available, to avoid problems when the system time changes.
2507 *
2508 * @param tv_sec return location for number of seconds
2509 * @param tv_usec return location for number of microseconds (thousandths)
2510 */
2511 void
_dbus_get_current_time(long * tv_sec,long * tv_usec)2512 _dbus_get_current_time (long *tv_sec,
2513 long *tv_usec)
2514 {
2515 struct timeval t;
2516
2517 #ifdef HAVE_MONOTONIC_CLOCK
2518 struct timespec ts;
2519 clock_gettime (CLOCK_MONOTONIC, &ts);
2520
2521 if (tv_sec)
2522 *tv_sec = ts.tv_sec;
2523 if (tv_usec)
2524 *tv_usec = ts.tv_nsec / 1000;
2525 #else
2526 gettimeofday (&t, NULL);
2527
2528 if (tv_sec)
2529 *tv_sec = t.tv_sec;
2530 if (tv_usec)
2531 *tv_usec = t.tv_usec;
2532 #endif
2533 }
2534
2535 /**
2536 * Creates a directory; succeeds if the directory
2537 * is created or already existed.
2538 *
2539 * @param filename directory filename
2540 * @param error initialized error object
2541 * @returns #TRUE on success
2542 */
2543 dbus_bool_t
_dbus_create_directory(const DBusString * filename,DBusError * error)2544 _dbus_create_directory (const DBusString *filename,
2545 DBusError *error)
2546 {
2547 const char *filename_c;
2548
2549 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2550
2551 filename_c = _dbus_string_get_const_data (filename);
2552
2553 if (mkdir (filename_c, 0700) < 0)
2554 {
2555 if (errno == EEXIST)
2556 return TRUE;
2557
2558 dbus_set_error (error, DBUS_ERROR_FAILED,
2559 "Failed to create directory %s: %s\n",
2560 filename_c, _dbus_strerror (errno));
2561 return FALSE;
2562 }
2563 else
2564 return TRUE;
2565 }
2566
2567 /**
2568 * Appends the given filename to the given directory.
2569 *
2570 * @todo it might be cute to collapse multiple '/' such as "foo//"
2571 * concat "//bar"
2572 *
2573 * @param dir the directory name
2574 * @param next_component the filename
2575 * @returns #TRUE on success
2576 */
2577 dbus_bool_t
_dbus_concat_dir_and_file(DBusString * dir,const DBusString * next_component)2578 _dbus_concat_dir_and_file (DBusString *dir,
2579 const DBusString *next_component)
2580 {
2581 dbus_bool_t dir_ends_in_slash;
2582 dbus_bool_t file_starts_with_slash;
2583
2584 if (_dbus_string_get_length (dir) == 0 ||
2585 _dbus_string_get_length (next_component) == 0)
2586 return TRUE;
2587
2588 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
2589 _dbus_string_get_length (dir) - 1);
2590
2591 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
2592
2593 if (dir_ends_in_slash && file_starts_with_slash)
2594 {
2595 _dbus_string_shorten (dir, 1);
2596 }
2597 else if (!(dir_ends_in_slash || file_starts_with_slash))
2598 {
2599 if (!_dbus_string_append_byte (dir, '/'))
2600 return FALSE;
2601 }
2602
2603 return _dbus_string_copy (next_component, 0, dir,
2604 _dbus_string_get_length (dir));
2605 }
2606
2607 /** nanoseconds in a second */
2608 #define NANOSECONDS_PER_SECOND 1000000000
2609 /** microseconds in a second */
2610 #define MICROSECONDS_PER_SECOND 1000000
2611 /** milliseconds in a second */
2612 #define MILLISECONDS_PER_SECOND 1000
2613 /** nanoseconds in a millisecond */
2614 #define NANOSECONDS_PER_MILLISECOND 1000000
2615 /** microseconds in a millisecond */
2616 #define MICROSECONDS_PER_MILLISECOND 1000
2617
2618 /**
2619 * Sleeps the given number of milliseconds.
2620 * @param milliseconds number of milliseconds
2621 */
2622 void
_dbus_sleep_milliseconds(int milliseconds)2623 _dbus_sleep_milliseconds (int milliseconds)
2624 {
2625 #ifdef HAVE_NANOSLEEP
2626 struct timespec req;
2627 struct timespec rem;
2628
2629 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
2630 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
2631 rem.tv_sec = 0;
2632 rem.tv_nsec = 0;
2633
2634 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
2635 req = rem;
2636 #elif defined (HAVE_USLEEP)
2637 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
2638 #else /* ! HAVE_USLEEP */
2639 sleep (MAX (milliseconds / 1000, 1));
2640 #endif
2641 }
2642
2643 static dbus_bool_t
_dbus_generate_pseudorandom_bytes(DBusString * str,int n_bytes)2644 _dbus_generate_pseudorandom_bytes (DBusString *str,
2645 int n_bytes)
2646 {
2647 int old_len;
2648 char *p;
2649
2650 old_len = _dbus_string_get_length (str);
2651
2652 if (!_dbus_string_lengthen (str, n_bytes))
2653 return FALSE;
2654
2655 p = _dbus_string_get_data_len (str, old_len, n_bytes);
2656
2657 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
2658
2659 return TRUE;
2660 }
2661
2662 /**
2663 * Generates the given number of random bytes,
2664 * using the best mechanism we can come up with.
2665 *
2666 * @param str the string
2667 * @param n_bytes the number of random bytes to append to string
2668 * @returns #TRUE on success, #FALSE if no memory
2669 */
2670 dbus_bool_t
_dbus_generate_random_bytes(DBusString * str,int n_bytes)2671 _dbus_generate_random_bytes (DBusString *str,
2672 int n_bytes)
2673 {
2674 int old_len;
2675 int fd;
2676
2677 /* FALSE return means "no memory", if it could
2678 * mean something else then we'd need to return
2679 * a DBusError. So we always fall back to pseudorandom
2680 * if the I/O fails.
2681 */
2682
2683 old_len = _dbus_string_get_length (str);
2684 fd = -1;
2685
2686 /* note, urandom on linux will fall back to pseudorandom */
2687 fd = open ("/dev/urandom", O_RDONLY);
2688 if (fd < 0)
2689 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2690
2691 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
2692
2693 if (_dbus_read (fd, str, n_bytes) != n_bytes)
2694 {
2695 _dbus_close (fd, NULL);
2696 _dbus_string_set_length (str, old_len);
2697 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2698 }
2699
2700 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2701 n_bytes);
2702
2703 _dbus_close (fd, NULL);
2704
2705 return TRUE;
2706 }
2707
2708 /**
2709 * Exit the process, returning the given value.
2710 *
2711 * @param code the exit code
2712 */
2713 void
_dbus_exit(int code)2714 _dbus_exit (int code)
2715 {
2716 _exit (code);
2717 }
2718
2719 /**
2720 * A wrapper around strerror() because some platforms
2721 * may be lame and not have strerror(). Also, never
2722 * returns NULL.
2723 *
2724 * @param error_number errno.
2725 * @returns error description.
2726 */
2727 const char*
_dbus_strerror(int error_number)2728 _dbus_strerror (int error_number)
2729 {
2730 const char *msg;
2731
2732 msg = strerror (error_number);
2733 if (msg == NULL)
2734 msg = "unknown";
2735
2736 return msg;
2737 }
2738
2739 /**
2740 * signal (SIGPIPE, SIG_IGN);
2741 */
2742 void
_dbus_disable_sigpipe(void)2743 _dbus_disable_sigpipe (void)
2744 {
2745 signal (SIGPIPE, SIG_IGN);
2746 }
2747
2748 /**
2749 * Sets the file descriptor to be close
2750 * on exec. Should be called for all file
2751 * descriptors in D-Bus code.
2752 *
2753 * @param fd the file descriptor
2754 */
2755 void
_dbus_fd_set_close_on_exec(intptr_t fd)2756 _dbus_fd_set_close_on_exec (intptr_t fd)
2757 {
2758 int val;
2759
2760 val = fcntl (fd, F_GETFD, 0);
2761
2762 if (val < 0)
2763 return;
2764
2765 val |= FD_CLOEXEC;
2766
2767 fcntl (fd, F_SETFD, val);
2768 }
2769
2770 /**
2771 * Closes a file descriptor.
2772 *
2773 * @param fd the file descriptor
2774 * @param error error object
2775 * @returns #FALSE if error set
2776 */
2777 dbus_bool_t
_dbus_close(int fd,DBusError * error)2778 _dbus_close (int fd,
2779 DBusError *error)
2780 {
2781 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2782
2783 again:
2784 if (close (fd) < 0)
2785 {
2786 if (errno == EINTR)
2787 goto again;
2788
2789 dbus_set_error (error, _dbus_error_from_errno (errno),
2790 "Could not close fd %d", fd);
2791 return FALSE;
2792 }
2793
2794 return TRUE;
2795 }
2796
2797 /**
2798 * Duplicates a file descriptor. Makes sure the fd returned is >= 3
2799 * (i.e. avoids stdin/stdout/stderr). Sets O_CLOEXEC.
2800 *
2801 * @param fd the file descriptor to duplicate
2802 * @returns duplicated file descriptor
2803 * */
2804 int
_dbus_dup(int fd,DBusError * error)2805 _dbus_dup(int fd,
2806 DBusError *error)
2807 {
2808 int new_fd;
2809
2810 #ifdef F_DUPFD_CLOEXEC
2811 dbus_bool_t cloexec_done;
2812
2813 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2814 cloexec_done = new_fd >= 0;
2815
2816 if (new_fd < 0 && errno == EINVAL)
2817 #endif
2818 {
2819 new_fd = fcntl(fd, F_DUPFD, 3);
2820 }
2821
2822 if (new_fd < 0) {
2823
2824 dbus_set_error (error, _dbus_error_from_errno (errno),
2825 "Could not duplicate fd %d", fd);
2826 return -1;
2827 }
2828
2829 #ifdef F_DUPFD_CLOEXEC
2830 if (!cloexec_done)
2831 #endif
2832 {
2833 _dbus_fd_set_close_on_exec(new_fd);
2834 }
2835
2836 return new_fd;
2837 }
2838
2839 /**
2840 * Sets a file descriptor to be nonblocking.
2841 *
2842 * @param fd the file descriptor.
2843 * @param error address of error location.
2844 * @returns #TRUE on success.
2845 */
2846 dbus_bool_t
_dbus_set_fd_nonblocking(int fd,DBusError * error)2847 _dbus_set_fd_nonblocking (int fd,
2848 DBusError *error)
2849 {
2850 int val;
2851
2852 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2853
2854 val = fcntl (fd, F_GETFL, 0);
2855 if (val < 0)
2856 {
2857 dbus_set_error (error, _dbus_error_from_errno (errno),
2858 "Failed to get flags from file descriptor %d: %s",
2859 fd, _dbus_strerror (errno));
2860 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
2861 _dbus_strerror (errno));
2862 return FALSE;
2863 }
2864
2865 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
2866 {
2867 dbus_set_error (error, _dbus_error_from_errno (errno),
2868 "Failed to set nonblocking flag of file descriptor %d: %s",
2869 fd, _dbus_strerror (errno));
2870 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
2871 fd, _dbus_strerror (errno));
2872
2873 return FALSE;
2874 }
2875
2876 return TRUE;
2877 }
2878
2879 /**
2880 * On GNU libc systems, print a crude backtrace to stderr. On other
2881 * systems, print "no backtrace support" and block for possible gdb
2882 * attachment if an appropriate environment variable is set.
2883 */
2884 void
_dbus_print_backtrace(void)2885 _dbus_print_backtrace (void)
2886 {
2887 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
2888 void *bt[500];
2889 int bt_size;
2890 int i;
2891 char **syms;
2892
2893 bt_size = backtrace (bt, 500);
2894
2895 syms = backtrace_symbols (bt, bt_size);
2896
2897 i = 0;
2898 while (i < bt_size)
2899 {
2900 /* don't use dbus_warn since it can _dbus_abort() */
2901 fprintf (stderr, " %s\n", syms[i]);
2902 ++i;
2903 }
2904 fflush (stderr);
2905
2906 free (syms);
2907 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
2908 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
2909 #else
2910 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
2911 #endif
2912 }
2913
2914 /**
2915 * Creates a full-duplex pipe (as in socketpair()).
2916 * Sets both ends of the pipe nonblocking.
2917 *
2918 * Marks both file descriptors as close-on-exec
2919 *
2920 * @todo libdbus only uses this for the debug-pipe server, so in
2921 * principle it could be in dbus-sysdeps-util.c, except that
2922 * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
2923 * debug-pipe server is used.
2924 *
2925 * @param fd1 return location for one end
2926 * @param fd2 return location for the other end
2927 * @param blocking #TRUE if pipe should be blocking
2928 * @param error error return
2929 * @returns #FALSE on failure (if error is set)
2930 */
2931 dbus_bool_t
_dbus_full_duplex_pipe(int * fd1,int * fd2,dbus_bool_t blocking,DBusError * error)2932 _dbus_full_duplex_pipe (int *fd1,
2933 int *fd2,
2934 dbus_bool_t blocking,
2935 DBusError *error)
2936 {
2937 #ifdef HAVE_SOCKETPAIR
2938 int fds[2];
2939 int retval;
2940
2941 #ifdef SOCK_CLOEXEC
2942 dbus_bool_t cloexec_done;
2943
2944 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
2945 cloexec_done = retval >= 0;
2946
2947 if (retval < 0 && errno == EINVAL)
2948 #endif
2949 {
2950 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
2951 }
2952
2953 if (retval < 0)
2954 {
2955 dbus_set_error (error, _dbus_error_from_errno (errno),
2956 "Could not create full-duplex pipe");
2957 return FALSE;
2958 }
2959
2960 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2961
2962 #ifdef SOCK_CLOEXEC
2963 if (!cloexec_done)
2964 #endif
2965 {
2966 _dbus_fd_set_close_on_exec (fds[0]);
2967 _dbus_fd_set_close_on_exec (fds[1]);
2968 }
2969
2970 if (!blocking &&
2971 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
2972 !_dbus_set_fd_nonblocking (fds[1], NULL)))
2973 {
2974 dbus_set_error (error, _dbus_error_from_errno (errno),
2975 "Could not set full-duplex pipe nonblocking");
2976
2977 _dbus_close (fds[0], NULL);
2978 _dbus_close (fds[1], NULL);
2979
2980 return FALSE;
2981 }
2982
2983 *fd1 = fds[0];
2984 *fd2 = fds[1];
2985
2986 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
2987 *fd1, *fd2);
2988
2989 return TRUE;
2990 #else
2991 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
2992 dbus_set_error (error, DBUS_ERROR_FAILED,
2993 "_dbus_full_duplex_pipe() not implemented on this OS");
2994 return FALSE;
2995 #endif
2996 }
2997
2998 /**
2999 * Measure the length of the given format string and arguments,
3000 * not including the terminating nul.
3001 *
3002 * @param format a printf-style format string
3003 * @param args arguments for the format string
3004 * @returns length of the given format string and args
3005 */
3006 int
_dbus_printf_string_upper_bound(const char * format,va_list args)3007 _dbus_printf_string_upper_bound (const char *format,
3008 va_list args)
3009 {
3010 char c;
3011 return vsnprintf (&c, 1, format, args);
3012 }
3013
3014 /**
3015 * Gets the temporary files directory by inspecting the environment variables
3016 * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
3017 *
3018 * @returns location of temp directory
3019 */
3020 const char*
_dbus_get_tmpdir(void)3021 _dbus_get_tmpdir(void)
3022 {
3023 static const char* tmpdir = NULL;
3024
3025 if (tmpdir == NULL)
3026 {
3027 /* TMPDIR is what glibc uses, then
3028 * glibc falls back to the P_tmpdir macro which
3029 * just expands to "/tmp"
3030 */
3031 if (tmpdir == NULL)
3032 tmpdir = getenv("TMPDIR");
3033
3034 /* These two env variables are probably
3035 * broken, but maybe some OS uses them?
3036 */
3037 if (tmpdir == NULL)
3038 tmpdir = getenv("TMP");
3039 if (tmpdir == NULL)
3040 tmpdir = getenv("TEMP");
3041
3042 /* And this is the sane fallback. */
3043 if (tmpdir == NULL)
3044 tmpdir = "/tmp";
3045 }
3046
3047 _dbus_assert(tmpdir != NULL);
3048
3049 return tmpdir;
3050 }
3051
3052 /**
3053 * Execute a subprocess, returning up to 1024 bytes of output
3054 * into @p result.
3055 *
3056 * If successful, returns #TRUE and appends the output to @p
3057 * result. If a failure happens, returns #FALSE and
3058 * sets an error in @p error.
3059 *
3060 * @note It's not an error if the subprocess terminates normally
3061 * without writing any data to stdout. Verify the @p result length
3062 * before and after this function call to cover this case.
3063 *
3064 * @param progname initial path to exec (may or may not be absolute)
3065 * @param path_fallback if %TRUE, search PATH for executable
3066 * @param argv NULL-terminated list of arguments
3067 * @param result a DBusString where the output can be append
3068 * @param error a DBusError to store the error in case of failure
3069 * @returns #TRUE on success, #FALSE if an error happened
3070 */
3071 static dbus_bool_t
_read_subprocess_line_argv(const char * progpath,dbus_bool_t path_fallback,char * const * argv,DBusString * result,DBusError * error)3072 _read_subprocess_line_argv (const char *progpath,
3073 dbus_bool_t path_fallback,
3074 char * const *argv,
3075 DBusString *result,
3076 DBusError *error)
3077 {
3078 int result_pipe[2] = { -1, -1 };
3079 int errors_pipe[2] = { -1, -1 };
3080 pid_t pid;
3081 int ret;
3082 int status;
3083 int orig_len;
3084 int i;
3085
3086 dbus_bool_t retval;
3087 sigset_t new_set, old_set;
3088
3089 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3090 retval = FALSE;
3091
3092 /* We need to block any existing handlers for SIGCHLD temporarily; they
3093 * will cause waitpid() below to fail.
3094 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3095 */
3096 sigemptyset (&new_set);
3097 sigaddset (&new_set, SIGCHLD);
3098 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3099
3100 orig_len = _dbus_string_get_length (result);
3101
3102 #define READ_END 0
3103 #define WRITE_END 1
3104 if (pipe (result_pipe) < 0)
3105 {
3106 dbus_set_error (error, _dbus_error_from_errno (errno),
3107 "Failed to create a pipe to call %s: %s",
3108 progpath, _dbus_strerror (errno));
3109 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3110 progpath, _dbus_strerror (errno));
3111 goto out;
3112 }
3113 if (pipe (errors_pipe) < 0)
3114 {
3115 dbus_set_error (error, _dbus_error_from_errno (errno),
3116 "Failed to create a pipe to call %s: %s",
3117 progpath, _dbus_strerror (errno));
3118 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3119 progpath, _dbus_strerror (errno));
3120 goto out;
3121 }
3122
3123 pid = fork ();
3124 if (pid < 0)
3125 {
3126 dbus_set_error (error, _dbus_error_from_errno (errno),
3127 "Failed to fork() to call %s: %s",
3128 progpath, _dbus_strerror (errno));
3129 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3130 progpath, _dbus_strerror (errno));
3131 goto out;
3132 }
3133
3134 if (pid == 0)
3135 {
3136 /* child process */
3137 int maxfds;
3138 int fd;
3139
3140 fd = open ("/dev/null", O_RDWR);
3141 if (fd == -1)
3142 /* huh?! can't open /dev/null? */
3143 _exit (1);
3144
3145 _dbus_verbose ("/dev/null fd %d opened\n", fd);
3146
3147 /* set-up stdXXX */
3148 close (result_pipe[READ_END]);
3149 close (errors_pipe[READ_END]);
3150 close (0); /* close stdin */
3151 close (1); /* close stdout */
3152 close (2); /* close stderr */
3153
3154 if (dup2 (fd, 0) == -1)
3155 _exit (1);
3156 if (dup2 (result_pipe[WRITE_END], 1) == -1)
3157 _exit (1);
3158 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
3159 _exit (1);
3160
3161 maxfds = sysconf (_SC_OPEN_MAX);
3162 /* Pick something reasonable if for some reason sysconf
3163 * says unlimited.
3164 */
3165 if (maxfds < 0)
3166 maxfds = 1024;
3167 /* close all inherited fds */
3168 for (i = 3; i < maxfds; i++)
3169 close (i);
3170
3171 sigprocmask (SIG_SETMASK, &old_set, NULL);
3172
3173 /* If it looks fully-qualified, try execv first */
3174 if (progpath[0] == '/')
3175 {
3176 execv (progpath, argv);
3177 /* Ok, that failed. Now if path_fallback is given, let's
3178 * try unqualified. This is mostly a hack to work
3179 * around systems which ship dbus-launch in /usr/bin
3180 * but everything else in /bin (because dbus-launch
3181 * depends on X11).
3182 */
3183 if (path_fallback)
3184 /* We must have a slash, because we checked above */
3185 execvp (strrchr (progpath, '/')+1, argv);
3186 }
3187 else
3188 execvp (progpath, argv);
3189
3190 /* still nothing, we failed */
3191 _exit (1);
3192 }
3193
3194 /* parent process */
3195 close (result_pipe[WRITE_END]);
3196 close (errors_pipe[WRITE_END]);
3197 result_pipe[WRITE_END] = -1;
3198 errors_pipe[WRITE_END] = -1;
3199
3200 ret = 0;
3201 do
3202 {
3203 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3204 }
3205 while (ret > 0);
3206
3207 /* reap the child process to avoid it lingering as zombie */
3208 do
3209 {
3210 ret = waitpid (pid, &status, 0);
3211 }
3212 while (ret == -1 && errno == EINTR);
3213
3214 /* We succeeded if the process exited with status 0 and
3215 anything was read */
3216 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3217 {
3218 /* The process ended with error */
3219 DBusString error_message;
3220 _dbus_string_init (&error_message);
3221 ret = 0;
3222 do
3223 {
3224 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3225 }
3226 while (ret > 0);
3227
3228 _dbus_string_set_length (result, orig_len);
3229 if (_dbus_string_get_length (&error_message) > 0)
3230 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3231 "%s terminated abnormally with the following error: %s",
3232 progpath, _dbus_string_get_data (&error_message));
3233 else
3234 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3235 "%s terminated abnormally without any error message",
3236 progpath);
3237 goto out;
3238 }
3239
3240 retval = TRUE;
3241
3242 out:
3243 sigprocmask (SIG_SETMASK, &old_set, NULL);
3244
3245 if (retval)
3246 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3247 else
3248 _DBUS_ASSERT_ERROR_IS_SET (error);
3249
3250 if (result_pipe[0] != -1)
3251 close (result_pipe[0]);
3252 if (result_pipe[1] != -1)
3253 close (result_pipe[1]);
3254 if (errors_pipe[0] != -1)
3255 close (errors_pipe[0]);
3256 if (errors_pipe[1] != -1)
3257 close (errors_pipe[1]);
3258
3259 return retval;
3260 }
3261
3262 /**
3263 * Returns the address of a new session bus.
3264 *
3265 * If successful, returns #TRUE and appends the address to @p
3266 * address. If a failure happens, returns #FALSE and
3267 * sets an error in @p error.
3268 *
3269 * @param address a DBusString where the address can be stored
3270 * @param error a DBusError to store the error in case of failure
3271 * @returns #TRUE on success, #FALSE if an error happened
3272 */
3273 dbus_bool_t
_dbus_get_autolaunch_address(DBusString * address,DBusError * error)3274 _dbus_get_autolaunch_address (DBusString *address,
3275 DBusError *error)
3276 {
3277 static char *argv[6];
3278 int i;
3279 DBusString uuid;
3280 dbus_bool_t retval;
3281
3282 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3283 retval = FALSE;
3284
3285 if (!_dbus_string_init (&uuid))
3286 {
3287 _DBUS_SET_OOM (error);
3288 return FALSE;
3289 }
3290
3291 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
3292 {
3293 _DBUS_SET_OOM (error);
3294 goto out;
3295 }
3296
3297 i = 0;
3298 argv[i] = "dbus-launch";
3299 ++i;
3300 argv[i] = "--autolaunch";
3301 ++i;
3302 argv[i] = _dbus_string_get_data (&uuid);
3303 ++i;
3304 argv[i] = "--binary-syntax";
3305 ++i;
3306 argv[i] = "--close-stderr";
3307 ++i;
3308 argv[i] = NULL;
3309 ++i;
3310
3311 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3312
3313 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
3314 TRUE,
3315 argv, address, error);
3316
3317 out:
3318 _dbus_string_free (&uuid);
3319 return retval;
3320 }
3321
3322 /**
3323 * Reads the uuid of the machine we're running on from
3324 * the dbus configuration. Optionally try to create it
3325 * (only root can do this usually).
3326 *
3327 * On UNIX, reads a file that gets created by dbus-uuidgen
3328 * in a post-install script. On Windows, if there's a standard
3329 * machine uuid we could just use that, but I can't find one
3330 * with the right properties (the hardware profile guid can change
3331 * without rebooting I believe). If there's no standard one
3332 * we might want to use the registry instead of a file for
3333 * this, and I'm not sure how we'd ensure the uuid gets created.
3334 *
3335 * @param machine_id guid to init with the machine's uuid
3336 * @param create_if_not_found try to create the uuid if it doesn't exist
3337 * @param error the error return
3338 * @returns #FALSE if the error is set
3339 */
3340 dbus_bool_t
_dbus_read_local_machine_uuid(DBusGUID * machine_id,dbus_bool_t create_if_not_found,DBusError * error)3341 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3342 dbus_bool_t create_if_not_found,
3343 DBusError *error)
3344 {
3345 DBusString filename;
3346 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3347 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
3348 }
3349
3350 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
3351 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
3352
3353 /**
3354 * Determines the address of the session bus by querying a
3355 * platform-specific method.
3356 *
3357 * The first parameter will be a boolean specifying whether
3358 * or not a dynamic session lookup is supported on this platform.
3359 *
3360 * If supported is TRUE and the return value is #TRUE, the
3361 * address will be appended to @p address.
3362 * If a failure happens, returns #FALSE and sets an error in
3363 * @p error.
3364 *
3365 * If supported is FALSE, ignore the return value.
3366 *
3367 * @param supported returns whether this method is supported
3368 * @param address a DBusString where the address can be stored
3369 * @param error a DBusError to store the error in case of failure
3370 * @returns #TRUE on success, #FALSE if an error happened
3371 */
3372 dbus_bool_t
_dbus_lookup_session_address(dbus_bool_t * supported,DBusString * address,DBusError * error)3373 _dbus_lookup_session_address (dbus_bool_t *supported,
3374 DBusString *address,
3375 DBusError *error)
3376 {
3377 /* On non-Mac Unix platforms, if the session address isn't already
3378 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
3379 * fall back to the autolaunch: global default; see
3380 * init_session_address in dbus/dbus-bus.c. */
3381 *supported = FALSE;
3382 return TRUE;
3383 }
3384
3385 /**
3386 * Returns the standard directories for a session bus to look for service
3387 * activation files
3388 *
3389 * On UNIX this should be the standard xdg freedesktop.org data directories:
3390 *
3391 * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share}
3392 * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
3393 *
3394 * and
3395 *
3396 * DBUS_DATADIR
3397 *
3398 * @param dirs the directory list we are returning
3399 * @returns #FALSE on OOM
3400 */
3401
3402 dbus_bool_t
_dbus_get_standard_session_servicedirs(DBusList ** dirs)3403 _dbus_get_standard_session_servicedirs (DBusList **dirs)
3404 {
3405 const char *xdg_data_home;
3406 const char *xdg_data_dirs;
3407 DBusString servicedir_path;
3408
3409 if (!_dbus_string_init (&servicedir_path))
3410 return FALSE;
3411
3412 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
3413 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
3414
3415 if (xdg_data_dirs != NULL)
3416 {
3417 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
3418 goto oom;
3419
3420 if (!_dbus_string_append (&servicedir_path, ":"))
3421 goto oom;
3422 }
3423 else
3424 {
3425 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
3426 goto oom;
3427 }
3428
3429 /*
3430 * add configured datadir to defaults
3431 * this may be the same as an xdg dir
3432 * however the config parser should take
3433 * care of duplicates
3434 */
3435 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
3436 goto oom;
3437
3438 if (xdg_data_home != NULL)
3439 {
3440 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
3441 goto oom;
3442 }
3443 else
3444 {
3445 const DBusString *homedir;
3446 DBusString local_share;
3447
3448 if (!_dbus_homedir_from_current_process (&homedir))
3449 goto oom;
3450
3451 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
3452 goto oom;
3453
3454 _dbus_string_init_const (&local_share, "/.local/share");
3455 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
3456 goto oom;
3457 }
3458
3459 if (!_dbus_split_paths_and_append (&servicedir_path,
3460 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
3461 dirs))
3462 goto oom;
3463
3464 _dbus_string_free (&servicedir_path);
3465 return TRUE;
3466
3467 oom:
3468 _dbus_string_free (&servicedir_path);
3469 return FALSE;
3470 }
3471
3472
3473 /**
3474 * Returns the standard directories for a system bus to look for service
3475 * activation files
3476 *
3477 * On UNIX this should be the standard xdg freedesktop.org data directories:
3478 *
3479 * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
3480 *
3481 * and
3482 *
3483 * DBUS_DATADIR
3484 *
3485 * On Windows there is no system bus and this function can return nothing.
3486 *
3487 * @param dirs the directory list we are returning
3488 * @returns #FALSE on OOM
3489 */
3490
3491 dbus_bool_t
_dbus_get_standard_system_servicedirs(DBusList ** dirs)3492 _dbus_get_standard_system_servicedirs (DBusList **dirs)
3493 {
3494 const char *xdg_data_dirs;
3495 DBusString servicedir_path;
3496
3497 if (!_dbus_string_init (&servicedir_path))
3498 return FALSE;
3499
3500 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
3501
3502 if (xdg_data_dirs != NULL)
3503 {
3504 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
3505 goto oom;
3506
3507 if (!_dbus_string_append (&servicedir_path, ":"))
3508 goto oom;
3509 }
3510 else
3511 {
3512 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
3513 goto oom;
3514 }
3515
3516 /*
3517 * add configured datadir to defaults
3518 * this may be the same as an xdg dir
3519 * however the config parser should take
3520 * care of duplicates
3521 */
3522 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
3523 goto oom;
3524
3525 if (!_dbus_split_paths_and_append (&servicedir_path,
3526 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
3527 dirs))
3528 goto oom;
3529
3530 _dbus_string_free (&servicedir_path);
3531 return TRUE;
3532
3533 oom:
3534 _dbus_string_free (&servicedir_path);
3535 return FALSE;
3536 }
3537
3538 /**
3539 * Append the absolute path of the system.conf file
3540 * (there is no system bus on Windows so this can just
3541 * return FALSE and print a warning or something)
3542 *
3543 * @param str the string to append to
3544 * @returns #FALSE if no memory
3545 */
3546 dbus_bool_t
_dbus_append_system_config_file(DBusString * str)3547 _dbus_append_system_config_file (DBusString *str)
3548 {
3549 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
3550 }
3551
3552 /**
3553 * Append the absolute path of the session.conf file.
3554 *
3555 * @param str the string to append to
3556 * @returns #FALSE if no memory
3557 */
3558 dbus_bool_t
_dbus_append_session_config_file(DBusString * str)3559 _dbus_append_session_config_file (DBusString *str)
3560 {
3561 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
3562 }
3563
3564 /**
3565 * Called when the bus daemon is signaled to reload its configuration; any
3566 * caches should be nuked. Of course any caches that need explicit reload
3567 * are probably broken, but c'est la vie.
3568 *
3569 *
3570 */
3571 void
_dbus_flush_caches(void)3572 _dbus_flush_caches (void)
3573 {
3574 _dbus_user_database_flush_system ();
3575 }
3576
3577 /**
3578 * Appends the directory in which a keyring for the given credentials
3579 * should be stored. The credentials should have either a Windows or
3580 * UNIX user in them. The directory should be an absolute path.
3581 *
3582 * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
3583 * be something else, since the dotfile convention is not normal on Windows.
3584 *
3585 * @param directory string to append directory to
3586 * @param credentials credentials the directory should be for
3587 *
3588 * @returns #FALSE on no memory
3589 */
3590 dbus_bool_t
_dbus_append_keyring_directory_for_credentials(DBusString * directory,DBusCredentials * credentials)3591 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
3592 DBusCredentials *credentials)
3593 {
3594 DBusString homedir;
3595 DBusString dotdir;
3596 dbus_uid_t uid;
3597
3598 _dbus_assert (credentials != NULL);
3599 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
3600
3601 if (!_dbus_string_init (&homedir))
3602 return FALSE;
3603
3604 uid = _dbus_credentials_get_unix_uid (credentials);
3605 _dbus_assert (uid != DBUS_UID_UNSET);
3606
3607 if (!_dbus_homedir_from_uid (uid, &homedir))
3608 goto failed;
3609
3610 #ifdef DBUS_BUILD_TESTS
3611 {
3612 const char *override;
3613
3614 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
3615 if (override != NULL && *override != '\0')
3616 {
3617 _dbus_string_set_length (&homedir, 0);
3618 if (!_dbus_string_append (&homedir, override))
3619 goto failed;
3620
3621 _dbus_verbose ("Using fake homedir for testing: %s\n",
3622 _dbus_string_get_const_data (&homedir));
3623 }
3624 else
3625 {
3626 static dbus_bool_t already_warned = FALSE;
3627 if (!already_warned)
3628 {
3629 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3630 already_warned = TRUE;
3631 }
3632 }
3633 }
3634 #endif
3635
3636 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
3637 if (!_dbus_concat_dir_and_file (&homedir,
3638 &dotdir))
3639 goto failed;
3640
3641 if (!_dbus_string_copy (&homedir, 0,
3642 directory, _dbus_string_get_length (directory))) {
3643 goto failed;
3644 }
3645
3646 _dbus_string_free (&homedir);
3647 return TRUE;
3648
3649 failed:
3650 _dbus_string_free (&homedir);
3651 return FALSE;
3652 }
3653
3654 //PENDING(kdab) docs
3655 void
_dbus_daemon_publish_session_bus_address(const char * addr)3656 _dbus_daemon_publish_session_bus_address (const char* addr)
3657 {
3658
3659 }
3660
3661 //PENDING(kdab) docs
3662 void
_dbus_daemon_unpublish_session_bus_address(void)3663 _dbus_daemon_unpublish_session_bus_address (void)
3664 {
3665
3666 }
3667
3668 /**
3669 * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
3670 * for Winsock so is abstracted)
3671 *
3672 * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
3673 */
3674 dbus_bool_t
_dbus_get_is_errno_eagain_or_ewouldblock(void)3675 _dbus_get_is_errno_eagain_or_ewouldblock (void)
3676 {
3677 return errno == EAGAIN || errno == EWOULDBLOCK;
3678 }
3679
3680 /**
3681 * Removes a directory; Directory must be empty
3682 *
3683 * @param filename directory filename
3684 * @param error initialized error object
3685 * @returns #TRUE on success
3686 */
3687 dbus_bool_t
_dbus_delete_directory(const DBusString * filename,DBusError * error)3688 _dbus_delete_directory (const DBusString *filename,
3689 DBusError *error)
3690 {
3691 const char *filename_c;
3692
3693 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3694
3695 filename_c = _dbus_string_get_const_data (filename);
3696
3697 if (rmdir (filename_c) != 0)
3698 {
3699 dbus_set_error (error, DBUS_ERROR_FAILED,
3700 "Failed to remove directory %s: %s\n",
3701 filename_c, _dbus_strerror (errno));
3702 return FALSE;
3703 }
3704
3705 return TRUE;
3706 }
3707
3708 /**
3709 * Checks whether file descriptors may be passed via the socket
3710 *
3711 * @param fd the socket
3712 * @return TRUE when fd passing over this socket is supported
3713 *
3714 */
3715 dbus_bool_t
_dbus_socket_can_pass_unix_fd(int fd)3716 _dbus_socket_can_pass_unix_fd(int fd) {
3717
3718 #ifdef SCM_RIGHTS
3719 union {
3720 struct sockaddr sa;
3721 struct sockaddr_storage storage;
3722 struct sockaddr_un un;
3723 } sa_buf;
3724
3725 socklen_t sa_len = sizeof(sa_buf);
3726
3727 _DBUS_ZERO(sa_buf);
3728
3729 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
3730 return FALSE;
3731
3732 return sa_buf.sa.sa_family == AF_UNIX;
3733
3734 #else
3735 return FALSE;
3736
3737 #endif
3738 }
3739
3740
3741 /*
3742 * replaces the term DBUS_PREFIX in configure_time_path by the
3743 * current dbus installation directory. On unix this function is a noop
3744 *
3745 * @param configure_time_path
3746 * @return real path
3747 */
3748 const char *
_dbus_replace_install_prefix(const char * configure_time_path)3749 _dbus_replace_install_prefix (const char *configure_time_path)
3750 {
3751 return configure_time_path;
3752 }
3753
3754 /* tests in dbus-sysdeps-util.c */
3755