D-Bus: dbus-sysdeps-unix.c Source File

D-Bus 1.12.18

dbus-sysdeps-unix.c
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-file.h"
33 #include "dbus-transport.h"
34 #include "dbus-string.h"
35 #include "dbus-userdb.h"
36 #include "dbus-list.h"
37 #include "dbus-credentials.h"
38 #include "dbus-nonce.h"
39
40 #include <sys/types.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <fcntl.h>
47 #include <sys/socket.h>
48 #include <dirent.h>
49 #include <sys/un.h>
50 #include <pwd.h>
51 #include <time.h>
52 #include <locale.h>
53 #include <sys/time.h>
54 #include <sys/stat.h>
55 #include <sys/wait.h>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <netdb.h>
59 #include <grp.h>
60 #include <arpa/inet.h>
61
62 #ifdef HAVE_ERRNO_H
63 #include <errno.h>
64 #endif
65 #ifdef HAVE_SYSLOG_H
66 #include <syslog.h>
67 #endif
68 #ifdef HAVE_WRITEV
69 #include <sys/uio.h>
70 #endif
71 #ifdef HAVE_POLL
72 #include <sys/poll.h>
73 #endif
74 #ifdef HAVE_BACKTRACE
75 #include <execinfo.h>
76 #endif
77 #ifdef HAVE_GETPEERUCRED
78 #include <ucred.h>
79 #endif
80 #ifdef HAVE_ALLOCA_H
81 #include <alloca.h>
82 #endif
83
84 #ifdef HAVE_ADT
85 #include <bsm/adt.h>
86 #endif
87
88 #ifdef HAVE_SYSTEMD
89 #include <systemd/sd-daemon.h>
90 #endif
91
92 #if !DBUS_USE_SYNC
93 #include <pthread.h>
94 #endif
95
96 #ifndef O_BINARY
97 #define O_BINARY 0
98 #endif
99
100 #ifndef AI_ADDRCONFIG
101 #define AI_ADDRCONFIG 0
102 #endif
103
104 #ifndef HAVE_SOCKLEN_T
105 #define socklen_t int
106 #endif
107
108 #if defined (__sun) || defined (__sun__)
109 /*
110 * CMS_SPACE etc. definitions for Solaris < 10, based on
111 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
112 * via
113 * http://wiki.opencsw.org/porting-faq#toc10
114 *
115 * These are only redefined for Solaris, for now: if your OS needs these too,
116 * please file a bug. (Or preferably, improve your OS so they're not needed.)
117 */
118
119 # ifndef CMSG_ALIGN
120 # ifdef __sun__
121 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
122 # else
123 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
124 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
125 ~(sizeof (long) - 1))
126 # endif
127 # endif
128
129 # ifndef CMSG_SPACE
130 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
131 CMSG_ALIGN (len))
132 # endif
133
134 # ifndef CMSG_LEN
135 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
136 # endif
137
138 #endif /* Solaris */
139
154 dbus_bool_t
155 _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
156 const char **error_str_p)
157 {
158 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
159 DBUS_FORCE_STDOUT_NULL,
160 DBUS_FORCE_STDERR_NULL };
161 /* Should always get replaced with the real error before use */
162 const char *error_str = "Failed mysteriously";
163 int devnull = -1;
164 int saved_errno;
165 /* This function relies on the standard fds having their POSIX values. */
166 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
167 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
168 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
169 int i;
170
171 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
172 {
173 /* Because we rely on being single-threaded, and we want the
174 * standard fds to not be close-on-exec, we don't set it
175 * close-on-exec. */
176 if (devnull < i)
177 devnull = open ("/dev/null", O_RDWR);
178
179 if (devnull < 0)
180 {
181 error_str = "Failed to open /dev/null";
182 goto out;
183 }
184
185 /* We already opened all fds < i, so the only way this assertion
186 * could fail is if another thread closed one, and we document
187 * this function as not safe for multi-threading. */
188 _dbus_assert (devnull >= i);
189
190 if (devnull != i && (flags & relevant_flag[i]) != 0)
191 {
192 if (dup2 (devnull, i) < 0)
193 {
194 error_str = "Failed to dup2 /dev/null onto a standard fd";
195 goto out;
196 }
197 }
198 }
199
200 error_str = NULL;
201
202 out:
203 saved_errno = errno;
204
205 if (devnull > STDERR_FILENO)
206 close (devnull);
207
208 if (error_str_p != NULL)
209 *error_str_p = error_str;
210
211 errno = saved_errno;
212 return (error_str == NULL);
213 }
214
215 static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
216 DBusError *error);
217
218 static dbus_bool_t
219 _dbus_open_socket (int *fd_p,
220 int domain,
221 int type,
222 int protocol,
223 DBusError *error)
224 {
225 #ifdef SOCK_CLOEXEC
226 dbus_bool_t cloexec_done;
227
228 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
229 cloexec_done = *fd_p >= 0;
230
231 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
232 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
233 #endif
234 {
235 *fd_p = socket (domain, type, protocol);
236 }
237
238 if (*fd_p >= 0)
239 {
240 #ifdef SOCK_CLOEXEC
241 if (!cloexec_done)
242 #endif
243 {
244 _dbus_fd_set_close_on_exec(*fd_p);
245 }
246
247 _dbus_verbose ("socket fd %d opened\n", *fd_p);
248 return TRUE;
249 }
250 else
251 {
252 dbus_set_error(error,
253 _dbus_error_from_errno (errno),
254 "Failed to open socket: %s",
255 _dbus_strerror (errno));
256 return FALSE;
257 }
258 }
259
270 static dbus_bool_t
271 _dbus_open_unix_socket (int *fd,
272 DBusError *error)
273 {
274 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
275 }
276
285 dbus_bool_t
286 _dbus_close_socket (DBusSocket fd,
287 DBusError *error)
288 {
289 return _dbus_close (fd.fd, error);
290 }
291
301 int
302 _dbus_read_socket (DBusSocket fd,
303 DBusString *buffer,
304 int count)
305 {
306 return _dbus_read (fd.fd, buffer, count);
307 }
308
319 int
320 _dbus_write_socket (DBusSocket fd,
321 const DBusString *buffer,
322 int start,
323 int len)
324 {
325 #if HAVE_DECL_MSG_NOSIGNAL
326 const char *data;
327 int bytes_written;
328
329 data = _dbus_string_get_const_data_len (buffer, start, len);
330
331 again:
332
333 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
334
335 if (bytes_written < 0 && errno == EINTR)
336 goto again;
337
338 return bytes_written;
339
340 #else
341 return _dbus_write (fd.fd, buffer, start, len);
342 #endif
343 }
344
357 int
358 _dbus_read_socket_with_unix_fds (DBusSocket fd,
359 DBusString *buffer,
360 int count,
361 int *fds,
362 unsigned int *n_fds) {
363 #ifndef HAVE_UNIX_FD_PASSING
364 int r;
365
366 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
367 return r;
368
369 *n_fds = 0;
370 return r;
371
372 #else
373 int bytes_read;
374 int start;
375 struct msghdr m;
376 struct iovec iov;
377
378 _dbus_assert (count >= 0);
379 _dbus_assert (*n_fds <= DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
380
381 start = _dbus_string_get_length (buffer);
382
383 if (!_dbus_string_lengthen (buffer, count))
384 {
385 errno = ENOMEM;
386 return -1;
387 }
388
389 _DBUS_ZERO(iov);
390 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
391 iov.iov_len = count;
392
393 _DBUS_ZERO(m);
394 m.msg_iov = &iov;
395 m.msg_iovlen = 1;
396
397 /* Hmm, we have no clue how long the control data will actually be
398 that is queued for us. The least we can do is assume that the
399 caller knows. Hence let's make space for the number of fds that
400 we shall read at max plus the cmsg header. */
401 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
402
403 /* It's probably safe to assume that systems with SCM_RIGHTS also
404 know alloca() */
405 m.msg_control = alloca(m.msg_controllen);
406 memset(m.msg_control, 0, m.msg_controllen);
407
408 /* Do not include the padding at the end when we tell the kernel
409 * how much we're willing to receive. This avoids getting
410 * the padding filled with additional fds that we weren't expecting,
411 * if a (potentially malicious) sender included them. (fd.o #83622) */
412 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
413
414 again:
415
416 bytes_read = recvmsg (fd.fd, &m, 0
417 #ifdef MSG_CMSG_CLOEXEC
418 |MSG_CMSG_CLOEXEC
419 #endif
420 );
421
422 if (bytes_read < 0)
423 {
424 if (errno == EINTR)
425 goto again;
426 else
427 {
428 /* put length back (note that this doesn't actually realloc anything) */
429 _dbus_string_set_length (buffer, start);
430 return -1;
431 }
432 }
433 else
434 {
435 struct cmsghdr *cm;
436 dbus_bool_t found = FALSE;
437
438 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
439 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
440 {
441 size_t i;
442 int *payload = (int *) CMSG_DATA (cm);
443 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
444 size_t payload_len_fds = payload_len_bytes / sizeof (int);
445 size_t fds_to_use;
446
447 /* Every unsigned int fits in a size_t without truncation, so
448 * casting (size_t) *n_fds is OK */
449 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
450
451 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
452 {
453 /* The fds in the payload will fit in our buffer */
454 fds_to_use = payload_len_fds;
455 }
456 else
457 {
458 /* Too many fds in the payload. This shouldn't happen
459 * any more because we're setting m.msg_controllen to
460 * the exact number we can accept, but be safe and
461 * truncate. */
462 fds_to_use = (size_t) *n_fds;
463
464 /* Close the excess fds to avoid DoS: if they stayed open,
465 * someone could send us an extra fd per message
466 * and we'd eventually run out. */
467 for (i = fds_to_use; i < payload_len_fds; i++)
468 {
469 close (payload[i]);
470 }
471 }
472
473 memcpy (fds, payload, fds_to_use * sizeof (int));
474 found = TRUE;
475 /* This narrowing cast from size_t to unsigned int cannot
476 * overflow because we have chosen fds_to_use
477 * to be <= *n_fds */
478 *n_fds = (unsigned int) fds_to_use;
479
480 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
481 worked, hence we need to go through this list and set
482 CLOEXEC everywhere in any case */
483 for (i = 0; i < fds_to_use; i++)
484 _dbus_fd_set_close_on_exec(fds[i]);
485
486 break;
487 }
488
489 if (!found)
490 *n_fds = 0;
491
492 if (m.msg_flags & MSG_CTRUNC)
493 {
494 unsigned int i;
495
496 /* Hmm, apparently the control data was truncated. The bad
497 thing is that we might have completely lost a couple of fds
498 without chance to recover them. Hence let's treat this as a
499 serious error. */
500
501 /* We still need to close whatever fds we *did* receive,
502 * otherwise they'll never get closed. (CVE-2020-12049) */
503 for (i = 0; i < *n_fds; i++)
504 close (fds[i]);
505
506 *n_fds = 0;
507 errno = ENOSPC;
508 _dbus_string_set_length (buffer, start);
509 return -1;
510 }
511
512 /* put length back (doesn't actually realloc) */
513 _dbus_string_set_length (buffer, start + bytes_read);
514
515 #if 0
516 if (bytes_read > 0)
517 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
518 #endif
519
520 return bytes_read;
521 }
522 #endif
523 }
524
525 int
526 _dbus_write_socket_with_unix_fds(DBusSocket fd,
527 const DBusString *buffer,
528 int start,
529 int len,
530 const int *fds,
531 int n_fds) {
532
533 #ifndef HAVE_UNIX_FD_PASSING
534
535 if (n_fds > 0) {
536 errno = ENOTSUP;
537 return -1;
538 }
539
540 return _dbus_write_socket(fd, buffer, start, len);
541 #else
542 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
543 #endif
544 }
545
546 int
547 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
548 const DBusString *buffer1,
549 int start1,
550 int len1,
551 const DBusString *buffer2,
552 int start2,
553 int len2,
554 const int *fds,
555 int n_fds) {
556
557 #ifndef HAVE_UNIX_FD_PASSING
558
559 if (n_fds > 0) {
560 errno = ENOTSUP;
561 return -1;
562 }
563
564 return _dbus_write_socket_two(fd,
565 buffer1, start1, len1,
566 buffer2, start2, len2);
567 #else
568
569 struct msghdr m;
570 struct cmsghdr *cm;
571 struct iovec iov[2];
572 int bytes_written;
573
574 _dbus_assert (len1 >= 0);
575 _dbus_assert (len2 >= 0);
576 _dbus_assert (n_fds >= 0);
577
578 _DBUS_ZERO(iov);
579 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
580 iov[0].iov_len = len1;
581
582 if (buffer2)
583 {
584 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
585 iov[1].iov_len = len2;
586 }
587
588 _DBUS_ZERO(m);
589 m.msg_iov = iov;
590 m.msg_iovlen = buffer2 ? 2 : 1;
591
592 if (n_fds > 0)
593 {
594 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
595 m.msg_control = alloca(m.msg_controllen);
596 memset(m.msg_control, 0, m.msg_controllen);
597
598 cm = CMSG_FIRSTHDR(&m);
599 cm->cmsg_level = SOL_SOCKET;
600 cm->cmsg_type = SCM_RIGHTS;
601 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
602 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
603 }
604
605 again:
606
607 bytes_written = sendmsg (fd.fd, &m, 0
608 #if HAVE_DECL_MSG_NOSIGNAL
609 |MSG_NOSIGNAL
610 #endif
611 );
612
613 if (bytes_written < 0 && errno == EINTR)
614 goto again;
615
616 #if 0
617 if (bytes_written > 0)
618 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
619 #endif
620
621 return bytes_written;
622 #endif
623 }
624
638 int
639 _dbus_write_socket_two (DBusSocket fd,
640 const DBusString *buffer1,
641 int start1,
642 int len1,
643 const DBusString *buffer2,
644 int start2,
645 int len2)
646 {
647 #if HAVE_DECL_MSG_NOSIGNAL
648 struct iovec vectors[2];
649 const char *data1;
650 const char *data2;
651 int bytes_written;
652 struct msghdr m;
653
654 _dbus_assert (buffer1 != NULL);
655 _dbus_assert (start1 >= 0);
656 _dbus_assert (start2 >= 0);
657 _dbus_assert (len1 >= 0);
658 _dbus_assert (len2 >= 0);
659
660 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
661
662 if (buffer2 != NULL)
663 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
664 else
665 {
666 data2 = NULL;
667 start2 = 0;
668 len2 = 0;
669 }
670
671 vectors[0].iov_base = (char*) data1;
672 vectors[0].iov_len = len1;
673 vectors[1].iov_base = (char*) data2;
674 vectors[1].iov_len = len2;
675
676 _DBUS_ZERO(m);
677 m.msg_iov = vectors;
678 m.msg_iovlen = data2 ? 2 : 1;
679
680 again:
681
682 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
683
684 if (bytes_written < 0 && errno == EINTR)
685 goto again;
686
687 return bytes_written;
688
689 #else
690 return _dbus_write_two (fd.fd, buffer1, start1, len1,
691 buffer2, start2, len2);
692 #endif
693 }
694
711 int
712 _dbus_read (int fd,
713 DBusString *buffer,
714 int count)
715 {
716 int bytes_read;
717 int start;
718 char *data;
719
720 _dbus_assert (count >= 0);
721
722 start = _dbus_string_get_length (buffer);
723
724 if (!_dbus_string_lengthen (buffer, count))
725 {
726 errno = ENOMEM;
727 return -1;
728 }
729
730 data = _dbus_string_get_data_len (buffer, start, count);
731
732 again:
733
734 bytes_read = read (fd, data, count);
735
736 if (bytes_read < 0)
737 {
738 if (errno == EINTR)
739 goto again;
740 else
741 {
742 /* put length back (note that this doesn't actually realloc anything) */
743 _dbus_string_set_length (buffer, start);
744 return -1;
745 }
746 }
747 else
748 {
749 /* put length back (doesn't actually realloc) */
750 _dbus_string_set_length (buffer, start + bytes_read);
751
752 #if 0
753 if (bytes_read > 0)
754 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
755 #endif
756
757 return bytes_read;
758 }
759 }
760
771 int
772 _dbus_write (int fd,
773 const DBusString *buffer,
774 int start,
775 int len)
776 {
777 const char *data;
778 int bytes_written;
779
780 data = _dbus_string_get_const_data_len (buffer, start, len);
781
782 again:
783
784 bytes_written = write (fd, data, len);
785
786 if (bytes_written < 0 && errno == EINTR)
787 goto again;
788
789 #if 0
790 if (bytes_written > 0)
791 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
792 #endif
793
794 return bytes_written;
795 }
796
817 int
818 _dbus_write_two (int fd,
819 const DBusString *buffer1,
820 int start1,
821 int len1,
822 const DBusString *buffer2,
823 int start2,
824 int len2)
825 {
826 _dbus_assert (buffer1 != NULL);
827 _dbus_assert (start1 >= 0);
828 _dbus_assert (start2 >= 0);
829 _dbus_assert (len1 >= 0);
830 _dbus_assert (len2 >= 0);
831
832 #ifdef HAVE_WRITEV
833 {
834 struct iovec vectors[2];
835 const char *data1;
836 const char *data2;
837 int bytes_written;
838
839 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
840
841 if (buffer2 != NULL)
842 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
843 else
844 {
845 data2 = NULL;
846 start2 = 0;
847 len2 = 0;
848 }
849
850 vectors[0].iov_base = (char*) data1;
851 vectors[0].iov_len = len1;
852 vectors[1].iov_base = (char*) data2;
853 vectors[1].iov_len = len2;
854
855 again:
856
857 bytes_written = writev (fd,
858 vectors,
859 data2 ? 2 : 1);
860
861 if (bytes_written < 0 && errno == EINTR)
862 goto again;
863
864 return bytes_written;
865 }
866 #else /* HAVE_WRITEV */
867 {
868 int ret1, ret2;
869
870 ret1 = _dbus_write (fd, buffer1, start1, len1);
871 if (ret1 == len1 && buffer2 != NULL)
872 {
873 ret2 = _dbus_write (fd, buffer2, start2, len2);
874 if (ret2 < 0)
875 ret2 = 0; /* we can't report an error as the first write was OK */
876
877 return ret1 + ret2;
878 }
879 else
880 return ret1;
881 }
882 #endif /* !HAVE_WRITEV */
883 }
884
885 #define _DBUS_MAX_SUN_PATH_LENGTH 99
886
916 int
917 _dbus_connect_unix_socket (const char *path,
918 dbus_bool_t abstract,
919 DBusError *error)
920 {
921 int fd;
922 size_t path_len;
923 struct sockaddr_un addr;
924 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
925
926 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
927
928 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
929 path, abstract);
930
931
932 if (!_dbus_open_unix_socket (&fd, error))
933 {
934 _DBUS_ASSERT_ERROR_IS_SET(error);
935 return -1;
936 }
937 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
938
939 _DBUS_ZERO (addr);
940 addr.sun_family = AF_UNIX;
941 path_len = strlen (path);
942
943 if (abstract)
944 {
945 #ifdef __linux__
946 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
947 path_len++; /* Account for the extra nul byte added to the start of sun_path */
948
949 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
950 {
951 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
952 "Abstract socket name too long\n");
953 _dbus_close (fd, NULL);
954 return -1;
955 }
956
957 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
958 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
959 #else /* !__linux__ */
960 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
961 "Operating system does not support abstract socket namespace\n");
962 _dbus_close (fd, NULL);
963 return -1;
964 #endif /* !__linux__ */
965 }
966 else
967 {
968 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
969 {
970 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
971 "Socket name too long\n");
972 _dbus_close (fd, NULL);
973 return -1;
974 }
975
976 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
977 }
978
979 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
980 {
981 dbus_set_error (error,
982 _dbus_error_from_errno (errno),
983 "Failed to connect to socket %s: %s",
984 path, _dbus_strerror (errno));
985
986 _dbus_close (fd, NULL);
987 return -1;
988 }
989
990 if (!_dbus_set_fd_nonblocking (fd, error))
991 {
992 _DBUS_ASSERT_ERROR_IS_SET (error);
993
994 _dbus_close (fd, NULL);
995 return -1;
996 }
997
998 return fd;
999 }
1000
1013 int
1014 _dbus_connect_exec (const char *path,
1015 char *const argv[],
1016 DBusError *error)
1017 {
1018 int fds[2];
1019 pid_t pid;
1020 int retval;
1021 dbus_bool_t cloexec_done = 0;
1022
1023 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1024
1025 _dbus_verbose ("connecting to process %s\n", path);
1026
1027 #ifdef SOCK_CLOEXEC
1028 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1029 cloexec_done = (retval >= 0);
1030
1031 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1032 #endif
1033 {
1034 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1035 }
1036
1037 if (retval < 0)
1038 {
1039 dbus_set_error (error,
1040 _dbus_error_from_errno (errno),
1041 "Failed to create socket pair: %s",
1042 _dbus_strerror (errno));
1043 return -1;
1044 }
1045
1046 if (!cloexec_done)
1047 {
1048 _dbus_fd_set_close_on_exec (fds[0]);
1049 _dbus_fd_set_close_on_exec (fds[1]);
1050 }
1051
1052 pid = fork ();
1053 if (pid < 0)
1054 {
1055 dbus_set_error (error,
1056 _dbus_error_from_errno (errno),
1057 "Failed to fork() to call %s: %s",
1058 path, _dbus_strerror (errno));
1059 close (fds[0]);
1060 close (fds[1]);
1061 return -1;
1062 }
1063
1064 if (pid == 0)
1065 {
1066 /* child */
1067 close (fds[0]);
1068
1069 dup2 (fds[1], STDIN_FILENO);
1070 dup2 (fds[1], STDOUT_FILENO);
1071
1072 if (fds[1] != STDIN_FILENO &&
1073 fds[1] != STDOUT_FILENO)
1074 close (fds[1]);
1075
1076 /* Inherit STDERR and the controlling terminal from the
1077 parent */
1078
1079 _dbus_close_all ();
1080
1081 execvp (path, (char * const *) argv);
1082
1083 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1084
1085 _exit(1);
1086 }
1087
1088 /* parent */
1089 close (fds[1]);
1090
1091 if (!_dbus_set_fd_nonblocking (fds[0], error))
1092 {
1093 _DBUS_ASSERT_ERROR_IS_SET (error);
1094
1095 close (fds[0]);
1096 return -1;
1097 }
1098
1099 return fds[0];
1100 }
1101
1119 int
1120 _dbus_listen_unix_socket (const char *path,
1121 dbus_bool_t abstract,
1122 DBusError *error)
1123 {
1124 int listen_fd;
1125 struct sockaddr_un addr;
1126 size_t path_len;
1127 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1128
1129 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1130
1131 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1132 path, abstract);
1133
1134 if (!_dbus_open_unix_socket (&listen_fd, error))
1135 {
1136 _DBUS_ASSERT_ERROR_IS_SET(error);
1137 return -1;
1138 }
1139 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1140
1141 _DBUS_ZERO (addr);
1142 addr.sun_family = AF_UNIX;
1143 path_len = strlen (path);
1144
1145 if (abstract)
1146 {
1147 #ifdef __linux__
1148 /* remember that abstract names aren't nul-terminated so we rely
1149 * on sun_path being filled in with zeroes above.
1150 */
1151 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1152 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1153
1154 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1155 {
1156 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1157 "Abstract socket name too long\n");
1158 _dbus_close (listen_fd, NULL);
1159 return -1;
1160 }
1161
1162 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1163 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1164 #else /* !__linux__ */
1165 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1166 "Operating system does not support abstract socket namespace\n");
1167 _dbus_close (listen_fd, NULL);
1168 return -1;
1169 #endif /* !__linux__ */
1170 }
1171 else
1172 {
1173 /* Discussed security implications of this with Nalin,
1174 * and we couldn't think of where it would kick our ass, but
1175 * it still seems a bit sucky. It also has non-security suckage;
1176 * really we'd prefer to exit if the socket is already in use.
1177 * But there doesn't seem to be a good way to do this.
1178 *
1179 * Just to be extra careful, I threw in the stat() - clearly
1180 * the stat() can't *fix* any security issue, but it at least
1181 * avoids inadvertent/accidental data loss.
1182 */
1183 {
1184 struct stat sb;
1185
1186 if (stat (path, &sb) == 0 &&
1187 S_ISSOCK (sb.st_mode))
1188 unlink (path);
1189 }
1190
1191 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1192 {
1193 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1194 "Socket name too long\n");
1195 _dbus_close (listen_fd, NULL);
1196 return -1;
1197 }
1198
1199 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1200 }
1201
1202 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1203 {
1204 dbus_set_error (error, _dbus_error_from_errno (errno),
1205 "Failed to bind socket \"%s\": %s",
1206 path, _dbus_strerror (errno));
1207 _dbus_close (listen_fd, NULL);
1208 return -1;
1209 }
1210
1211 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1212 {
1213 dbus_set_error (error, _dbus_error_from_errno (errno),
1214 "Failed to listen on socket \"%s\": %s",
1215 path, _dbus_strerror (errno));
1216 _dbus_close (listen_fd, NULL);
1217 return -1;
1218 }
1219
1220 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1221 {
1222 _DBUS_ASSERT_ERROR_IS_SET (error);
1223 _dbus_close (listen_fd, NULL);
1224 return -1;
1225 }
1226
1227 /* Try opening up the permissions, but if we can't, just go ahead
1228 * and continue, maybe it will be good enough.
1229 */
1230 if (!abstract && chmod (path, 0777) < 0)
1231 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1232
1233 return listen_fd;
1234 }
1235
1246 int
1247 _dbus_listen_systemd_sockets (DBusSocket **fds,
1248 DBusError *error)
1249 {
1250 #ifdef HAVE_SYSTEMD
1251 int r, n;
1252 int fd;
1253 DBusSocket *new_fds;
1254
1255 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1256
1257 n = sd_listen_fds (TRUE);
1258 if (n < 0)
1259 {
1260 dbus_set_error (error, _dbus_error_from_errno (-n),
1261 "Failed to acquire systemd socket: %s",
1262 _dbus_strerror (-n));
1263 return -1;
1264 }
1265
1266 if (n <= 0)
1267 {
1268 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1269 "No socket received.");
1270 return -1;
1271 }
1272
1273 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1274 {
1275 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1276 if (r < 0)
1277 {
1278 dbus_set_error (error, _dbus_error_from_errno (-r),
1279 "Failed to verify systemd socket type: %s",
1280 _dbus_strerror (-r));
1281 return -1;
1282 }
1283
1284 if (!r)
1285 {
1286 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1287 "Passed socket has wrong type.");
1288 return -1;
1289 }
1290 }
1291
1292 /* OK, the file descriptors are all good, so let's take posession of
1293 them then. */
1294
1295 new_fds = dbus_new (DBusSocket, n);
1296 if (!new_fds)
1297 {
1298 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1299 "Failed to allocate file handle array.");
1300 goto fail;
1301 }
1302
1303 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1304 {
1305 if (!_dbus_set_fd_nonblocking (fd, error))
1306 {
1307 _DBUS_ASSERT_ERROR_IS_SET (error);
1308 goto fail;
1309 }
1310
1311 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1312 }
1313
1314 *fds = new_fds;
1315 return n;
1316
1317 fail:
1318
1319 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1320 {
1321 _dbus_close (fd, NULL);
1322 }
1323
1324 dbus_free (new_fds);
1325 return -1;
1326 #else
1327 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
1328 "dbus was compiled without systemd support");
1329 return -1;
1330 #endif
1331 }
1332
1333 /* Convert an error code from getaddrinfo() or getnameinfo() into
1334 * a D-Bus error name. */
1335 static const char *
1336 _dbus_error_from_gai (int gai_res,
1337 int saved_errno)
1338 {
1339 switch (gai_res)
1340 {
1341 #ifdef EAI_FAMILY
1342 case EAI_FAMILY:
1343 /* ai_family not supported (at all) */
1344 return DBUS_ERROR_NOT_SUPPORTED;
1345 #endif
1346
1347 #ifdef EAI_SOCKTYPE
1348 case EAI_SOCKTYPE:
1349 /* ai_socktype not supported (at all) */
1350 return DBUS_ERROR_NOT_SUPPORTED;
1351 #endif
1352
1353 #ifdef EAI_MEMORY
1354 case EAI_MEMORY:
1355 /* Out of memory */
1356 return DBUS_ERROR_NO_MEMORY;
1357 #endif
1358
1359 #ifdef EAI_SYSTEM
1360 case EAI_SYSTEM:
1361 /* Unspecified system error, details in errno */
1362 return _dbus_error_from_errno (saved_errno);
1363 #endif
1364
1365 case 0:
1366 /* It succeeded, but we didn't get any addresses? */
1367 return DBUS_ERROR_FAILED;
1368
1369 /* EAI_AGAIN: Transient failure */
1370 /* EAI_BADFLAGS: invalid ai_flags (programming error) */
1371 /* EAI_FAIL: Non-recoverable failure */
1372 /* EAI_NODATA: host exists but has no addresses */
1373 /* EAI_NONAME: host does not exist */
1374 /* EAI_OVERFLOW: argument buffer overflow */
1375 /* EAI_SERVICE: service not available for specified socket
1376 * type (we should never see this because we use numeric
1377 * ports) */
1378 default:
1379 return DBUS_ERROR_FAILED;
1380 }
1381 }
1382
1396 DBusSocket
1397 _dbus_connect_tcp_socket (const char *host,
1398 const char *port,
1399 const char *family,
1400 DBusError *error)
1401 {
1402 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1403 }
1404
1405 DBusSocket
1406 _dbus_connect_tcp_socket_with_nonce (const char *host,
1407 const char *port,
1408 const char *family,
1409 const char *noncefile,
1410 DBusError *error)
1411 {
1412 int saved_errno = 0;
1413 DBusSocket fd = DBUS_SOCKET_INIT;
1414 int res;
1415 struct addrinfo hints;
1416 struct addrinfo *ai, *tmp;
1417
1418 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1419
1420 _DBUS_ZERO (hints);
1421
1422 if (!family)
1423 hints.ai_family = AF_UNSPEC;
1424 else if (!strcmp(family, "ipv4"))
1425 hints.ai_family = AF_INET;
1426 else if (!strcmp(family, "ipv6"))
1427 hints.ai_family = AF_INET6;
1428 else
1429 {
1430 dbus_set_error (error,
1431 DBUS_ERROR_BAD_ADDRESS,
1432 "Unknown address family %s", family);
1433 return _dbus_socket_get_invalid ();
1434 }
1435 hints.ai_protocol = IPPROTO_TCP;
1436 hints.ai_socktype = SOCK_STREAM;
1437 hints.ai_flags = AI_ADDRCONFIG;
1438
1439 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1440 {
1441 dbus_set_error (error,
1442 _dbus_error_from_gai (res, errno),
1443 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1444 host, port, gai_strerror(res), res);
1445 return _dbus_socket_get_invalid ();
1446 }
1447
1448 tmp = ai;
1449 while (tmp)
1450 {
1451 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1452 {
1453 freeaddrinfo(ai);
1454 _DBUS_ASSERT_ERROR_IS_SET(error);
1455 return _dbus_socket_get_invalid ();
1456 }
1457 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1458
1459 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1460 {
1461 saved_errno = errno;
1462 _dbus_close (fd.fd, NULL);
1463 fd.fd = -1;
1464 tmp = tmp->ai_next;
1465 continue;
1466 }
1467
1468 break;
1469 }
1470 freeaddrinfo(ai);
1471
1472 if (fd.fd == -1)
1473 {
1474 dbus_set_error (error,
1475 _dbus_error_from_errno (saved_errno),
1476 "Failed to connect to socket \"%s:%s\" %s",
1477 host, port, _dbus_strerror(saved_errno));
1478 return _dbus_socket_get_invalid ();
1479 }
1480
1481 if (noncefile != NULL)
1482 {
1483 DBusString noncefileStr;
1484 dbus_bool_t ret;
1485 _dbus_string_init_const (&noncefileStr, noncefile);
1486 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1487 _dbus_string_free (&noncefileStr);
1488
1489 if (!ret)
1490 {
1491 _dbus_close (fd.fd, NULL);
1492 return _dbus_socket_get_invalid ();
1493 }
1494 }
1495
1496 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1497 {
1498 _dbus_close (fd.fd, NULL);
1499 return _dbus_socket_get_invalid ();
1500 }
1501
1502 return fd;
1503 }
1504
1521 int
1522 _dbus_listen_tcp_socket (const char *host,
1523 const char *port,
1524 const char *family,
1525 DBusString *retport,
1526 DBusSocket **fds_p,
1527 DBusError *error)
1528 {
1529 int saved_errno;
1530 int nlisten_fd = 0, res, i;
1531 DBusSocket *listen_fd = NULL;
1532 struct addrinfo hints;
1533 struct addrinfo *ai, *tmp;
1534 unsigned int reuseaddr;
1535
1536 *fds_p = NULL;
1537 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1538
1539 _DBUS_ZERO (hints);
1540
1541 if (!family)
1542 hints.ai_family = AF_UNSPEC;
1543 else if (!strcmp(family, "ipv4"))
1544 hints.ai_family = AF_INET;
1545 else if (!strcmp(family, "ipv6"))
1546 hints.ai_family = AF_INET6;
1547 else
1548 {
1549 dbus_set_error (error,
1550 DBUS_ERROR_BAD_ADDRESS,
1551 "Unknown address family %s", family);
1552 return -1;
1553 }
1554
1555 hints.ai_protocol = IPPROTO_TCP;
1556 hints.ai_socktype = SOCK_STREAM;
1557 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1558
1559 redo_lookup_with_port:
1560 ai = NULL;
1561 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1562 {
1563 dbus_set_error (error,
1564 _dbus_error_from_gai (res, errno),
1565 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1566 host ? host : "*", port, gai_strerror(res), res);
1567 goto failed;
1568 }
1569
1570 tmp = ai;
1571 while (tmp)
1572 {
1573 int fd = -1, tcp_nodelay_on;
1574 DBusSocket *newlisten_fd;
1575
1576 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1577 {
1578 _DBUS_ASSERT_ERROR_IS_SET(error);
1579 goto failed;
1580 }
1581 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1582
1583 reuseaddr = 1;
1584 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1585 {
1586 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1587 host ? host : "*", port, _dbus_strerror (errno));
1588 }
1589
1590 /* Nagle's algorithm imposes a huge delay on the initial messages
1591 going over TCP. */
1592 tcp_nodelay_on = 1;
1593 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1594 {
1595 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1596 host ? host : "*", port, _dbus_strerror (errno));
1597 }
1598
1599 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1600 {
1601 saved_errno = errno;
1602 _dbus_close(fd, NULL);
1603 if (saved_errno == EADDRINUSE)
1604 {
1605 /* Depending on kernel policy, binding to an IPv6 address
1606 might implicitly bind to a corresponding IPv4
1607 address or vice versa, resulting in EADDRINUSE for the
1608 other one (e.g. bindv6only=0 on Linux).
1609
1610 Also, after we "goto redo_lookup_with_port" after binding
1611 a port on one of the possible addresses, we will
1612 try to bind that same port on every address, including the
1613 same address again for a second time; that one will
1614 also fail with EADDRINUSE.
1615
1616 For both those reasons, ignore EADDRINUSE here */
1617 tmp = tmp->ai_next;
1618 continue;
1619 }
1620 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1621 "Failed to bind socket \"%s:%s\": %s",
1622 host ? host : "*", port, _dbus_strerror (saved_errno));
1623 goto failed;
1624 }
1625
1626 if (listen (fd, 30 /* backlog */) < 0)
1627 {
1628 saved_errno = errno;
1629 _dbus_close (fd, NULL);
1630 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1631 "Failed to listen on socket \"%s:%s\": %s",
1632 host ? host : "*", port, _dbus_strerror (saved_errno));
1633 goto failed;
1634 }
1635
1636 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1637 if (!newlisten_fd)
1638 {
1639 _dbus_close (fd, NULL);
1640 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1641 "Failed to allocate file handle array");
1642 goto failed;
1643 }
1644 listen_fd = newlisten_fd;
1645 listen_fd[nlisten_fd].fd = fd;
1646 nlisten_fd++;
1647
1648 if (!_dbus_string_get_length(retport))
1649 {
1650 /* If the user didn't specify a port, or used 0, then
1651 the kernel chooses a port. After the first address
1652 is bound to, we need to force all remaining addresses
1653 to use the same port */
1654 if (!port || !strcmp(port, "0"))
1655 {
1656 int result;
1657 struct sockaddr_storage addr;
1658 socklen_t addrlen;
1659 char portbuf[50];
1660
1661 addrlen = sizeof(addr);
1662 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1663
1664 if (result == -1)
1665 {
1666 saved_errno = errno;
1667 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1668 "Failed to retrieve socket name for \"%s:%s\": %s",
1669 host ? host : "*", port, _dbus_strerror (saved_errno));
1670 goto failed;
1671 }
1672
1673 if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1674 portbuf, sizeof(portbuf),
1675 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1676 {
1677 saved_errno = errno;
1678 dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
1679 "Failed to resolve port \"%s:%s\": %s (%d)",
1680 host ? host : "*", port, gai_strerror(res), res);
1681 goto failed;
1682 }
1683
1684 if (!_dbus_string_append(retport, portbuf))
1685 {
1686 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1687 goto failed;
1688 }
1689
1690 /* Release current address list & redo lookup */
1691 port = _dbus_string_get_const_data(retport);
1692 freeaddrinfo(ai);
1693 goto redo_lookup_with_port;
1694 }
1695 else
1696 {
1697 if (!_dbus_string_append(retport, port))
1698 {
1699 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1700 goto failed;
1701 }
1702 }
1703 }
1704
1705 tmp = tmp->ai_next;
1706 }
1707 freeaddrinfo(ai);
1708 ai = NULL;
1709
1710 if (!nlisten_fd)
1711 {
1712 errno = EADDRINUSE;
1713 dbus_set_error (error, _dbus_error_from_errno (errno),
1714 "Failed to bind socket \"%s:%s\": %s",
1715 host ? host : "*", port, _dbus_strerror (errno));
1716 goto failed;
1717 }
1718
1719 for (i = 0 ; i < nlisten_fd ; i++)
1720 {
1721 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1722 {
1723 goto failed;
1724 }
1725 }
1726
1727 *fds_p = listen_fd;
1728
1729 return nlisten_fd;
1730
1731 failed:
1732 if (ai)
1733 freeaddrinfo(ai);
1734 for (i = 0 ; i < nlisten_fd ; i++)
1735 _dbus_close(listen_fd[i].fd, NULL);
1736 dbus_free(listen_fd);
1737 return -1;
1738 }
1739
1740 static dbus_bool_t
1741 write_credentials_byte (int server_fd,
1742 DBusError *error)
1743 {
1744 int bytes_written;
1745 char buf[1] = { '\0' };
1746 #if defined(HAVE_CMSGCRED)
1747 union {
1748 struct cmsghdr hdr;
1749 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1750 } cmsg;
1751 struct iovec iov;
1752 struct msghdr msg;
1753 iov.iov_base = buf;
1754 iov.iov_len = 1;
1755
1756 _DBUS_ZERO(msg);
1757 msg.msg_iov = &iov;
1758 msg.msg_iovlen = 1;
1759
1760 msg.msg_control = (caddr_t) &cmsg;
1761 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1762 _DBUS_ZERO(cmsg);
1763 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1764 cmsg.hdr.cmsg_level = SOL_SOCKET;
1765 cmsg.hdr.cmsg_type = SCM_CREDS;
1766 #endif
1767
1768 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1769
1770 again:
1771
1772 #if defined(HAVE_CMSGCRED)
1773 bytes_written = sendmsg (server_fd, &msg, 0
1774 #if HAVE_DECL_MSG_NOSIGNAL
1775 |MSG_NOSIGNAL
1776 #endif
1777 );
1778
1779 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1780 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1781 * only allows that on AF_UNIX. Try just doing a send() instead. */
1782 if (bytes_written < 0 && errno == EINVAL)
1783 #endif
1784 {
1785 bytes_written = send (server_fd, buf, 1, 0
1786 #if HAVE_DECL_MSG_NOSIGNAL
1787 |MSG_NOSIGNAL
1788 #endif
1789 );
1790 }
1791
1792 if (bytes_written < 0 && errno == EINTR)
1793 goto again;
1794
1795 if (bytes_written < 0)
1796 {
1797 dbus_set_error (error, _dbus_error_from_errno (errno),
1798 "Failed to write credentials byte: %s",
1799 _dbus_strerror (errno));
1800 return FALSE;
1801 }
1802 else if (bytes_written == 0)
1803 {
1804 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1805 "wrote zero bytes writing credentials byte");
1806 return FALSE;
1807 }
1808 else
1809 {
1810 _dbus_assert (bytes_written == 1);
1811 _dbus_verbose ("wrote credentials byte\n");
1812 return TRUE;
1813 }
1814 }
1815
1816 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1817 static dbus_bool_t
1818 add_linux_security_label_to_credentials (int client_fd,
1819 DBusCredentials *credentials)
1820 {
1821 #if defined(__linux__) && defined(SO_PEERSEC)
1822 DBusString buf;
1823 socklen_t len = 1024;
1824 dbus_bool_t oom = FALSE;
1825
1826 if (!_dbus_string_init_preallocated (&buf, len) ||
1827 !_dbus_string_set_length (&buf, len))
1828 return FALSE;
1829
1830 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1831 _dbus_string_get_data (&buf), &len) < 0)
1832 {
1833 int e = errno;
1834
1835 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1836 _dbus_strerror (e), (unsigned long) len);
1837
1838 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1839 {
1840 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1841 _dbus_strerror (e));
1842 goto out;
1843 }
1844
1845 /* If not enough space, len is updated to be enough.
1846 * Try again with a large enough buffer. */
1847 if (!_dbus_string_set_length (&buf, len))
1848 {
1849 oom = TRUE;
1850 goto out;
1851 }
1852
1853 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1854 }
1855
1856 if (len <= 0)
1857 {
1858 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1859 (unsigned long) len);
1860 goto out;
1861 }
1862
1863 if (len > _dbus_string_get_length_uint (&buf))
1864 {
1865 _dbus_verbose ("%lu > %u", (unsigned long) len,
1866 _dbus_string_get_length_uint (&buf));
1867 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1868 }
1869
1870 if (_dbus_string_get_byte (&buf, len - 1) == 0)
1871 {
1872 /* the kernel included the trailing \0 in its count,
1873 * but DBusString always has an extra \0 after the data anyway */
1874 _dbus_verbose ("subtracting trailing \\0\n");
1875 len--;
1876 }
1877
1878 if (!_dbus_string_set_length (&buf, len))
1879 {
1880 _dbus_assert_not_reached ("shortening string should not lead to OOM");
1881 oom = TRUE;
1882 goto out;
1883 }
1884
1885 if (strlen (_dbus_string_get_const_data (&buf)) != len)
1886 {
1887 /* LSM people on the linux-security-module@ mailing list say this
1888 * should never happen: the label should be a bytestring with
1889 * an optional trailing \0 */
1890 _dbus_verbose ("security label from kernel had an embedded \\0, "
1891 "ignoring it\n");
1892 goto out;
1893 }
1894
1895 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1896 (unsigned long) len,
1897 _dbus_string_get_const_data (&buf));
1898
1899 if (!_dbus_credentials_add_linux_security_label (credentials,
1900 _dbus_string_get_const_data (&buf)))
1901 {
1902 oom = TRUE;
1903 goto out;
1904 }
1905
1906 out:
1907 _dbus_string_free (&buf);
1908 return !oom;
1909 #else
1910 /* no error */
1911 return TRUE;
1912 #endif
1913 }
1914
1955 dbus_bool_t
1956 _dbus_read_credentials_socket (DBusSocket client_fd,
1957 DBusCredentials *credentials,
1958 DBusError *error)
1959 {
1960 struct msghdr msg;
1961 struct iovec iov;
1962 char buf;
1963 dbus_uid_t uid_read;
1964 dbus_pid_t pid_read;
1965 int bytes_read;
1966
1967 #ifdef HAVE_CMSGCRED
1968 union {
1969 struct cmsghdr hdr;
1970 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1971 } cmsg;
1972 #endif
1973
1974 /* The POSIX spec certainly doesn't promise this, but
1975 * we need these assertions to fail as soon as we're wrong about
1976 * it so we can do the porting fixups
1977 */
1978 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1979 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1980 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1981
1982 uid_read = DBUS_UID_UNSET;
1983 pid_read = DBUS_PID_UNSET;
1984
1985 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1986
1987 _dbus_credentials_clear (credentials);
1988
1989 iov.iov_base = &buf;
1990 iov.iov_len = 1;
1991
1992 _DBUS_ZERO(msg);
1993 msg.msg_iov = &iov;
1994 msg.msg_iovlen = 1;
1995
1996 #if defined(HAVE_CMSGCRED)
1997 _DBUS_ZERO(cmsg);
1998 msg.msg_control = (caddr_t) &cmsg;
1999 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
2000 #endif
2001
2002 again:
2003 bytes_read = recvmsg (client_fd.fd, &msg, 0);
2004
2005 if (bytes_read < 0)
2006 {
2007 if (errno == EINTR)
2008 goto again;
2009
2010 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
2011 * normally only call read_credentials if the socket was ready
2012 * for reading
2013 */
2014
2015 dbus_set_error (error, _dbus_error_from_errno (errno),
2016 "Failed to read credentials byte: %s",
2017 _dbus_strerror (errno));
2018 return FALSE;
2019 }
2020 else if (bytes_read == 0)
2021 {
2022 /* this should not happen unless we are using recvmsg wrong,
2023 * so is essentially here for paranoia
2024 */
2025 dbus_set_error (error, DBUS_ERROR_FAILED,
2026 "Failed to read credentials byte (zero-length read)");
2027 return FALSE;
2028 }
2029 else if (buf != '\0')
2030 {
2031 dbus_set_error (error, DBUS_ERROR_FAILED,
2032 "Credentials byte was not nul");
2033 return FALSE;
2034 }
2035
2036 _dbus_verbose ("read credentials byte\n");
2037
2038 {
2039 #ifdef SO_PEERCRED
2040 /* Supported by at least Linux and OpenBSD, with minor differences.
2041 *
2042 * This mechanism passes the process ID through and does not require
2043 * the peer's cooperation, so we prefer it over all others. Notably,
2044 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
2045 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
2046 * because this is much less fragile.
2047 */
2048 #ifdef __OpenBSD__
2049 struct sockpeercred cr;
2050 #else
2051 struct ucred cr;
2052 #endif
2053 socklen_t cr_len = sizeof (cr);
2054
2055 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
2056 {
2057 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
2058 _dbus_strerror (errno));
2059 }
2060 else if (cr_len != sizeof (cr))
2061 {
2062 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2063 cr_len, (int) sizeof (cr));
2064 }
2065 else
2066 {
2067 pid_read = cr.pid;
2068 uid_read = cr.uid;
2069 }
2070 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2071 /* Another variant of the above - used on NetBSD
2072 */
2073 struct unpcbid cr;
2074 socklen_t cr_len = sizeof (cr);
2075
2076 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2077 {
2078 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2079 _dbus_strerror (errno));
2080 }
2081 else if (cr_len != sizeof (cr))
2082 {
2083 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2084 cr_len, (int) sizeof (cr));
2085 }
2086 else
2087 {
2088 pid_read = cr.unp_pid;
2089 uid_read = cr.unp_euid;
2090 }
2091 #elif defined(HAVE_CMSGCRED)
2092 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2093 * presence of that struct implies SCM_CREDS. Supported by at least
2094 * FreeBSD and DragonflyBSD.
2095 *
2096 * This mechanism requires the peer to help us (it has to send us a
2097 * SCM_CREDS message) but it does pass the process ID through,
2098 * which makes it better than getpeereid().
2099 */
2100 struct cmsgcred *cred;
2101 struct cmsghdr *cmsgp;
2102
2103 for (cmsgp = CMSG_FIRSTHDR (&msg);
2104 cmsgp != NULL;
2105 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2106 {
2107 if (cmsgp->cmsg_type == SCM_CREDS &&
2108 cmsgp->cmsg_level == SOL_SOCKET &&
2109 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2110 {
2111 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2112 pid_read = cred->cmcred_pid;
2113 uid_read = cred->cmcred_euid;
2114 break;
2115 }
2116 }
2117
2118 #elif defined(HAVE_GETPEERUCRED)
2119 /* Supported in at least Solaris >= 10. It should probably be higher
2120 * up this list, because it carries the pid and we use this code path
2121 * for audit data. */
2122 ucred_t * ucred = NULL;
2123 if (getpeerucred (client_fd.fd, &ucred) == 0)
2124 {
2125 #ifdef HAVE_ADT
2126 adt_session_data_t *adth = NULL;
2127 #endif
2128 pid_read = ucred_getpid (ucred);
2129 uid_read = ucred_geteuid (ucred);
2130 #ifdef HAVE_ADT
2131 /* generate audit session data based on socket ucred */
2132 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2133 {
2134 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2135 }
2136 else
2137 {
2138 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2139 {
2140 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2141 }
2142 else
2143 {
2144 adt_export_data_t *data = NULL;
2145 size_t size = adt_export_session_data (adth, &data);
2146 if (size <= 0)
2147 {
2148 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2149 }
2150 else
2151 {
2152 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2153 free (data);
2154 }
2155 }
2156 (void) adt_end_session (adth);
2157 }
2158 #endif /* HAVE_ADT */
2159 }
2160 else
2161 {
2162 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2163 }
2164 if (ucred != NULL)
2165 ucred_free (ucred);
2166
2167 /* ----------------------------------------------------------------
2168 * When adding new mechanisms, please add them above this point
2169 * if they support passing the process ID through, or below if not.
2170 * ---------------------------------------------------------------- */
2171
2172 #elif defined(HAVE_GETPEEREID)
2173 /* getpeereid() originates from D.J. Bernstein and is fairly
2174 * widely-supported. According to a web search, it might be present in
2175 * any/all of:
2176 *
2177 * - AIX?
2178 * - Blackberry?
2179 * - Cygwin
2180 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2181 * - Mac OS X
2182 * - Minix 3.1.8+
2183 * - MirBSD?
2184 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2185 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2186 * - QNX?
2187 */
2188 uid_t euid;
2189 gid_t egid;
2190 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2191 {
2192 uid_read = euid;
2193 }
2194 else
2195 {
2196 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2197 }
2198 #else /* no supported mechanism */
2199
2200 #warning Socket credentials not supported on this Unix OS
2201 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2202
2203 /* Please add other operating systems known to support at least one of
2204 * the mechanisms above to this list, keeping alphabetical order.
2205 * Everything not in this list is best-effort.
2206 */
2207 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2208 defined(__linux__) || \
2209 defined(__OpenBSD__) || \
2210 defined(__NetBSD__)
2211 # error Credentials passing not working on this OS is a regression!
2212 #endif
2213
2214 _dbus_verbose ("Socket credentials not supported on this OS\n");
2215 #endif
2216 }
2217
2218 _dbus_verbose ("Credentials:"
2219 " pid "DBUS_PID_FORMAT
2220 " uid "DBUS_UID_FORMAT
2221 "\n",
2222 pid_read,
2223 uid_read);
2224
2225 if (pid_read != DBUS_PID_UNSET)
2226 {
2227 if (!_dbus_credentials_add_pid (credentials, pid_read))
2228 {
2229 _DBUS_SET_OOM (error);
2230 return FALSE;
2231 }
2232 }
2233
2234 if (uid_read != DBUS_UID_UNSET)
2235 {
2236 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2237 {
2238 _DBUS_SET_OOM (error);
2239 return FALSE;
2240 }
2241 }
2242
2243 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2244 {
2245 _DBUS_SET_OOM (error);
2246 return FALSE;
2247 }
2248
2249 return TRUE;
2250 }
2251
2269 dbus_bool_t
2270 _dbus_send_credentials_socket (DBusSocket server_fd,
2271 DBusError *error)
2272 {
2273 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2274
2275 if (write_credentials_byte (server_fd.fd, error))
2276 return TRUE;
2277 else
2278 return FALSE;
2279 }
2280
2290 DBusSocket
2291 _dbus_accept (DBusSocket listen_fd)
2292 {
2293 DBusSocket client_fd;
2294 struct sockaddr addr;
2295 socklen_t addrlen;
2296 #ifdef HAVE_ACCEPT4
2297 dbus_bool_t cloexec_done;
2298 #endif
2299
2300 addrlen = sizeof (addr);
2301
2302 retry:
2303
2304 #ifdef HAVE_ACCEPT4
2305 /*
2306 * At compile-time, we assume that if accept4() is available in
2307 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2308 * not necessarily true that either is supported by the running kernel.
2309 */
2310 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2311 cloexec_done = client_fd.fd >= 0;
2312
2313 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2314 #endif
2315 {
2316 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2317 }
2318
2319 if (client_fd.fd < 0)
2320 {
2321 if (errno == EINTR)
2322 goto retry;
2323 }
2324
2325 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2326
2327 #ifdef HAVE_ACCEPT4
2328 if (!cloexec_done)
2329 #endif
2330 {
2331 _dbus_fd_set_close_on_exec(client_fd.fd);
2332 }
2333
2334 return client_fd;
2335 }
2336
2345 dbus_bool_t
2346 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2347 {
2348 const char *directory;
2349 struct stat sb;
2350
2351 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2352
2353 directory = _dbus_string_get_const_data (dir);
2354
2355 if (stat (directory, &sb) < 0)
2356 {
2357 dbus_set_error (error, _dbus_error_from_errno (errno),
2358 "%s", _dbus_strerror (errno));
2359
2360 return FALSE;
2361 }
2362
2363 if (sb.st_uid != geteuid ())
2364 {
2365 dbus_set_error (error, DBUS_ERROR_FAILED,
2366 "%s directory is owned by user %lu, not %lu",
2367 directory,
2368 (unsigned long) sb.st_uid,
2369 (unsigned long) geteuid ());
2370 return FALSE;
2371 }
2372
2373 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2374 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2375 {
2376 dbus_set_error (error, DBUS_ERROR_FAILED,
2377 "%s directory is not private to the user", directory);
2378 return FALSE;
2379 }
2380
2381 return TRUE;
2382 }
2383
2384 static dbus_bool_t
2385 fill_user_info_from_passwd (struct passwd *p,
2386 DBusUserInfo *info,
2387 DBusError *error)
2388 {
2389 _dbus_assert (p->pw_name != NULL);
2390 _dbus_assert (p->pw_dir != NULL);
2391
2392 info->uid = p->pw_uid;
2393 info->primary_gid = p->pw_gid;
2394 info->username = _dbus_strdup (p->pw_name);
2395 info->homedir = _dbus_strdup (p->pw_dir);
2396
2397 if (info->username == NULL ||
2398 info->homedir == NULL)
2399 {
2400 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2401 return FALSE;
2402 }
2403
2404 return TRUE;
2405 }
2406
2407 static dbus_bool_t
2408 fill_user_info (DBusUserInfo *info,
2409 dbus_uid_t uid,
2410 const DBusString *username,
2411 DBusError *error)
2412 {
2413 const char *username_c;
2414
2415 /* exactly one of username/uid provided */
2416 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2417 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2418
2419 info->uid = DBUS_UID_UNSET;
2420 info->primary_gid = DBUS_GID_UNSET;
2421 info->group_ids = NULL;
2422 info->n_group_ids = 0;
2423 info->username = NULL;
2424 info->homedir = NULL;
2425
2426 if (username != NULL)
2427 username_c = _dbus_string_get_const_data (username);
2428 else
2429 username_c = NULL;
2430
2431 /* For now assuming that the getpwnam() and getpwuid() flavors
2432 * are always symmetrical, if not we have to add more configure
2433 * checks
2434 */
2435
2436 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2437 {
2438 struct passwd *p;
2439 int result;
2440 size_t buflen;
2441 char *buf;
2442 struct passwd p_str;
2443
2444 /* retrieve maximum needed size for buf */
2445 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2446
2447 /* sysconf actually returns a long, but everything else expects size_t,
2448 * so just recast here.
2449 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2450 */
2451 if ((long) buflen <= 0)
2452 buflen = 1024;
2453
2454 result = -1;
2455 while (1)
2456 {
2457 buf = dbus_malloc (buflen);
2458 if (buf == NULL)
2459 {
2460 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2461 return FALSE;
2462 }
2463
2464 p = NULL;
2465 #ifdef HAVE_POSIX_GETPWNAM_R
2466 if (uid != DBUS_UID_UNSET)
2467 result = getpwuid_r (uid, &p_str, buf, buflen,
2468 &p);
2469 else
2470 result = getpwnam_r (username_c, &p_str, buf, buflen,
2471 &p);
2472 #else
2473 if (uid != DBUS_UID_UNSET)
2474 p = getpwuid_r (uid, &p_str, buf, buflen);
2475 else
2476 p = getpwnam_r (username_c, &p_str, buf, buflen);
2477 result = 0;
2478 #endif /* !HAVE_POSIX_GETPWNAM_R */
2479 //Try a bigger buffer if ERANGE was returned
2480 if (result == ERANGE && buflen < 512 * 1024)
2481 {
2482 dbus_free (buf);
2483 buflen *= 2;
2484 }
2485 else
2486 {
2487 break;
2488 }
2489 }
2490 if (result == 0 && p == &p_str)
2491 {
2492 if (!fill_user_info_from_passwd (p, info, error))
2493 {
2494 dbus_free (buf);
2495 return FALSE;
2496 }
2497 dbus_free (buf);
2498 }
2499 else
2500 {
2501 dbus_set_error (error, _dbus_error_from_errno (errno),
2502 "User \"%s\" unknown or no memory to allocate password entry\n",
2503 username_c ? username_c : "???");
2504 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2505 dbus_free (buf);
2506 return FALSE;
2507 }
2508 }
2509 #else /* ! HAVE_GETPWNAM_R */
2510 {
2511 /* I guess we're screwed on thread safety here */
2512 struct passwd *p;
2513
2514 if (uid != DBUS_UID_UNSET)
2515 p = getpwuid (uid);
2516 else
2517 p = getpwnam (username_c);
2518
2519 if (p != NULL)
2520 {
2521 if (!fill_user_info_from_passwd (p, info, error))
2522 {
2523 return FALSE;
2524 }
2525 }
2526 else
2527 {
2528 dbus_set_error (error, _dbus_error_from_errno (errno),
2529 "User \"%s\" unknown or no memory to allocate password entry\n",
2530 username_c ? username_c : "???");
2531 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2532 return FALSE;
2533 }
2534 }
2535 #endif /* ! HAVE_GETPWNAM_R */
2536
2537 /* Fill this in so we can use it to get groups */
2538 username_c = info->username;
2539
2540 #ifdef HAVE_GETGROUPLIST
2541 {
2542 gid_t *buf;
2543 int buf_count;
2544 int i;
2545 int initial_buf_count;
2546
2547 initial_buf_count = 17;
2548 buf_count = initial_buf_count;
2549 buf = dbus_new (gid_t, buf_count);
2550 if (buf == NULL)
2551 {
2552 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2553 goto failed;
2554 }
2555
2556 if (getgrouplist (username_c,
2557 info->primary_gid,
2558 buf, &buf_count) < 0)
2559 {
2560 gid_t *new;
2561 /* Presumed cause of negative return code: buf has insufficient
2562 entries to hold the entire group list. The Linux behavior in this
2563 case is to pass back the actual number of groups in buf_count, but
2564 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2565 So as a hack, try to help out a bit by guessing a larger
2566 number of groups, within reason.. might still fail, of course,
2567 but we can at least print a more informative message. I looked up
2568 the "right way" to do this by downloading Apple's own source code
2569 for the "id" command, and it turns out that they use an
2570 undocumented library function getgrouplist_2 (!) which is not
2571 declared in any header in /usr/include (!!). That did not seem
2572 like the way to go here.
2573 */
2574 if (buf_count == initial_buf_count)
2575 {
2576 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2577 }
2578 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2579 if (new == NULL)
2580 {
2581 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2582 dbus_free (buf);
2583 goto failed;
2584 }
2585
2586 buf = new;
2587
2588 errno = 0;
2589 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2590 {
2591 if (errno == 0)
2592 {
2593 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2594 username_c, buf_count, buf_count);
2595 }
2596 else
2597 {
2598 dbus_set_error (error,
2599 _dbus_error_from_errno (errno),
2600 "Failed to get groups for username \"%s\" primary GID "
2601 DBUS_GID_FORMAT ": %s\n",
2602 username_c, info->primary_gid,
2603 _dbus_strerror (errno));
2604 dbus_free (buf);
2605 goto failed;
2606 }
2607 }
2608 }
2609
2610 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2611 if (info->group_ids == NULL)
2612 {
2613 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2614 dbus_free (buf);
2615 goto failed;
2616 }
2617
2618 for (i = 0; i < buf_count; ++i)
2619 info->group_ids[i] = buf[i];
2620
2621 info->n_group_ids = buf_count;
2622
2623 dbus_free (buf);
2624 }
2625 #else /* HAVE_GETGROUPLIST */
2626 {
2627 /* We just get the one group ID */
2628 info->group_ids = dbus_new (dbus_gid_t, 1);
2629 if (info->group_ids == NULL)
2630 {
2631 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2632 goto failed;
2633 }
2634
2635 info->n_group_ids = 1;
2636
2637 (info->group_ids)[0] = info->primary_gid;
2638 }
2639 #endif /* HAVE_GETGROUPLIST */
2640
2641 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2642
2643 return TRUE;
2644
2645 failed:
2646 _DBUS_ASSERT_ERROR_IS_SET (error);
2647 return FALSE;
2648 }
2649
2658 dbus_bool_t
2659 _dbus_user_info_fill (DBusUserInfo *info,
2660 const DBusString *username,
2661 DBusError *error)
2662 {
2663 return fill_user_info (info, DBUS_UID_UNSET,
2664 username, error);
2665 }
2666
2675 dbus_bool_t
2676 _dbus_user_info_fill_uid (DBusUserInfo *info,
2677 dbus_uid_t uid,
2678 DBusError *error)
2679 {
2680 return fill_user_info (info, uid,
2681 NULL, error);
2682 }
2683
2691 dbus_bool_t
2692 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2693 {
2694 /* The POSIX spec certainly doesn't promise this, but
2695 * we need these assertions to fail as soon as we're wrong about
2696 * it so we can do the porting fixups
2697 */
2698 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2699 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2700 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2701
2702 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2703 return FALSE;
2704 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2705 return FALSE;
2706
2707 return TRUE;
2708 }
2709
2721 dbus_bool_t
2722 _dbus_append_user_from_current_process (DBusString *str)
2723 {
2724 return _dbus_string_append_uint (str,
2725 _dbus_geteuid ());
2726 }
2727
2732 dbus_pid_t
2733 _dbus_getpid (void)
2734 {
2735 return getpid ();
2736 }
2737
2741 dbus_uid_t
2742 _dbus_getuid (void)
2743 {
2744 return getuid ();
2745 }
2746
2750 dbus_uid_t
2751 _dbus_geteuid (void)
2752 {
2753 return geteuid ();
2754 }
2755
2762 unsigned long
2763 _dbus_pid_for_log (void)
2764 {
2765 return getpid ();
2766 }
2767
2775 dbus_bool_t
2776 _dbus_parse_uid (const DBusString *uid_str,
2777 dbus_uid_t *uid)
2778 {
2779 int end;
2780 long val;
2781
2782 if (_dbus_string_get_length (uid_str) == 0)
2783 {
2784 _dbus_verbose ("UID string was zero length\n");
2785 return FALSE;
2786 }
2787
2788 val = -1;
2789 end = 0;
2790 if (!_dbus_string_parse_int (uid_str, 0, &val,
2791 &end))
2792 {
2793 _dbus_verbose ("could not parse string as a UID\n");
2794 return FALSE;
2795 }
2796
2797 if (end != _dbus_string_get_length (uid_str))
2798 {
2799 _dbus_verbose ("string contained trailing stuff after UID\n");
2800 return FALSE;
2801 }
2802
2803 *uid = val;
2804
2805 return TRUE;
2806 }
2807
2808 #if !DBUS_USE_SYNC
2809 /* To be thread-safe by default on platforms that don't necessarily have
2810 * atomic operations (notably Debian armel, which is armv4t), we must
2811 * use a mutex that can be initialized statically, like this.
2812 * GLib >= 2.32 uses a similar system.
2813 */
2814 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2815 #endif
2816
2823 dbus_int32_t
2824 _dbus_atomic_inc (DBusAtomic *atomic)
2825 {
2826 #if DBUS_USE_SYNC
2827 return __sync_add_and_fetch(&atomic->value, 1)-1;
2828 #else
2829 dbus_int32_t res;
2830
2831 pthread_mutex_lock (&atomic_mutex);
2832 res = atomic->value;
2833 atomic->value += 1;
2834 pthread_mutex_unlock (&atomic_mutex);
2835
2836 return res;
2837 #endif
2838 }
2839
2846 dbus_int32_t
2847 _dbus_atomic_dec (DBusAtomic *atomic)
2848 {
2849 #if DBUS_USE_SYNC
2850 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2851 #else
2852 dbus_int32_t res;
2853
2854 pthread_mutex_lock (&atomic_mutex);
2855 res = atomic->value;
2856 atomic->value -= 1;
2857 pthread_mutex_unlock (&atomic_mutex);
2858
2859 return res;
2860 #endif
2861 }
2862
2870 dbus_int32_t
2871 _dbus_atomic_get (DBusAtomic *atomic)
2872 {
2873 #if DBUS_USE_SYNC
2874 __sync_synchronize ();
2875 return atomic->value;
2876 #else
2877 dbus_int32_t res;
2878
2879 pthread_mutex_lock (&atomic_mutex);
2880 res = atomic->value;
2881 pthread_mutex_unlock (&atomic_mutex);
2882
2883 return res;
2884 #endif
2885 }
2886
2895 int
2896 _dbus_poll (DBusPollFD *fds,
2897 int n_fds,
2898 int timeout_milliseconds)
2899 {
2900 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2901 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2902 if (timeout_milliseconds < -1)
2903 {
2904 timeout_milliseconds = -1;
2905 }
2906
2907 return poll (fds,
2908 n_fds,
2909 timeout_milliseconds);
2910 #else /* ! HAVE_POLL */
2911 /* Emulate poll() in terms of select() */
2912 fd_set read_set, write_set, err_set;
2913 int max_fd = 0;
2914 int i;
2915 struct timeval tv;
2916 int ready;
2917
2918 FD_ZERO (&read_set);
2919 FD_ZERO (&write_set);
2920 FD_ZERO (&err_set);
2921
2922 for (i = 0; i < n_fds; i++)
2923 {
2924 DBusPollFD *fdp = &fds[i];
2925
2926 if (fdp->events & _DBUS_POLLIN)
2927 FD_SET (fdp->fd, &read_set);
2928
2929 if (fdp->events & _DBUS_POLLOUT)
2930 FD_SET (fdp->fd, &write_set);
2931
2932 FD_SET (fdp->fd, &err_set);
2933
2934 max_fd = MAX (max_fd, fdp->fd);
2935 }
2936
2937 tv.tv_sec = timeout_milliseconds / 1000;
2938 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2939
2940 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2941 timeout_milliseconds < 0 ? NULL : &tv);
2942
2943 if (ready > 0)
2944 {
2945 for (i = 0; i < n_fds; i++)
2946 {
2947 DBusPollFD *fdp = &fds[i];
2948
2949 fdp->revents = 0;
2950
2951 if (FD_ISSET (fdp->fd, &read_set))
2952 fdp->revents |= _DBUS_POLLIN;
2953
2954 if (FD_ISSET (fdp->fd, &write_set))
2955 fdp->revents |= _DBUS_POLLOUT;
2956
2957 if (FD_ISSET (fdp->fd, &err_set))
2958 fdp->revents |= _DBUS_POLLERR;
2959 }
2960 }
2961
2962 return ready;
2963 #endif
2964 }
2965
2973 void
2974 _dbus_get_monotonic_time (long *tv_sec,
2975 long *tv_usec)
2976 {
2977 #ifdef HAVE_MONOTONIC_CLOCK
2978 struct timespec ts;
2979 clock_gettime (CLOCK_MONOTONIC, &ts);
2980
2981 if (tv_sec)
2982 *tv_sec = ts.tv_sec;
2983 if (tv_usec)
2984 *tv_usec = ts.tv_nsec / 1000;
2985 #else
2986 struct timeval t;
2987
2988 gettimeofday (&t, NULL);
2989
2990 if (tv_sec)
2991 *tv_sec = t.tv_sec;
2992 if (tv_usec)
2993 *tv_usec = t.tv_usec;
2994 #endif
2995 }
2996
3004 void
3005 _dbus_get_real_time (long *tv_sec,
3006 long *tv_usec)
3007 {
3008 struct timeval t;
3009
3010 gettimeofday (&t, NULL);
3011
3012 if (tv_sec)
3013 *tv_sec = t.tv_sec;
3014 if (tv_usec)
3015 *tv_usec = t.tv_usec;
3016 }
3017
3026 dbus_bool_t
3027 _dbus_ensure_directory (const DBusString *filename,
3028 DBusError *error)
3029 {
3030 const char *filename_c;
3031
3032 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3033
3034 filename_c = _dbus_string_get_const_data (filename);
3035
3036 if (mkdir (filename_c, 0700) < 0)
3037 {
3038 if (errno == EEXIST)
3039 return TRUE;
3040
3041 dbus_set_error (error, DBUS_ERROR_FAILED,
3042 "Failed to create directory %s: %s\n",
3043 filename_c, _dbus_strerror (errno));
3044 return FALSE;
3045 }
3046 else
3047 return TRUE;
3048 }
3049
3058 dbus_bool_t
3059 _dbus_create_directory (const DBusString *filename,
3060 DBusError *error)
3061 {
3062 const char *filename_c;
3063
3064 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3065
3066 filename_c = _dbus_string_get_const_data (filename);
3067
3068 if (mkdir (filename_c, 0700) < 0)
3069 {
3070 dbus_set_error (error, DBUS_ERROR_FAILED,
3071 "Failed to create directory %s: %s\n",
3072 filename_c, _dbus_strerror (errno));
3073 return FALSE;
3074 }
3075 else
3076 return TRUE;
3077 }
3078
3089 dbus_bool_t
3090 _dbus_concat_dir_and_file (DBusString *dir,
3091 const DBusString *next_component)
3092 {
3093 dbus_bool_t dir_ends_in_slash;
3094 dbus_bool_t file_starts_with_slash;
3095
3096 if (_dbus_string_get_length (dir) == 0 ||
3097 _dbus_string_get_length (next_component) == 0)
3098 return TRUE;
3099
3100 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3101 _dbus_string_get_length (dir) - 1);
3102
3103 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3104
3105 if (dir_ends_in_slash && file_starts_with_slash)
3106 {
3107 _dbus_string_shorten (dir, 1);
3108 }
3109 else if (!(dir_ends_in_slash || file_starts_with_slash))
3110 {
3111 if (!_dbus_string_append_byte (dir, '/'))
3112 return FALSE;
3113 }
3114
3115 return _dbus_string_copy (next_component, 0, dir,
3116 _dbus_string_get_length (dir));
3117 }
3118
3120 #define NANOSECONDS_PER_SECOND 1000000000
3121
3122 #define MICROSECONDS_PER_SECOND 1000000
3123
3124 #define MILLISECONDS_PER_SECOND 1000
3125
3126 #define NANOSECONDS_PER_MILLISECOND 1000000
3127
3128 #define MICROSECONDS_PER_MILLISECOND 1000
3129
3134 void
3135 _dbus_sleep_milliseconds (int milliseconds)
3136 {
3137 #ifdef HAVE_NANOSLEEP
3138 struct timespec req;
3139 struct timespec rem;
3140
3141 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3142 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3143 rem.tv_sec = 0;
3144 rem.tv_nsec = 0;
3145
3146 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3147 req = rem;
3148 #elif defined (HAVE_USLEEP)
3149 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3150 #else /* ! HAVE_USLEEP */
3151 sleep (MAX (milliseconds / 1000, 1));
3152 #endif
3153 }
3154
3164 dbus_bool_t
3165 _dbus_generate_random_bytes (DBusString *str,
3166 int n_bytes,
3167 DBusError *error)
3168 {
3169 int old_len;
3170 int fd;
3171 int result;
3172
3173 old_len = _dbus_string_get_length (str);
3174 fd = -1;
3175
3176 /* note, urandom on linux will fall back to pseudorandom */
3177 fd = open ("/dev/urandom", O_RDONLY);
3178
3179 if (fd < 0)
3180 {
3181 dbus_set_error (error, _dbus_error_from_errno (errno),
3182 "Could not open /dev/urandom: %s",
3183 _dbus_strerror (errno));
3184 return FALSE;
3185 }
3186
3187 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3188
3189 result = _dbus_read (fd, str, n_bytes);
3190
3191 if (result != n_bytes)
3192 {
3193 if (result < 0)
3194 dbus_set_error (error, _dbus_error_from_errno (errno),
3195 "Could not read /dev/urandom: %s",
3196 _dbus_strerror (errno));
3197 else
3198 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
3199 "Short read from /dev/urandom");
3200
3201 _dbus_close (fd, NULL);
3202 _dbus_string_set_length (str, old_len);
3203 return FALSE;
3204 }
3205
3206 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3207 n_bytes);
3208
3209 _dbus_close (fd, NULL);
3210
3211 return TRUE;
3212 }
3213
3219 void
3220 _dbus_exit (int code)
3221 {
3222 _exit (code);
3223 }
3224
3233 const char*
3234 _dbus_strerror (int error_number)
3235 {
3236 const char *msg;
3237
3238 msg = strerror (error_number);
3239 if (msg == NULL)
3240 msg = "unknown";
3241
3242 return msg;
3243 }
3244
3248 void
3249 _dbus_disable_sigpipe (void)
3250 {
3251 signal (SIGPIPE, SIG_IGN);
3252 }
3253
3261 void
3262 _dbus_fd_set_close_on_exec (int fd)
3263 {
3264 int val;
3265
3266 val = fcntl (fd, F_GETFD, 0);
3267
3268 if (val < 0)
3269 return;
3270
3271 val |= FD_CLOEXEC;
3272
3273 fcntl (fd, F_SETFD, val);
3274 }
3275
3283 dbus_bool_t
3284 _dbus_close (int fd,
3285 DBusError *error)
3286 {
3287 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3288
3289 again:
3290 if (close (fd) < 0)
3291 {
3292 if (errno == EINTR)
3293 goto again;
3294
3295 dbus_set_error (error, _dbus_error_from_errno (errno),
3296 "Could not close fd %d", fd);
3297 return FALSE;
3298 }
3299
3300 return TRUE;
3301 }
3302
3311 int
3312 _dbus_dup(int fd,
3313 DBusError *error)
3314 {
3315 int new_fd;
3316
3317 #ifdef F_DUPFD_CLOEXEC
3318 dbus_bool_t cloexec_done;
3319
3320 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3321 cloexec_done = new_fd >= 0;
3322
3323 if (new_fd < 0 && errno == EINVAL)
3324 #endif
3325 {
3326 new_fd = fcntl(fd, F_DUPFD, 3);
3327 }
3328
3329 if (new_fd < 0) {
3330
3331 dbus_set_error (error, _dbus_error_from_errno (errno),
3332 "Could not duplicate fd %d", fd);
3333 return -1;
3334 }
3335
3336 #ifdef F_DUPFD_CLOEXEC
3337 if (!cloexec_done)
3338 #endif
3339 {
3340 _dbus_fd_set_close_on_exec(new_fd);
3341 }
3342
3343 return new_fd;
3344 }
3345
3353 dbus_bool_t
3354 _dbus_set_socket_nonblocking (DBusSocket fd,
3355 DBusError *error)
3356 {
3357 return _dbus_set_fd_nonblocking (fd.fd, error);
3358 }
3359
3360 static dbus_bool_t
3361 _dbus_set_fd_nonblocking (int fd,
3362 DBusError *error)
3363 {
3364 int val;
3365
3366 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3367
3368 val = fcntl (fd, F_GETFL, 0);
3369 if (val < 0)
3370 {
3371 dbus_set_error (error, _dbus_error_from_errno (errno),
3372 "Failed to get flags from file descriptor %d: %s",
3373 fd, _dbus_strerror (errno));
3374 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3375 _dbus_strerror (errno));
3376 return FALSE;
3377 }
3378
3379 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3380 {
3381 dbus_set_error (error, _dbus_error_from_errno (errno),
3382 "Failed to set nonblocking flag of file descriptor %d: %s",
3383 fd, _dbus_strerror (errno));
3384 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3385 fd, _dbus_strerror (errno));
3386
3387 return FALSE;
3388 }
3389
3390 return TRUE;
3391 }
3392
3398 void
3399 _dbus_print_backtrace (void)
3400 {
3401 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3402 void *bt[500];
3403 int bt_size;
3404 int i;
3405 char **syms;
3406
3407 bt_size = backtrace (bt, 500);
3408
3409 syms = backtrace_symbols (bt, bt_size);
3410
3411 i = 0;
3412 while (i < bt_size)
3413 {
3414 /* don't use dbus_warn since it can _dbus_abort() */
3415 fprintf (stderr, " %s\n", syms[i]);
3416 ++i;
3417 }
3418 fflush (stderr);
3419
3420 free (syms);
3421 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3422 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3423 #else
3424 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3425 #endif
3426 }
3427
3440 dbus_bool_t
3441 _dbus_socketpair (DBusSocket *fd1,
3442 DBusSocket *fd2,
3443 dbus_bool_t blocking,
3444 DBusError *error)
3445 {
3446 #ifdef HAVE_SOCKETPAIR
3447 int fds[2];
3448 int retval;
3449
3450 #ifdef SOCK_CLOEXEC
3451 dbus_bool_t cloexec_done;
3452
3453 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3454 cloexec_done = retval >= 0;
3455
3456 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3457 #endif
3458 {
3459 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3460 }
3461
3462 if (retval < 0)
3463 {
3464 dbus_set_error (error, _dbus_error_from_errno (errno),
3465 "Could not create full-duplex pipe");
3466 return FALSE;
3467 }
3468
3469 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3470
3471 #ifdef SOCK_CLOEXEC
3472 if (!cloexec_done)
3473 #endif
3474 {
3475 _dbus_fd_set_close_on_exec (fds[0]);
3476 _dbus_fd_set_close_on_exec (fds[1]);
3477 }
3478
3479 if (!blocking &&
3480 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3481 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3482 {
3483 dbus_set_error (error, _dbus_error_from_errno (errno),
3484 "Could not set full-duplex pipe nonblocking");
3485
3486 _dbus_close (fds[0], NULL);
3487 _dbus_close (fds[1], NULL);
3488
3489 return FALSE;
3490 }
3491
3492 fd1->fd = fds[0];
3493 fd2->fd = fds[1];
3494
3495 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3496 fd1->fd, fd2->fd);
3497
3498 return TRUE;
3499 #else
3500 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3501 dbus_set_error (error, DBUS_ERROR_FAILED,
3502 "_dbus_socketpair() not implemented on this OS");
3503 return FALSE;
3504 #endif
3505 }
3506
3515 int
3516 _dbus_printf_string_upper_bound (const char *format,
3517 va_list args)
3518 {
3519 char static_buf[1024];
3520 int bufsize = sizeof (static_buf);
3521 int len;
3522 va_list args_copy;
3523
3524 DBUS_VA_COPY (args_copy, args);
3525 len = vsnprintf (static_buf, bufsize, format, args_copy);
3526 va_end (args_copy);
3527
3528 /* If vsnprintf() returned non-negative, then either the string fits in
3529 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3530 * returns the number of characters that were needed, or this OS returns the
3531 * truncated length.
3532 *
3533 * We ignore the possibility that snprintf might just ignore the length and
3534 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3535 * If your libc is really that bad, come back when you have a better one. */
3536 if (len == bufsize)
3537 {
3538 /* This could be the truncated length (Tru64 and IRIX have this bug),
3539 * or the real length could be coincidentally the same. Which is it?
3540 * If vsnprintf returns the truncated length, we'll go to the slow
3541 * path. */
3542 DBUS_VA_COPY (args_copy, args);
3543
3544 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3545 len = -1;
3546
3547 va_end (args_copy);
3548 }
3549
3550 /* If vsnprintf() returned negative, we have to do more work.
3551 * HP-UX returns negative. */
3552 while (len < 0)
3553 {
3554 char *buf;
3555
3556 bufsize *= 2;
3557
3558 buf = dbus_malloc (bufsize);
3559
3560 if (buf == NULL)
3561 return -1;
3562
3563 DBUS_VA_COPY (args_copy, args);
3564 len = vsnprintf (buf, bufsize, format, args_copy);
3565 va_end (args_copy);
3566
3567 dbus_free (buf);
3568
3569 /* If the reported length is exactly the buffer size, round up to the
3570 * next size, in case vsnprintf has been returning the truncated
3571 * length */
3572 if (len == bufsize)
3573 len = -1;
3574 }
3575
3576 return len;
3577 }
3578
3585 const char*
3586 _dbus_get_tmpdir(void)
3587 {
3588 /* Protected by _DBUS_LOCK_sysdeps */
3589 static const char* tmpdir = NULL;
3590
3591 if (!_DBUS_LOCK (sysdeps))
3592 return NULL;
3593
3594 if (tmpdir == NULL)
3595 {
3596 /* TMPDIR is what glibc uses, then
3597 * glibc falls back to the P_tmpdir macro which
3598 * just expands to "/tmp"
3599 */
3600 if (tmpdir == NULL)
3601 tmpdir = getenv("TMPDIR");
3602
3603 /* These two env variables are probably
3604 * broken, but maybe some OS uses them?
3605 */
3606 if (tmpdir == NULL)
3607 tmpdir = getenv("TMP");
3608 if (tmpdir == NULL)
3609 tmpdir = getenv("TEMP");
3610
3611 /* And this is the sane fallback. */
3612 if (tmpdir == NULL)
3613 tmpdir = "/tmp";
3614 }
3615
3616 _DBUS_UNLOCK (sysdeps);
3617
3618 _dbus_assert(tmpdir != NULL);
3619
3620 return tmpdir;
3621 }
3622
3623 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3624
3643 static dbus_bool_t
3644 _read_subprocess_line_argv (const char *progpath,
3645 dbus_bool_t path_fallback,
3646 const char * const *argv,
3647 DBusString *result,
3648 DBusError *error)
3649 {
3650 int result_pipe[2] = { -1, -1 };
3651 int errors_pipe[2] = { -1, -1 };
3652 pid_t pid;
3653 int ret;
3654 int status;
3655 int orig_len;
3656
3657 dbus_bool_t retval;
3658 sigset_t new_set, old_set;
3659
3660 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3661 retval = FALSE;
3662
3663 /* We need to block any existing handlers for SIGCHLD temporarily; they
3664 * will cause waitpid() below to fail.
3665 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3666 */
3667 sigemptyset (&new_set);
3668 sigaddset (&new_set, SIGCHLD);
3669 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3670
3671 orig_len = _dbus_string_get_length (result);
3672
3673 #define READ_END 0
3674 #define WRITE_END 1
3675 if (pipe (result_pipe) < 0)
3676 {
3677 dbus_set_error (error, _dbus_error_from_errno (errno),
3678 "Failed to create a pipe to call %s: %s",
3679 progpath, _dbus_strerror (errno));
3680 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3681 progpath, _dbus_strerror (errno));
3682 goto out;
3683 }
3684 if (pipe (errors_pipe) < 0)
3685 {
3686 dbus_set_error (error, _dbus_error_from_errno (errno),
3687 "Failed to create a pipe to call %s: %s",
3688 progpath, _dbus_strerror (errno));
3689 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3690 progpath, _dbus_strerror (errno));
3691 goto out;
3692 }
3693
3694 pid = fork ();
3695 if (pid < 0)
3696 {
3697 dbus_set_error (error, _dbus_error_from_errno (errno),
3698 "Failed to fork() to call %s: %s",
3699 progpath, _dbus_strerror (errno));
3700 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3701 progpath, _dbus_strerror (errno));
3702 goto out;
3703 }
3704
3705 if (pid == 0)
3706 {
3707 /* child process */
3708 const char *error_str;
3709
3710 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
3711 {
3712 int saved_errno = errno;
3713
3714 /* Try to write details into the pipe, but don't bother
3715 * trying too hard (no retry loop). */
3716
3717 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
3718 write (errors_pipe[WRITE_END], ": ", 2) < 0)
3719 {
3720 /* ignore, not much we can do */
3721 }
3722
3723 error_str = _dbus_strerror (saved_errno);
3724
3725 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
3726 {
3727 /* ignore, not much we can do */
3728 }
3729
3730 _exit (1);
3731 }
3732
3733 /* set-up stdXXX */
3734 close (result_pipe[READ_END]);
3735 close (errors_pipe[READ_END]);
3736
3737 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3738 _exit (1);
3739 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3740 _exit (1);
3741
3742 _dbus_close_all ();
3743
3744 sigprocmask (SIG_SETMASK, &old_set, NULL);
3745
3746 /* If it looks fully-qualified, try execv first */
3747 if (progpath[0] == '/')
3748 {
3749 execv (progpath, (char * const *) argv);
3750 /* Ok, that failed. Now if path_fallback is given, let's
3751 * try unqualified. This is mostly a hack to work
3752 * around systems which ship dbus-launch in /usr/bin
3753 * but everything else in /bin (because dbus-launch
3754 * depends on X11).
3755 */
3756 if (path_fallback)
3757 /* We must have a slash, because we checked above */
3758 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
3759 }
3760 else
3761 execvp (progpath, (char * const *) argv);
3762
3763 /* still nothing, we failed */
3764 _exit (1);
3765 }
3766
3767 /* parent process */
3768 close (result_pipe[WRITE_END]);
3769 close (errors_pipe[WRITE_END]);
3770 result_pipe[WRITE_END] = -1;
3771 errors_pipe[WRITE_END] = -1;
3772
3773 ret = 0;
3774 do
3775 {
3776 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3777 }
3778 while (ret > 0);
3779
3780 /* reap the child process to avoid it lingering as zombie */
3781 do
3782 {
3783 ret = waitpid (pid, &status, 0);
3784 }
3785 while (ret == -1 && errno == EINTR);
3786
3787 /* We succeeded if the process exited with status 0 and
3788 anything was read */
3789 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3790 {
3791 /* The process ended with error */
3792 DBusString error_message;
3793 if (!_dbus_string_init (&error_message))
3794 {
3795 _DBUS_SET_OOM (error);
3796 goto out;
3797 }
3798
3799 ret = 0;
3800 do
3801 {
3802 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3803 }
3804 while (ret > 0);
3805
3806 _dbus_string_set_length (result, orig_len);
3807 if (_dbus_string_get_length (&error_message) > 0)
3808 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3809 "%s terminated abnormally with the following error: %s",
3810 progpath, _dbus_string_get_data (&error_message));
3811 else
3812 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3813 "%s terminated abnormally without any error message",
3814 progpath);
3815 goto out;
3816 }
3817
3818 retval = TRUE;
3819
3820 out:
3821 sigprocmask (SIG_SETMASK, &old_set, NULL);
3822
3823 if (retval)
3824 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3825 else
3826 _DBUS_ASSERT_ERROR_IS_SET (error);
3827
3828 if (result_pipe[0] != -1)
3829 close (result_pipe[0]);
3830 if (result_pipe[1] != -1)
3831 close (result_pipe[1]);
3832 if (errors_pipe[0] != -1)
3833 close (errors_pipe[0]);
3834 if (errors_pipe[1] != -1)
3835 close (errors_pipe[1]);
3836
3837 return retval;
3838 }
3839 #endif
3840
3853 dbus_bool_t
3854 _dbus_get_autolaunch_address (const char *scope,
3855 DBusString *address,
3856 DBusError *error)
3857 {
3858 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3859 static const char arg_dbus_launch[] = "dbus-launch";
3860 static const char arg_autolaunch[] = "--autolaunch";
3861 static const char arg_binary_syntax[] = "--binary-syntax";
3862 static const char arg_close_stderr[] = "--close-stderr";
3863
3864 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3865 * but that's done elsewhere, and if it worked, this function wouldn't
3866 * be called.) */
3867 const char *display;
3868 const char *progpath;
3869 const char *argv[6];
3870 int i;
3871 DBusString uuid;
3872 dbus_bool_t retval;
3873
3874 if (_dbus_check_setuid ())
3875 {
3876 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3877 "Unable to autolaunch when setuid");
3878 return FALSE;
3879 }
3880
3881 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3882 retval = FALSE;
3883
3884 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3885 * dbus-launch-x11 is just going to fail. Rather than trying to
3886 * run it, we might as well bail out early with a nice error.
3887 *
3888 * This is not strictly true in a world where the user bus exists,
3889 * because dbus-launch --autolaunch knows how to connect to that -
3890 * but if we were going to connect to the user bus, we'd have done
3891 * so before trying autolaunch: in any case. */
3892 display = _dbus_getenv ("DISPLAY");
3893
3894 if (display == NULL || display[0] == '\0')
3895 {
3896 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3897 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3898 return FALSE;
3899 }
3900
3901 if (!_dbus_string_init (&uuid))
3902 {
3903 _DBUS_SET_OOM (error);
3904 return FALSE;
3905 }
3906
3907 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3908 {
3909 goto out;
3910 }
3911
3912 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3913 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
3914
3915 if (progpath == NULL)
3916 #endif
3917 progpath = DBUS_BINDIR "/dbus-launch";
3918 /*
3919 * argv[0] is always dbus-launch, that's the name what we'll
3920 * get from /proc, or ps(1), regardless what the progpath is,
3921 * see fd.o#69716
3922 */
3923 i = 0;
3924 argv[i] = arg_dbus_launch;
3925 ++i;
3926 argv[i] = arg_autolaunch;
3927 ++i;
3928 argv[i] = _dbus_string_get_data (&uuid);
3929 ++i;
3930 argv[i] = arg_binary_syntax;
3931 ++i;
3932 argv[i] = arg_close_stderr;
3933 ++i;
3934 argv[i] = NULL;
3935 ++i;
3936
3937 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3938
3939 retval = _read_subprocess_line_argv (progpath,
3940 TRUE,
3941 argv, address, error);
3942
3943 out:
3944 _dbus_string_free (&uuid);
3945 return retval;
3946 #else
3947 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3948 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3949 "set your DBUS_SESSION_BUS_ADDRESS instead");
3950 return FALSE;
3951 #endif
3952 }
3953
3972 dbus_bool_t
3973 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3974 dbus_bool_t create_if_not_found,
3975 DBusError *error)
3976 {
3977 DBusError our_error = DBUS_ERROR_INIT;
3978 DBusError etc_error = DBUS_ERROR_INIT;
3979 DBusString filename;
3980 dbus_bool_t b;
3981
3982 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3983
3984 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
3985 if (b)
3986 return TRUE;
3987
3988 /* Fallback to the system machine ID */
3989 _dbus_string_init_const (&filename, "/etc/machine-id");
3990 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
3991
3992 if (b)
3993 {
3994 if (create_if_not_found)
3995 {
3996 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3997 * complain if that isn't possible for whatever reason */
3998 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3999 _dbus_write_uuid_file (&filename, machine_id, NULL);
4000 }
4001
4002 dbus_error_free (&our_error);
4003 return TRUE;
4004 }
4005
4006 if (!create_if_not_found)
4007 {
4008 dbus_set_error (error, etc_error.name,
4009 "D-Bus library appears to be incorrectly set up: "
4010 "see the manual page for dbus-uuidgen to correct "
4011 "this issue. (%s; %s)",
4012 our_error.message, etc_error.message);
4013 dbus_error_free (&our_error);
4014 dbus_error_free (&etc_error);
4015 return FALSE;
4016 }
4017
4018 dbus_error_free (&our_error);
4019 dbus_error_free (&etc_error);
4020
4021 /* if none found, try to make a new one */
4022 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4023
4024 if (!_dbus_generate_uuid (machine_id, error))
4025 return FALSE;
4026
4027 return _dbus_write_uuid_file (&filename, machine_id, error);
4028 }
4029
4037 dbus_bool_t
4038 _dbus_lookup_launchd_socket (DBusString *socket_path,
4039 const char *launchd_env_var,
4040 DBusError *error)
4041 {
4042 #ifdef DBUS_ENABLE_LAUNCHD
4043 char *argv[4];
4044 int i;
4045
4046 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4047
4048 if (_dbus_check_setuid ())
4049 {
4050 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4051 "Unable to find launchd socket when setuid");
4052 return FALSE;
4053 }
4054
4055 i = 0;
4056 argv[i] = "launchctl";
4057 ++i;
4058 argv[i] = "getenv";
4059 ++i;
4060 argv[i] = (char*)launchd_env_var;
4061 ++i;
4062 argv[i] = NULL;
4063 ++i;
4064
4065 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4066
4067 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4068 {
4069 return FALSE;
4070 }
4071
4072 /* no error, but no result either */
4073 if (_dbus_string_get_length(socket_path) == 0)
4074 {
4075 return FALSE;
4076 }
4077
4078 /* strip the carriage-return */
4079 _dbus_string_shorten(socket_path, 1);
4080 return TRUE;
4081 #else /* DBUS_ENABLE_LAUNCHD */
4082 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
4083 "can't lookup socket from launchd; launchd support not compiled in");
4084 return FALSE;
4085 #endif
4086 }
4087
4088 #ifdef DBUS_ENABLE_LAUNCHD
4089 static dbus_bool_t
4090 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4091 {
4092 dbus_bool_t valid_socket;
4093 DBusString socket_path;
4094
4095 if (_dbus_check_setuid ())
4096 {
4097 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4098 "Unable to find launchd socket when setuid");
4099 return FALSE;
4100 }
4101
4102 if (!_dbus_string_init (&socket_path))
4103 {
4104 _DBUS_SET_OOM (error);
4105 return FALSE;
4106 }
4107
4108 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4109
4110 if (dbus_error_is_set(error))
4111 {
4112 _dbus_string_free(&socket_path);
4113 return FALSE;
4114 }
4115
4116 if (!valid_socket)
4117 {
4118 dbus_set_error(error, "no socket path",
4119 "launchd did not provide a socket path, "
4120 "verify that org.freedesktop.dbus-session.plist is loaded!");
4121 _dbus_string_free(&socket_path);
4122 return FALSE;
4123 }
4124 if (!_dbus_string_append (address, "unix:path="))
4125 {
4126 _DBUS_SET_OOM (error);
4127 _dbus_string_free(&socket_path);
4128 return FALSE;
4129 }
4130 if (!_dbus_string_copy (&socket_path, 0, address,
4131 _dbus_string_get_length (address)))
4132 {
4133 _DBUS_SET_OOM (error);
4134 _dbus_string_free(&socket_path);
4135 return FALSE;
4136 }
4137
4138 _dbus_string_free(&socket_path);
4139 return TRUE;
4140 }
4141 #endif
4142
4143 dbus_bool_t
4144 _dbus_lookup_user_bus (dbus_bool_t *supported,
4145 DBusString *address,
4146 DBusError *error)
4147 {
4148 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4149 dbus_bool_t ret = FALSE;
4150 struct stat stbuf;
4151 DBusString user_bus_path;
4152
4153 if (runtime_dir == NULL)
4154 {
4155 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4156 *supported = FALSE;
4157 return TRUE; /* Cannot use it, but not an error */
4158 }
4159
4160 if (!_dbus_string_init (&user_bus_path))
4161 {
4162 _DBUS_SET_OOM (error);
4163 return FALSE;
4164 }
4165
4166 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4167 {
4168 _DBUS_SET_OOM (error);
4169 goto out;
4170 }
4171
4172 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4173 {
4174 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4175 _dbus_strerror (errno));
4176 *supported = FALSE;
4177 ret = TRUE; /* Cannot use it, but not an error */
4178 goto out;
4179 }
4180
4181 if (stbuf.st_uid != getuid ())
4182 {
4183 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4184 (long) stbuf.st_uid, (long) getuid ());
4185 *supported = FALSE;
4186 ret = TRUE; /* Cannot use it, but not an error */
4187 goto out;
4188 }
4189
4190 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4191 {
4192 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4193 (long) stbuf.st_mode);
4194 *supported = FALSE;
4195 ret = TRUE; /* Cannot use it, but not an error */
4196 goto out;
4197 }
4198
4199 if (!_dbus_string_append (address, "unix:path=") ||
4200 !_dbus_address_append_escaped (address, &user_bus_path))
4201 {
4202 _DBUS_SET_OOM (error);
4203 goto out;
4204 }
4205
4206 *supported = TRUE;
4207 ret = TRUE;
4208
4209 out:
4210 _dbus_string_free (&user_bus_path);
4211 return ret;
4212 }
4213
4233 dbus_bool_t
4234 _dbus_lookup_session_address (dbus_bool_t *supported,
4235 DBusString *address,
4236 DBusError *error)
4237 {
4238 #ifdef DBUS_ENABLE_LAUNCHD
4239 *supported = TRUE;
4240 return _dbus_lookup_session_address_launchd (address, error);
4241 #else
4242 *supported = FALSE;
4243
4244 if (!_dbus_lookup_user_bus (supported, address, error))
4245 return FALSE;
4246 else if (*supported)
4247 return TRUE;
4248
4249 /* On non-Mac Unix platforms, if the session address isn't already
4250 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4251 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4252 * autolaunch: global default; see init_session_address in
4253 * dbus/dbus-bus.c. */
4254 return TRUE;
4255 #endif
4256 }
4257
4265 void
4266 _dbus_flush_caches (void)
4267 {
4268 _dbus_user_database_flush_system ();
4269 }
4270
4284 dbus_bool_t
4285 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
4286 DBusCredentials *credentials)
4287 {
4288 DBusString homedir;
4289 DBusString dotdir;
4290 dbus_uid_t uid;
4291
4292 _dbus_assert (credentials != NULL);
4293 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
4294
4295 if (!_dbus_string_init (&homedir))
4296 return FALSE;
4297
4298 uid = _dbus_credentials_get_unix_uid (credentials);
4299 _dbus_assert (uid != DBUS_UID_UNSET);
4300
4301 if (!_dbus_homedir_from_uid (uid, &homedir))
4302 goto failed;
4303
4304 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4305 {
4306 const char *override;
4307
4308 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4309 if (override != NULL && *override != '\0')
4310 {
4311 _dbus_string_set_length (&homedir, 0);
4312 if (!_dbus_string_append (&homedir, override))
4313 goto failed;
4314
4315 _dbus_verbose ("Using fake homedir for testing: %s\n",
4316 _dbus_string_get_const_data (&homedir));
4317 }
4318 else
4319 {
4320 /* Not strictly thread-safe, but if we fail at thread-safety here,
4321 * the worst that will happen is some extra warnings. */
4322 static dbus_bool_t already_warned = FALSE;
4323 if (!already_warned)
4324 {
4325 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4326 _dbus_string_get_const_data (&homedir));
4327 already_warned = TRUE;
4328 }
4329 }
4330 }
4331 #endif
4332
4333 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4334 if (!_dbus_concat_dir_and_file (&homedir,
4335 &dotdir))
4336 goto failed;
4337
4338 if (!_dbus_string_copy (&homedir, 0,
4339 directory, _dbus_string_get_length (directory))) {
4340 goto failed;
4341 }
4342
4343 _dbus_string_free (&homedir);
4344 return TRUE;
4345
4346 failed:
4347 _dbus_string_free (&homedir);
4348 return FALSE;
4349 }
4350
4351 //PENDING(kdab) docs
4352 dbus_bool_t
4353 _dbus_daemon_publish_session_bus_address (const char* addr,
4354 const char *scope)
4355 {
4356 return TRUE;
4357 }
4358
4359 //PENDING(kdab) docs
4360 void
4361 _dbus_daemon_unpublish_session_bus_address (void)
4362 {
4363
4364 }
4365
4372 dbus_bool_t
4373 _dbus_get_is_errno_eagain_or_ewouldblock (int e)
4374 {
4375 /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
4376 * EWOULDBLOCK are numerically equal, which is permitted as described by
4377 * errno(3).
4378 */
4379 #if EAGAIN == EWOULDBLOCK
4380 return e == EAGAIN;
4381 #else
4382 return e == EAGAIN || e == EWOULDBLOCK;
4383 #endif
4384 }
4385
4393 dbus_bool_t
4394 _dbus_delete_directory (const DBusString *filename,
4395 DBusError *error)
4396 {
4397 const char *filename_c;
4398
4399 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4400
4401 filename_c = _dbus_string_get_const_data (filename);
4402
4403 if (rmdir (filename_c) != 0)
4404 {
4405 dbus_set_error (error, DBUS_ERROR_FAILED,
4406 "Failed to remove directory %s: %s\n",
4407 filename_c, _dbus_strerror (errno));
4408 return FALSE;
4409 }
4410
4411 return TRUE;
4412 }
4413
4421 dbus_bool_t
4422 _dbus_socket_can_pass_unix_fd (DBusSocket fd)
4423 {
4424 #ifdef SCM_RIGHTS
4425 union {
4426 struct sockaddr sa;
4427 struct sockaddr_storage storage;
4428 struct sockaddr_un un;
4429 } sa_buf;
4430
4431 socklen_t sa_len = sizeof(sa_buf);
4432
4433 _DBUS_ZERO(sa_buf);
4434
4435 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4436 return FALSE;
4437
4438 return sa_buf.sa.sa_family == AF_UNIX;
4439
4440 #else
4441 return FALSE;
4442
4443 #endif
4444 }
4445
4450 void
4451 _dbus_close_all (void)
4452 {
4453 int maxfds, i;
4454
4455 #ifdef __linux__
4456 DIR *d;
4457
4458 /* On Linux we can optimize this a bit if /proc is available. If it
4459 isn't available, fall back to the brute force way. */
4460
4461 d = opendir ("/proc/self/fd");
4462 if (d)
4463 {
4464 for (;;)
4465 {
4466 struct dirent *de;
4467 int fd;
4468 long l;
4469 char *e = NULL;
4470
4471 de = readdir (d);
4472 if (!de)
4473 break;
4474
4475 if (de->d_name[0] == '.')
4476 continue;
4477
4478 errno = 0;
4479 l = strtol (de->d_name, &e, 10);
4480 if (errno != 0 || e == NULL || *e != '\0')
4481 continue;
4482
4483 fd = (int) l;
4484 if (fd < 3)
4485 continue;
4486
4487 if (fd == dirfd (d))
4488 continue;
4489
4490 close (fd);
4491 }
4492
4493 closedir (d);
4494 return;
4495 }
4496 #endif
4497
4498 maxfds = sysconf (_SC_OPEN_MAX);
4499
4500 /* Pick something reasonable if for some reason sysconf says
4501 * unlimited.
4502 */
4503 if (maxfds < 0)
4504 maxfds = 1024;
4505
4506 /* close all inherited fds */
4507 for (i = 3; i < maxfds; i++)
4508 close (i);
4509 }
4510
4520 dbus_bool_t
4521 _dbus_check_setuid (void)
4522 {
4523 /* TODO: get __libc_enable_secure exported from glibc.
4524 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4525 */
4526 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4527 {
4528 /* See glibc/include/unistd.h */
4529 extern int __libc_enable_secure;
4530 return __libc_enable_secure;
4531 }
4532 #elif defined(HAVE_ISSETUGID)
4533 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4534 return issetugid ();
4535 #else
4536 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4537 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4538
4539 /* We call into this function from _dbus_threads_init_platform_specific()
4540 * to make sure these are initialized before we start threading. */
4541 static dbus_bool_t check_setuid_initialised;
4542 static dbus_bool_t is_setuid;
4543
4544 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4545 {
4546 #ifdef HAVE_GETRESUID
4547 if (getresuid (&ruid, &euid, &suid) != 0 ||
4548 getresgid (&rgid, &egid, &sgid) != 0)
4549 #endif /* HAVE_GETRESUID */
4550 {
4551 suid = ruid = getuid ();
4552 sgid = rgid = getgid ();
4553 euid = geteuid ();
4554 egid = getegid ();
4555 }
4556
4557 check_setuid_initialised = TRUE;
4558 is_setuid = (ruid != euid || ruid != suid ||
4559 rgid != egid || rgid != sgid);
4560
4561 }
4562 return is_setuid;
4563 #endif
4564 }
4565
4573 dbus_bool_t
4574 _dbus_append_address_from_socket (DBusSocket fd,
4575 DBusString *address,
4576 DBusError *error)
4577 {
4578 union {
4579 struct sockaddr sa;
4580 struct sockaddr_storage storage;
4581 struct sockaddr_un un;
4582 struct sockaddr_in ipv4;
4583 struct sockaddr_in6 ipv6;
4584 } socket;
4585 char hostip[INET6_ADDRSTRLEN];
4586 socklen_t size = sizeof (socket);
4587 DBusString path_str;
4588
4589 if (getsockname (fd.fd, &socket.sa, &size))
4590 goto err;
4591
4592 switch (socket.sa.sa_family)
4593 {
4594 case AF_UNIX:
4595 if (socket.un.sun_path[0]=='\0')
4596 {
4597 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4598 if (_dbus_string_append (address, "unix:abstract=") &&
4599 _dbus_address_append_escaped (address, &path_str))
4600 return TRUE;
4601 }
4602 else
4603 {
4604 _dbus_string_init_const (&path_str, socket.un.sun_path);
4605 if (_dbus_string_append (address, "unix:path=") &&
4606 _dbus_address_append_escaped (address, &path_str))
4607 return TRUE;
4608 }
4609 break;
4610 case AF_INET:
4611 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4612 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4613 hostip, ntohs (socket.ipv4.sin_port)))
4614 return TRUE;
4615 break;
4616 #ifdef AF_INET6
4617 case AF_INET6:
4618 _dbus_string_init_const (&path_str, hostip);
4619 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4620 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4621 ntohs (socket.ipv6.sin6_port)) &&
4622 _dbus_address_append_escaped (address, &path_str))
4623 return TRUE;
4624 break;
4625 #endif
4626 default:
4627 dbus_set_error (error,
4628 _dbus_error_from_errno (EINVAL),
4629 "Failed to read address from socket: Unknown socket type.");
4630 return FALSE;
4631 }
4632 err:
4633 dbus_set_error (error,
4634 _dbus_error_from_errno (errno),
4635 "Failed to open socket: %s",
4636 _dbus_strerror (errno));
4637 return FALSE;
4638 }
4639
4640 int
4641 _dbus_save_socket_errno (void)
4642 {
4643 return errno;
4644 }
4645
4646 void
4647 _dbus_restore_socket_errno (int saved_errno)
4648 {
4649 errno = saved_errno;
4650 }
4651
4652 static const char *syslog_tag = "dbus";
4653 #ifdef HAVE_SYSLOG_H
4654 static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4655 #endif
4656
4671 void
4672 _dbus_init_system_log (const char *tag,
4673 DBusLogFlags flags)
4674 {
4675 /* We never want to turn off logging completely */
4676 _dbus_assert (
4677 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
4678
4679 syslog_tag = tag;
4680
4681 #ifdef HAVE_SYSLOG_H
4682 log_flags = flags;
4683
4684 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4685 openlog (tag, LOG_PID, LOG_DAEMON);
4686 #endif
4687 }
4688
4696 void
4697 _dbus_logv (DBusSystemLogSeverity severity,
4698 const char *msg,
4699 va_list args)
4700 {
4701 va_list tmp;
4702 #ifdef HAVE_SYSLOG_H
4703 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4704 {
4705 int flags;
4706 switch (severity)
4707 {
4708 case DBUS_SYSTEM_LOG_INFO:
4709 flags = LOG_DAEMON | LOG_INFO;
4710 break;
4711 case DBUS_SYSTEM_LOG_WARNING:
4712 flags = LOG_DAEMON | LOG_WARNING;
4713 break;
4714 case DBUS_SYSTEM_LOG_SECURITY:
4715 flags = LOG_AUTH | LOG_NOTICE;
4716 break;
4717 case DBUS_SYSTEM_LOG_ERROR:
4718 flags = LOG_DAEMON|LOG_CRIT;
4719 break;
4720 default:
4721 _dbus_assert_not_reached ("invalid log severity");
4722 }
4723
4724 DBUS_VA_COPY (tmp, args);
4725 vsyslog (flags, msg, tmp);
4726 va_end (tmp);
4727 }
4728
4729 /* If we don't have syslog.h, we always behave as though stderr was in
4730 * the flags */
4731 if (log_flags & DBUS_LOG_FLAGS_STDERR)
4732 #endif
4733 {
4734 DBUS_VA_COPY (tmp, args);
4735 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
4736 vfprintf (stderr, msg, tmp);
4737 fputc ('\n', stderr);
4738 va_end (tmp);
4739 }
4740 }
4741
4742 /* tests in dbus-sysdeps-util.c */
_dbus_string_append
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:935
_dbus_string_parse_int
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_parse_int(const DBusString *str, int start, long *value_return, int *end_return)
Parses an integer contained in a DBusString.
Definition: dbus-sysdeps.c:437
DBusAtomic
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:306
_dbus_credentials_get_unix_uid
dbus_uid_t _dbus_credentials_get_unix_uid(DBusCredentials *credentials)
Gets the UNIX user ID in the credentials, or DBUS_UID_UNSET if the credentials object doesn't contain...
Definition: dbus-credentials.c:297
_dbus_string_append_uint
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:394
DBusError::message
const char * message
public error message field
Definition: dbus-errors.h:51
DBusUserInfo::username
char * username
Username.
Definition: dbus-sysdeps-unix.h:112
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
DBusCredentials
Definition: dbus-credentials.c:48
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition: dbus-protocol.h:416
DBusAtomic::value
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:311
_dbus_check_dir_is_private_to_user
dbus_bool_t _dbus_check_dir_is_private_to_user(DBusString *dir, DBusError *error)
Checks to make sure the given directory is private to the user.
Definition: dbus-sysdeps-unix.c:2346
_dbus_read_local_machine_uuid
dbus_bool_t _dbus_read_local_machine_uuid(DBusGUID *machine_id, dbus_bool_t create_if_not_found, DBusError *error)
Reads the uuid of the machine we're running on from the dbus configuration.
Definition: dbus-sysdeps-unix.c:3973
_dbus_close_all
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:4451
_dbus_string_lengthen
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:760
_dbus_ensure_directory
dbus_bool_t _dbus_ensure_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
Definition: dbus-sysdeps-unix.c:3027
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
_dbus_socketpair
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
Definition: dbus-sysdeps-unix.c:3441
_dbus_write
int _dbus_write(int fd, const DBusString *buffer, int start, int len)
Thin wrapper around the write() system call that writes a part of a DBusString and handles EINTR for ...
Definition: dbus-sysdeps-unix.c:772
_dbus_ensure_standard_fds
dbus_bool_t _dbus_ensure_standard_fds(DBusEnsureStandardFdsFlags flags, const char **error_str_p)
Ensure that the standard file descriptors stdin, stdout and stderr are open, by opening /dev/null if ...
Definition: dbus-sysdeps-unix.c:155
DBUS_ERROR_NOT_SUPPORTED
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
Definition: dbus-protocol.h:369
dbus_new
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
DBUS_GID_FORMAT
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
Definition: dbus-sysdeps.h:150
DBUS_PID_FORMAT
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:146
_dbus_generate_uuid
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
Definition: dbus-internals.c:667
_dbus_get_local_machine_uuid_encoded
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
Definition: dbus-internals.c:898
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition: dbus-internals.h:152
_dbus_append_address_from_socket
dbus_bool_t _dbus_append_address_from_socket(DBusSocket fd, DBusString *address, DBusError *error)
Read the address from the socket and append it to the string.
Definition: dbus-sysdeps-unix.c:4574
DBUS_ERROR_INIT
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
_dbus_check_setuid
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib.
Definition: dbus-sysdeps-unix.c:4521
_dbus_user_database_flush_system
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
Definition: dbus-userdb.c:349
dbus_error_free
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
DBusUserInfo::primary_gid
dbus_gid_t primary_gid
GID.
Definition: dbus-sysdeps-unix.h:109
_dbus_credentials_add_linux_security_label
dbus_bool_t _dbus_credentials_add_linux_security_label(DBusCredentials *credentials, const char *label)
Add a Linux security label, as used by LSMs such as SELinux, Smack and AppArmor, to the credentials.
Definition: dbus-credentials.c:207
DBusPollFD
Definition: dbus-sysdeps.h:397
DBusGUID
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
Definition: dbus-internals.h:394
_dbus_getpid
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
Definition: dbus-sysdeps-unix.c:2733
_DBUS_POLLIN
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:405
_dbus_concat_dir_and_file
dbus_bool_t _dbus_concat_dir_and_file(DBusString *dir, const DBusString *next_component)
Appends the given filename to the given directory.
Definition: dbus-sysdeps-unix.c:3090
_dbus_string_get_data_len
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:490
_dbus_read_socket
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
Definition: dbus-sysdeps-unix.c:302
DBUS_MAXIMUM_MESSAGE_UNIX_FDS
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
Definition: dbus-protocol.h:218
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
DBUS_ERROR_IO_ERROR
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
Definition: dbus-protocol.h:365
_dbus_dup
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
Definition: dbus-sysdeps-unix.c:3312
_dbus_string_shorten
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:780
DBusPollFD::events
short events
Events to poll for.
Definition: dbus-sysdeps.h:400
_dbus_string_copy
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1283
DBUS_PID_UNSET
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
Definition: dbus-sysdeps.h:139
_dbus_send_credentials_socket
dbus_bool_t _dbus_send_credentials_socket(DBusSocket server_fd, DBusError *error)
Sends a single nul byte with our UNIX credentials as ancillary data.
Definition: dbus-sysdeps-unix.c:2270
_dbus_close_socket
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
Definition: dbus-sysdeps-unix.c:286
_dbus_credentials_clear
void _dbus_credentials_clear(DBusCredentials *credentials)
Clear all credentials in the object.
Definition: dbus-credentials.c:503
DBUS_UID_UNSET
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:141
_dbus_parse_uid
dbus_bool_t _dbus_parse_uid(const DBusString *uid_str, dbus_uid_t *uid)
Gets a UID from a UID string.
Definition: dbus-sysdeps-unix.c:2776
_dbus_get_autolaunch_address
dbus_bool_t _dbus_get_autolaunch_address(const char *scope, DBusString *address, DBusError *error)
Returns the address of a new session bus.
Definition: dbus-sysdeps-unix.c:3854
_dbus_error_from_errno
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
Definition: dbus-sysdeps.c:592
_dbus_user_info_fill
dbus_bool_t _dbus_user_info_fill(DBusUserInfo *info, const DBusString *username, DBusError *error)
Gets user info for the given username.
Definition: dbus-sysdeps-unix.c:2659
_dbus_homedir_from_uid
dbus_bool_t _dbus_homedir_from_uid(dbus_uid_t uid, DBusString *homedir)
Gets the home directory for the given user.
Definition: dbus-userdb.c:461
dbus_pid_t
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:132
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:175
DBusUserInfo::group_ids
dbus_gid_t * group_ids
Groups IDs, including above primary group.
Definition: dbus-sysdeps-unix.h:110
_dbus_lookup_launchd_socket
dbus_bool_t _dbus_lookup_launchd_socket(DBusString *socket_path, const char *launchd_env_var, DBusError *error)
quries launchd for a specific env var which holds the socket path.
Definition: dbus-sysdeps-unix.c:4038
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:462
_dbus_append_user_from_current_process
dbus_bool_t _dbus_append_user_from_current_process(DBusString *str)
Append to the string the identity we would like to have when we authenticate, on UNIX this is the cur...
Definition: dbus-sysdeps-unix.c:2722
_dbus_credentials_are_anonymous
dbus_bool_t _dbus_credentials_are_anonymous(DBusCredentials *credentials)
Checks whether a credentials object contains a user identity.
Definition: dbus-credentials.c:408
DBusString
Definition: dbus-string.h:42
_dbus_get_is_errno_eagain_or_ewouldblock
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(int e)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted)
Definition: dbus-sysdeps-unix.c:4373
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
_dbus_string_init_const
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
DBusUserInfo::n_group_ids
int n_group_ids
Size of group IDs array.
Definition: dbus-sysdeps-unix.h:111
_dbus_listen_systemd_sockets
int _dbus_listen_systemd_sockets(DBusSocket **fds, DBusError *error)
Acquires one or more sockets passed in from systemd.
Definition: dbus-sysdeps-unix.c:1247
_DBUS_POLLOUT
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:409
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition: dbus-internals.c:230
_dbus_write_socket_two
int _dbus_write_socket_two(DBusSocket fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write_two() but only works on sockets and is thus available on Windows.
Definition: dbus-sysdeps-unix.c:639
_dbus_accept
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
Definition: dbus-sysdeps-unix.c:2291
_dbus_string_init_preallocated
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:132
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition: dbus-sysdeps-unix.c:2824
DBusUserInfo::uid
dbus_uid_t uid
UID.
Definition: dbus-sysdeps-unix.h:108
_dbus_print_backtrace
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
Definition: dbus-sysdeps-unix.c:3399
_dbus_read
int _dbus_read(int fd, DBusString *buffer, int count)
Thin wrapper around the read() system call that appends the data it reads to the DBusString buffer.
Definition: dbus-sysdeps-unix.c:712
_dbus_string_append_printf
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1114
_dbus_append_keyring_directory_for_credentials
dbus_bool_t _dbus_append_keyring_directory_for_credentials(DBusString *directory, DBusCredentials *credentials)
Appends the directory in which a keyring for the given credentials should be stored.
Definition: dbus-sysdeps-unix.c:4285
_dbus_read_credentials_socket
dbus_bool_t _dbus_read_credentials_socket(DBusSocket client_fd, DBusCredentials *credentials, DBusError *error)
Reads a single byte which must be nul (an error occurs otherwise), and reads unix credentials if avai...
Definition: dbus-sysdeps-unix.c:1956
_dbus_create_directory
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
Definition: dbus-sysdeps-unix.c:3059
_dbus_delete_directory
dbus_bool_t _dbus_delete_directory(const DBusString *filename, DBusError *error)
Removes a directory; Directory must be empty.
Definition: dbus-sysdeps-unix.c:4394
DBusError
Object representing an exception.
Definition: dbus-errors.h:48
_dbus_address_append_escaped
dbus_bool_t _dbus_address_append_escaped(DBusString *escaped, const DBusString *unescaped)
Appends an escaped version of one string to another string, using the D-Bus address escaping mechanis...
Definition: dbus-address.c:104
_dbus_get_monotonic_time
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
Definition: dbus-sysdeps-unix.c:2974
_dbus_listen_tcp_socket
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, DBusSocket **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
Definition: dbus-sysdeps-unix.c:1522
_dbus_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition: dbus-sysdeps-unix.c:3249
DBUS_ERROR_BAD_ADDRESS
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
Definition: dbus-protocol.h:367
dbus_set_error
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
_dbus_credentials_add_adt_audit_data
dbus_bool_t _dbus_credentials_add_adt_audit_data(DBusCredentials *credentials, void *audit_data, dbus_int32_t size)
Add ADT audit data to the credentials.
Definition: dbus-credentials.c:231
_DBUS_N_ELEMENTS
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
Definition: dbus-internals.h:188
_dbus_read_socket_with_unix_fds
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, unsigned int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
Definition: dbus-sysdeps-unix.c:358
_dbus_flush_caches
void _dbus_flush_caches(void)
Called when the bus daemon is signaled to reload its configuration; any caches should be nuked.
Definition: dbus-sysdeps-unix.c:4266
_dbus_connect_exec
int _dbus_connect_exec(const char *path, char *const argv[], DBusError *error)
Creates a UNIX domain socket and connects it to the specified process to execute.
Definition: dbus-sysdeps-unix.c:1014
_dbus_get_tmpdir
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory by inspecting the environment variables TMPDIR,...
Definition: dbus-sysdeps-unix.c:3586
_dbus_string_append_byte
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1157
_DBUS_UNLOCK
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
Definition: dbus-internals.h:373
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
DBUS_GID_UNSET
#define DBUS_GID_UNSET
an invalid GID used to represent an uninitialized dbus_gid_t field
Definition: dbus-sysdeps.h:143
_dbus_geteuid
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
Definition: dbus-sysdeps-unix.c:2751
_dbus_credentials_add_from_current_process
dbus_bool_t _dbus_credentials_add_from_current_process(DBusCredentials *credentials)
Adds the credentials of the current process to the passed-in credentials object.
Definition: dbus-sysdeps-unix.c:2692
TRUE
#define TRUE
Expands to "1".
DBusPollFD::fd
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:399
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition: dbus-internals.h:163
_dbus_credentials_add_pid
dbus_bool_t _dbus_credentials_add_pid(DBusCredentials *credentials, dbus_pid_t pid)
Add a UNIX process ID to the credentials.
Definition: dbus-credentials.c:152
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition: dbus-protocol.h:355
DBusError::name
const char * name
public error name field
Definition: dbus-errors.h:50
READ_END
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:888
DBUS_UID_FORMAT
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:148
_dbus_read_uuid_file
dbus_bool_t _dbus_read_uuid_file(const DBusString *filename, DBusGUID *uuid, dbus_bool_t create_if_not_found, DBusError *error)
Reads (and optionally writes) a uuid to a file.
Definition: dbus-internals.c:846
DBusUserInfo::homedir
char * homedir
Home directory.
Definition: dbus-sysdeps-unix.h:113
_dbus_exit
void _dbus_exit(int code)
Exit the process, returning the given value.
Definition: dbus-sysdeps-unix.c:3220
_dbus_pid_for_log
unsigned long _dbus_pid_for_log(void)
The only reason this is separate from _dbus_getpid() is to allow it on Windows for logging but not fo...
Definition: dbus-sysdeps-unix.c:2763
_dbus_fd_set_close_on_exec
void _dbus_fd_set_close_on_exec(int fd)
Sets the file descriptor to be close on exec.
Definition: dbus-sysdeps-unix.c:3262
_dbus_connect_tcp_socket
DBusSocket _dbus_connect_tcp_socket(const char *host, const char *port, const char *family, DBusError *error)
Creates a socket and connects to a socket at the given host and port.
Definition: dbus-sysdeps-unix.c:1397
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:2847
_dbus_getuid
dbus_uid_t _dbus_getuid(void)
Gets our UID.
Definition: dbus-sysdeps-unix.c:2742
_dbus_init_system_log
void _dbus_init_system_log(const char *tag, DBusLogFlags flags)
Initialize the system log.
Definition: dbus-sysdeps-unix.c:4672
_dbus_generate_random_bytes
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of securely random bytes, using the best mechanism we can come up with.
Definition: dbus-sysdeps-unix.c:3165
_dbus_user_info_fill_uid
dbus_bool_t _dbus_user_info_fill_uid(DBusUserInfo *info, dbus_uid_t uid, DBusError *error)
Gets user info for the given user ID.
Definition: dbus-sysdeps-unix.c:2676
_dbus_set_socket_nonblocking
dbus_bool_t _dbus_set_socket_nonblocking(DBusSocket fd, DBusError *error)
Sets a file descriptor to be nonblocking.
Definition: dbus-sysdeps-unix.c:3354
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition: dbus-protocol.h:357
_dbus_lookup_session_address
dbus_bool_t _dbus_lookup_session_address(dbus_bool_t *supported, DBusString *address, DBusError *error)
Determines the address of the session bus by querying a platform-specific method.
Definition: dbus-sysdeps-unix.c:4234
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3284
_dbus_logv
void _dbus_logv(DBusSystemLogSeverity severity, const char *msg, va_list args)
Log a message to the system log file (e.g.
Definition: dbus-sysdeps-unix.c:4697
FALSE
#define FALSE
Expands to "0".
_dbus_write_uuid_file
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
Definition: dbus-internals.c:797
dbus_set_error_const
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:243
_dbus_string_set_length
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
_DBUS_LOCK
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
Definition: dbus-internals.h:372
_dbus_write_socket
int _dbus_write_socket(DBusSocket fd, const DBusString *buffer, int start, int len)
Like _dbus_write(), but only supports sockets and is thus available on Windows.
Definition: dbus-sysdeps-unix.c:320
_dbus_write_two
int _dbus_write_two(int fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write() but will use writev() if possible to write both buffers in sequence.
Definition: dbus-sysdeps-unix.c:818
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition: dbus-sysdeps-unix.c:2871
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition: dbus-sysdeps-unix.c:3135
_dbus_verbose_bytes_of_string
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
Definition: dbus-marshal-basic.c:1362
WRITE_END
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:890
dbus_gid_t
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:136
dbus_realloc
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:602
_dbus_printf_string_upper_bound
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the length of the given format string and arguments, not including the terminating nul.
Definition: dbus-sysdeps-unix.c:3516
dbus_int32_t
int dbus_int32_t
A 32-bit signed integer on all platforms.
Definition: dbus-arch-deps.h:42
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition: dbus-internals.c:536
_DBUS_ZERO
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
Definition: dbus-internals.h:193
_dbus_credentials_add_unix_uid
dbus_bool_t _dbus_credentials_add_unix_uid(DBusCredentials *credentials, dbus_uid_t uid)
Add a UNIX user ID to the credentials.
Definition: dbus-credentials.c:167
_dbus_socket_can_pass_unix_fd
dbus_bool_t _dbus_socket_can_pass_unix_fd(DBusSocket fd)
Checks whether file descriptors may be passed via the socket.
Definition: dbus-sysdeps-unix.c:4422
_dbus_getenv
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:187
dbus_uid_t
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:134
_dbus_poll
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
Definition: dbus-sysdeps-unix.c:2896
DBusPollFD::revents
short revents
Events that occurred.
Definition: dbus-sysdeps.h:401
_dbus_connect_unix_socket
int _dbus_connect_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and connects it to the UNIX domain socket at the given path.
Definition: dbus-sysdeps-unix.c:917
dbus_error_is_set
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329
_dbus_listen_unix_socket
int _dbus_listen_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
Definition: dbus-sysdeps-unix.c:1120
_dbus_get_real_time
void _dbus_get_real_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
Definition: dbus-sysdeps-unix.c:3005
DBusUserInfo
Information about a UNIX user.
Definition: dbus-sysdeps-unix.h:106
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:411