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

D-Bus 1.12.16

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 if (m.msg_flags & MSG_CTRUNC)
439 {
440 /* Hmm, apparently the control data was truncated. The bad
441 thing is that we might have completely lost a couple of fds
442 without chance to recover them. Hence let's treat this as a
443 serious error. */
444
445 errno = ENOSPC;
446 _dbus_string_set_length (buffer, start);
447 return -1;
448 }
449
450 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
451 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
452 {
453 size_t i;
454 int *payload = (int *) CMSG_DATA (cm);
455 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
456 size_t payload_len_fds = payload_len_bytes / sizeof (int);
457 size_t fds_to_use;
458
459 /* Every unsigned int fits in a size_t without truncation, so
460 * casting (size_t) *n_fds is OK */
461 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
462
463 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
464 {
465 /* The fds in the payload will fit in our buffer */
466 fds_to_use = payload_len_fds;
467 }
468 else
469 {
470 /* Too many fds in the payload. This shouldn't happen
471 * any more because we're setting m.msg_controllen to
472 * the exact number we can accept, but be safe and
473 * truncate. */
474 fds_to_use = (size_t) *n_fds;
475
476 /* Close the excess fds to avoid DoS: if they stayed open,
477 * someone could send us an extra fd per message
478 * and we'd eventually run out. */
479 for (i = fds_to_use; i < payload_len_fds; i++)
480 {
481 close (payload[i]);
482 }
483 }
484
485 memcpy (fds, payload, fds_to_use * sizeof (int));
486 found = TRUE;
487 /* This narrowing cast from size_t to unsigned int cannot
488 * overflow because we have chosen fds_to_use
489 * to be <= *n_fds */
490 *n_fds = (unsigned int) fds_to_use;
491
492 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
493 worked, hence we need to go through this list and set
494 CLOEXEC everywhere in any case */
495 for (i = 0; i < fds_to_use; i++)
496 _dbus_fd_set_close_on_exec(fds[i]);
497
498 break;
499 }
500
501 if (!found)
502 *n_fds = 0;
503
504 /* put length back (doesn't actually realloc) */
505 _dbus_string_set_length (buffer, start + bytes_read);
506
507 #if 0
508 if (bytes_read > 0)
509 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
510 #endif
511
512 return bytes_read;
513 }
514 #endif
515 }
516
517 int
518 _dbus_write_socket_with_unix_fds(DBusSocket fd,
519 const DBusString *buffer,
520 int start,
521 int len,
522 const int *fds,
523 int n_fds) {
524
525 #ifndef HAVE_UNIX_FD_PASSING
526
527 if (n_fds > 0) {
528 errno = ENOTSUP;
529 return -1;
530 }
531
532 return _dbus_write_socket(fd, buffer, start, len);
533 #else
534 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
535 #endif
536 }
537
538 int
539 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
540 const DBusString *buffer1,
541 int start1,
542 int len1,
543 const DBusString *buffer2,
544 int start2,
545 int len2,
546 const int *fds,
547 int n_fds) {
548
549 #ifndef HAVE_UNIX_FD_PASSING
550
551 if (n_fds > 0) {
552 errno = ENOTSUP;
553 return -1;
554 }
555
556 return _dbus_write_socket_two(fd,
557 buffer1, start1, len1,
558 buffer2, start2, len2);
559 #else
560
561 struct msghdr m;
562 struct cmsghdr *cm;
563 struct iovec iov[2];
564 int bytes_written;
565
566 _dbus_assert (len1 >= 0);
567 _dbus_assert (len2 >= 0);
568 _dbus_assert (n_fds >= 0);
569
570 _DBUS_ZERO(iov);
571 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
572 iov[0].iov_len = len1;
573
574 if (buffer2)
575 {
576 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
577 iov[1].iov_len = len2;
578 }
579
580 _DBUS_ZERO(m);
581 m.msg_iov = iov;
582 m.msg_iovlen = buffer2 ? 2 : 1;
583
584 if (n_fds > 0)
585 {
586 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
587 m.msg_control = alloca(m.msg_controllen);
588 memset(m.msg_control, 0, m.msg_controllen);
589
590 cm = CMSG_FIRSTHDR(&m);
591 cm->cmsg_level = SOL_SOCKET;
592 cm->cmsg_type = SCM_RIGHTS;
593 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
594 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
595 }
596
597 again:
598
599 bytes_written = sendmsg (fd.fd, &m, 0
600 #if HAVE_DECL_MSG_NOSIGNAL
601 |MSG_NOSIGNAL
602 #endif
603 );
604
605 if (bytes_written < 0 && errno == EINTR)
606 goto again;
607
608 #if 0
609 if (bytes_written > 0)
610 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
611 #endif
612
613 return bytes_written;
614 #endif
615 }
616
630 int
631 _dbus_write_socket_two (DBusSocket fd,
632 const DBusString *buffer1,
633 int start1,
634 int len1,
635 const DBusString *buffer2,
636 int start2,
637 int len2)
638 {
639 #if HAVE_DECL_MSG_NOSIGNAL
640 struct iovec vectors[2];
641 const char *data1;
642 const char *data2;
643 int bytes_written;
644 struct msghdr m;
645
646 _dbus_assert (buffer1 != NULL);
647 _dbus_assert (start1 >= 0);
648 _dbus_assert (start2 >= 0);
649 _dbus_assert (len1 >= 0);
650 _dbus_assert (len2 >= 0);
651
652 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
653
654 if (buffer2 != NULL)
655 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
656 else
657 {
658 data2 = NULL;
659 start2 = 0;
660 len2 = 0;
661 }
662
663 vectors[0].iov_base = (char*) data1;
664 vectors[0].iov_len = len1;
665 vectors[1].iov_base = (char*) data2;
666 vectors[1].iov_len = len2;
667
668 _DBUS_ZERO(m);
669 m.msg_iov = vectors;
670 m.msg_iovlen = data2 ? 2 : 1;
671
672 again:
673
674 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
675
676 if (bytes_written < 0 && errno == EINTR)
677 goto again;
678
679 return bytes_written;
680
681 #else
682 return _dbus_write_two (fd.fd, buffer1, start1, len1,
683 buffer2, start2, len2);
684 #endif
685 }
686
703 int
704 _dbus_read (int fd,
705 DBusString *buffer,
706 int count)
707 {
708 int bytes_read;
709 int start;
710 char *data;
711
712 _dbus_assert (count >= 0);
713
714 start = _dbus_string_get_length (buffer);
715
716 if (!_dbus_string_lengthen (buffer, count))
717 {
718 errno = ENOMEM;
719 return -1;
720 }
721
722 data = _dbus_string_get_data_len (buffer, start, count);
723
724 again:
725
726 bytes_read = read (fd, data, count);
727
728 if (bytes_read < 0)
729 {
730 if (errno == EINTR)
731 goto again;
732 else
733 {
734 /* put length back (note that this doesn't actually realloc anything) */
735 _dbus_string_set_length (buffer, start);
736 return -1;
737 }
738 }
739 else
740 {
741 /* put length back (doesn't actually realloc) */
742 _dbus_string_set_length (buffer, start + bytes_read);
743
744 #if 0
745 if (bytes_read > 0)
746 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
747 #endif
748
749 return bytes_read;
750 }
751 }
752
763 int
764 _dbus_write (int fd,
765 const DBusString *buffer,
766 int start,
767 int len)
768 {
769 const char *data;
770 int bytes_written;
771
772 data = _dbus_string_get_const_data_len (buffer, start, len);
773
774 again:
775
776 bytes_written = write (fd, data, len);
777
778 if (bytes_written < 0 && errno == EINTR)
779 goto again;
780
781 #if 0
782 if (bytes_written > 0)
783 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
784 #endif
785
786 return bytes_written;
787 }
788
809 int
810 _dbus_write_two (int fd,
811 const DBusString *buffer1,
812 int start1,
813 int len1,
814 const DBusString *buffer2,
815 int start2,
816 int len2)
817 {
818 _dbus_assert (buffer1 != NULL);
819 _dbus_assert (start1 >= 0);
820 _dbus_assert (start2 >= 0);
821 _dbus_assert (len1 >= 0);
822 _dbus_assert (len2 >= 0);
823
824 #ifdef HAVE_WRITEV
825 {
826 struct iovec vectors[2];
827 const char *data1;
828 const char *data2;
829 int bytes_written;
830
831 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
832
833 if (buffer2 != NULL)
834 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
835 else
836 {
837 data2 = NULL;
838 start2 = 0;
839 len2 = 0;
840 }
841
842 vectors[0].iov_base = (char*) data1;
843 vectors[0].iov_len = len1;
844 vectors[1].iov_base = (char*) data2;
845 vectors[1].iov_len = len2;
846
847 again:
848
849 bytes_written = writev (fd,
850 vectors,
851 data2 ? 2 : 1);
852
853 if (bytes_written < 0 && errno == EINTR)
854 goto again;
855
856 return bytes_written;
857 }
858 #else /* HAVE_WRITEV */
859 {
860 int ret1, ret2;
861
862 ret1 = _dbus_write (fd, buffer1, start1, len1);
863 if (ret1 == len1 && buffer2 != NULL)
864 {
865 ret2 = _dbus_write (fd, buffer2, start2, len2);
866 if (ret2 < 0)
867 ret2 = 0; /* we can't report an error as the first write was OK */
868
869 return ret1 + ret2;
870 }
871 else
872 return ret1;
873 }
874 #endif /* !HAVE_WRITEV */
875 }
876
877 #define _DBUS_MAX_SUN_PATH_LENGTH 99
878
908 int
909 _dbus_connect_unix_socket (const char *path,
910 dbus_bool_t abstract,
911 DBusError *error)
912 {
913 int fd;
914 size_t path_len;
915 struct sockaddr_un addr;
916 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
917
918 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
919
920 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
921 path, abstract);
922
923
924 if (!_dbus_open_unix_socket (&fd, error))
925 {
926 _DBUS_ASSERT_ERROR_IS_SET(error);
927 return -1;
928 }
929 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
930
931 _DBUS_ZERO (addr);
932 addr.sun_family = AF_UNIX;
933 path_len = strlen (path);
934
935 if (abstract)
936 {
937 #ifdef __linux__
938 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
939 path_len++; /* Account for the extra nul byte added to the start of sun_path */
940
941 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
942 {
943 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
944 "Abstract socket name too long\n");
945 _dbus_close (fd, NULL);
946 return -1;
947 }
948
949 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
950 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
951 #else /* !__linux__ */
952 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
953 "Operating system does not support abstract socket namespace\n");
954 _dbus_close (fd, NULL);
955 return -1;
956 #endif /* !__linux__ */
957 }
958 else
959 {
960 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
961 {
962 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
963 "Socket name too long\n");
964 _dbus_close (fd, NULL);
965 return -1;
966 }
967
968 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
969 }
970
971 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
972 {
973 dbus_set_error (error,
974 _dbus_error_from_errno (errno),
975 "Failed to connect to socket %s: %s",
976 path, _dbus_strerror (errno));
977
978 _dbus_close (fd, NULL);
979 return -1;
980 }
981
982 if (!_dbus_set_fd_nonblocking (fd, error))
983 {
984 _DBUS_ASSERT_ERROR_IS_SET (error);
985
986 _dbus_close (fd, NULL);
987 return -1;
988 }
989
990 return fd;
991 }
992
1005 int
1006 _dbus_connect_exec (const char *path,
1007 char *const argv[],
1008 DBusError *error)
1009 {
1010 int fds[2];
1011 pid_t pid;
1012 int retval;
1013 dbus_bool_t cloexec_done = 0;
1014
1015 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1016
1017 _dbus_verbose ("connecting to process %s\n", path);
1018
1019 #ifdef SOCK_CLOEXEC
1020 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1021 cloexec_done = (retval >= 0);
1022
1023 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1024 #endif
1025 {
1026 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1027 }
1028
1029 if (retval < 0)
1030 {
1031 dbus_set_error (error,
1032 _dbus_error_from_errno (errno),
1033 "Failed to create socket pair: %s",
1034 _dbus_strerror (errno));
1035 return -1;
1036 }
1037
1038 if (!cloexec_done)
1039 {
1040 _dbus_fd_set_close_on_exec (fds[0]);
1041 _dbus_fd_set_close_on_exec (fds[1]);
1042 }
1043
1044 pid = fork ();
1045 if (pid < 0)
1046 {
1047 dbus_set_error (error,
1048 _dbus_error_from_errno (errno),
1049 "Failed to fork() to call %s: %s",
1050 path, _dbus_strerror (errno));
1051 close (fds[0]);
1052 close (fds[1]);
1053 return -1;
1054 }
1055
1056 if (pid == 0)
1057 {
1058 /* child */
1059 close (fds[0]);
1060
1061 dup2 (fds[1], STDIN_FILENO);
1062 dup2 (fds[1], STDOUT_FILENO);
1063
1064 if (fds[1] != STDIN_FILENO &&
1065 fds[1] != STDOUT_FILENO)
1066 close (fds[1]);
1067
1068 /* Inherit STDERR and the controlling terminal from the
1069 parent */
1070
1071 _dbus_close_all ();
1072
1073 execvp (path, (char * const *) argv);
1074
1075 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1076
1077 _exit(1);
1078 }
1079
1080 /* parent */
1081 close (fds[1]);
1082
1083 if (!_dbus_set_fd_nonblocking (fds[0], error))
1084 {
1085 _DBUS_ASSERT_ERROR_IS_SET (error);
1086
1087 close (fds[0]);
1088 return -1;
1089 }
1090
1091 return fds[0];
1092 }
1093
1111 int
1112 _dbus_listen_unix_socket (const char *path,
1113 dbus_bool_t abstract,
1114 DBusError *error)
1115 {
1116 int listen_fd;
1117 struct sockaddr_un addr;
1118 size_t path_len;
1119 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1120
1121 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1122
1123 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1124 path, abstract);
1125
1126 if (!_dbus_open_unix_socket (&listen_fd, error))
1127 {
1128 _DBUS_ASSERT_ERROR_IS_SET(error);
1129 return -1;
1130 }
1131 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1132
1133 _DBUS_ZERO (addr);
1134 addr.sun_family = AF_UNIX;
1135 path_len = strlen (path);
1136
1137 if (abstract)
1138 {
1139 #ifdef __linux__
1140 /* remember that abstract names aren't nul-terminated so we rely
1141 * on sun_path being filled in with zeroes above.
1142 */
1143 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1144 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1145
1146 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1147 {
1148 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1149 "Abstract socket name too long\n");
1150 _dbus_close (listen_fd, NULL);
1151 return -1;
1152 }
1153
1154 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1155 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1156 #else /* !__linux__ */
1157 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1158 "Operating system does not support abstract socket namespace\n");
1159 _dbus_close (listen_fd, NULL);
1160 return -1;
1161 #endif /* !__linux__ */
1162 }
1163 else
1164 {
1165 /* Discussed security implications of this with Nalin,
1166 * and we couldn't think of where it would kick our ass, but
1167 * it still seems a bit sucky. It also has non-security suckage;
1168 * really we'd prefer to exit if the socket is already in use.
1169 * But there doesn't seem to be a good way to do this.
1170 *
1171 * Just to be extra careful, I threw in the stat() - clearly
1172 * the stat() can't *fix* any security issue, but it at least
1173 * avoids inadvertent/accidental data loss.
1174 */
1175 {
1176 struct stat sb;
1177
1178 if (stat (path, &sb) == 0 &&
1179 S_ISSOCK (sb.st_mode))
1180 unlink (path);
1181 }
1182
1183 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1184 {
1185 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1186 "Socket name too long\n");
1187 _dbus_close (listen_fd, NULL);
1188 return -1;
1189 }
1190
1191 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1192 }
1193
1194 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1195 {
1196 dbus_set_error (error, _dbus_error_from_errno (errno),
1197 "Failed to bind socket \"%s\": %s",
1198 path, _dbus_strerror (errno));
1199 _dbus_close (listen_fd, NULL);
1200 return -1;
1201 }
1202
1203 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1204 {
1205 dbus_set_error (error, _dbus_error_from_errno (errno),
1206 "Failed to listen on socket \"%s\": %s",
1207 path, _dbus_strerror (errno));
1208 _dbus_close (listen_fd, NULL);
1209 return -1;
1210 }
1211
1212 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1213 {
1214 _DBUS_ASSERT_ERROR_IS_SET (error);
1215 _dbus_close (listen_fd, NULL);
1216 return -1;
1217 }
1218
1219 /* Try opening up the permissions, but if we can't, just go ahead
1220 * and continue, maybe it will be good enough.
1221 */
1222 if (!abstract && chmod (path, 0777) < 0)
1223 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1224
1225 return listen_fd;
1226 }
1227
1238 int
1239 _dbus_listen_systemd_sockets (DBusSocket **fds,
1240 DBusError *error)
1241 {
1242 #ifdef HAVE_SYSTEMD
1243 int r, n;
1244 int fd;
1245 DBusSocket *new_fds;
1246
1247 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1248
1249 n = sd_listen_fds (TRUE);
1250 if (n < 0)
1251 {
1252 dbus_set_error (error, _dbus_error_from_errno (-n),
1253 "Failed to acquire systemd socket: %s",
1254 _dbus_strerror (-n));
1255 return -1;
1256 }
1257
1258 if (n <= 0)
1259 {
1260 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1261 "No socket received.");
1262 return -1;
1263 }
1264
1265 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1266 {
1267 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1268 if (r < 0)
1269 {
1270 dbus_set_error (error, _dbus_error_from_errno (-r),
1271 "Failed to verify systemd socket type: %s",
1272 _dbus_strerror (-r));
1273 return -1;
1274 }
1275
1276 if (!r)
1277 {
1278 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1279 "Passed socket has wrong type.");
1280 return -1;
1281 }
1282 }
1283
1284 /* OK, the file descriptors are all good, so let's take posession of
1285 them then. */
1286
1287 new_fds = dbus_new (DBusSocket, n);
1288 if (!new_fds)
1289 {
1290 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1291 "Failed to allocate file handle array.");
1292 goto fail;
1293 }
1294
1295 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1296 {
1297 if (!_dbus_set_fd_nonblocking (fd, error))
1298 {
1299 _DBUS_ASSERT_ERROR_IS_SET (error);
1300 goto fail;
1301 }
1302
1303 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1304 }
1305
1306 *fds = new_fds;
1307 return n;
1308
1309 fail:
1310
1311 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1312 {
1313 _dbus_close (fd, NULL);
1314 }
1315
1316 dbus_free (new_fds);
1317 return -1;
1318 #else
1319 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
1320 "dbus was compiled without systemd support");
1321 return -1;
1322 #endif
1323 }
1324
1325 /* Convert an error code from getaddrinfo() or getnameinfo() into
1326 * a D-Bus error name. */
1327 static const char *
1328 _dbus_error_from_gai (int gai_res,
1329 int saved_errno)
1330 {
1331 switch (gai_res)
1332 {
1333 #ifdef EAI_FAMILY
1334 case EAI_FAMILY:
1335 /* ai_family not supported (at all) */
1336 return DBUS_ERROR_NOT_SUPPORTED;
1337 #endif
1338
1339 #ifdef EAI_SOCKTYPE
1340 case EAI_SOCKTYPE:
1341 /* ai_socktype not supported (at all) */
1342 return DBUS_ERROR_NOT_SUPPORTED;
1343 #endif
1344
1345 #ifdef EAI_MEMORY
1346 case EAI_MEMORY:
1347 /* Out of memory */
1348 return DBUS_ERROR_NO_MEMORY;
1349 #endif
1350
1351 #ifdef EAI_SYSTEM
1352 case EAI_SYSTEM:
1353 /* Unspecified system error, details in errno */
1354 return _dbus_error_from_errno (saved_errno);
1355 #endif
1356
1357 case 0:
1358 /* It succeeded, but we didn't get any addresses? */
1359 return DBUS_ERROR_FAILED;
1360
1361 /* EAI_AGAIN: Transient failure */
1362 /* EAI_BADFLAGS: invalid ai_flags (programming error) */
1363 /* EAI_FAIL: Non-recoverable failure */
1364 /* EAI_NODATA: host exists but has no addresses */
1365 /* EAI_NONAME: host does not exist */
1366 /* EAI_OVERFLOW: argument buffer overflow */
1367 /* EAI_SERVICE: service not available for specified socket
1368 * type (we should never see this because we use numeric
1369 * ports) */
1370 default:
1371 return DBUS_ERROR_FAILED;
1372 }
1373 }
1374
1388 DBusSocket
1389 _dbus_connect_tcp_socket (const char *host,
1390 const char *port,
1391 const char *family,
1392 DBusError *error)
1393 {
1394 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1395 }
1396
1397 DBusSocket
1398 _dbus_connect_tcp_socket_with_nonce (const char *host,
1399 const char *port,
1400 const char *family,
1401 const char *noncefile,
1402 DBusError *error)
1403 {
1404 int saved_errno = 0;
1405 DBusSocket fd = DBUS_SOCKET_INIT;
1406 int res;
1407 struct addrinfo hints;
1408 struct addrinfo *ai, *tmp;
1409
1410 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1411
1412 _DBUS_ZERO (hints);
1413
1414 if (!family)
1415 hints.ai_family = AF_UNSPEC;
1416 else if (!strcmp(family, "ipv4"))
1417 hints.ai_family = AF_INET;
1418 else if (!strcmp(family, "ipv6"))
1419 hints.ai_family = AF_INET6;
1420 else
1421 {
1422 dbus_set_error (error,
1423 DBUS_ERROR_BAD_ADDRESS,
1424 "Unknown address family %s", family);
1425 return _dbus_socket_get_invalid ();
1426 }
1427 hints.ai_protocol = IPPROTO_TCP;
1428 hints.ai_socktype = SOCK_STREAM;
1429 hints.ai_flags = AI_ADDRCONFIG;
1430
1431 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1432 {
1433 dbus_set_error (error,
1434 _dbus_error_from_gai (res, errno),
1435 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1436 host, port, gai_strerror(res), res);
1437 return _dbus_socket_get_invalid ();
1438 }
1439
1440 tmp = ai;
1441 while (tmp)
1442 {
1443 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1444 {
1445 freeaddrinfo(ai);
1446 _DBUS_ASSERT_ERROR_IS_SET(error);
1447 return _dbus_socket_get_invalid ();
1448 }
1449 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1450
1451 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1452 {
1453 saved_errno = errno;
1454 _dbus_close (fd.fd, NULL);
1455 fd.fd = -1;
1456 tmp = tmp->ai_next;
1457 continue;
1458 }
1459
1460 break;
1461 }
1462 freeaddrinfo(ai);
1463
1464 if (fd.fd == -1)
1465 {
1466 dbus_set_error (error,
1467 _dbus_error_from_errno (saved_errno),
1468 "Failed to connect to socket \"%s:%s\" %s",
1469 host, port, _dbus_strerror(saved_errno));
1470 return _dbus_socket_get_invalid ();
1471 }
1472
1473 if (noncefile != NULL)
1474 {
1475 DBusString noncefileStr;
1476 dbus_bool_t ret;
1477 _dbus_string_init_const (&noncefileStr, noncefile);
1478 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1479 _dbus_string_free (&noncefileStr);
1480
1481 if (!ret)
1482 {
1483 _dbus_close (fd.fd, NULL);
1484 return _dbus_socket_get_invalid ();
1485 }
1486 }
1487
1488 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1489 {
1490 _dbus_close (fd.fd, NULL);
1491 return _dbus_socket_get_invalid ();
1492 }
1493
1494 return fd;
1495 }
1496
1513 int
1514 _dbus_listen_tcp_socket (const char *host,
1515 const char *port,
1516 const char *family,
1517 DBusString *retport,
1518 DBusSocket **fds_p,
1519 DBusError *error)
1520 {
1521 int saved_errno;
1522 int nlisten_fd = 0, res, i;
1523 DBusSocket *listen_fd = NULL;
1524 struct addrinfo hints;
1525 struct addrinfo *ai, *tmp;
1526 unsigned int reuseaddr;
1527
1528 *fds_p = NULL;
1529 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1530
1531 _DBUS_ZERO (hints);
1532
1533 if (!family)
1534 hints.ai_family = AF_UNSPEC;
1535 else if (!strcmp(family, "ipv4"))
1536 hints.ai_family = AF_INET;
1537 else if (!strcmp(family, "ipv6"))
1538 hints.ai_family = AF_INET6;
1539 else
1540 {
1541 dbus_set_error (error,
1542 DBUS_ERROR_BAD_ADDRESS,
1543 "Unknown address family %s", family);
1544 return -1;
1545 }
1546
1547 hints.ai_protocol = IPPROTO_TCP;
1548 hints.ai_socktype = SOCK_STREAM;
1549 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1550
1551 redo_lookup_with_port:
1552 ai = NULL;
1553 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1554 {
1555 dbus_set_error (error,
1556 _dbus_error_from_gai (res, errno),
1557 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1558 host ? host : "*", port, gai_strerror(res), res);
1559 goto failed;
1560 }
1561
1562 tmp = ai;
1563 while (tmp)
1564 {
1565 int fd = -1, tcp_nodelay_on;
1566 DBusSocket *newlisten_fd;
1567
1568 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1569 {
1570 _DBUS_ASSERT_ERROR_IS_SET(error);
1571 goto failed;
1572 }
1573 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1574
1575 reuseaddr = 1;
1576 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1577 {
1578 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1579 host ? host : "*", port, _dbus_strerror (errno));
1580 }
1581
1582 /* Nagle's algorithm imposes a huge delay on the initial messages
1583 going over TCP. */
1584 tcp_nodelay_on = 1;
1585 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1586 {
1587 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1588 host ? host : "*", port, _dbus_strerror (errno));
1589 }
1590
1591 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1592 {
1593 saved_errno = errno;
1594 _dbus_close(fd, NULL);
1595 if (saved_errno == EADDRINUSE)
1596 {
1597 /* Depending on kernel policy, binding to an IPv6 address
1598 might implicitly bind to a corresponding IPv4
1599 address or vice versa, resulting in EADDRINUSE for the
1600 other one (e.g. bindv6only=0 on Linux).
1601
1602 Also, after we "goto redo_lookup_with_port" after binding
1603 a port on one of the possible addresses, we will
1604 try to bind that same port on every address, including the
1605 same address again for a second time; that one will
1606 also fail with EADDRINUSE.
1607
1608 For both those reasons, ignore EADDRINUSE here */
1609 tmp = tmp->ai_next;
1610 continue;
1611 }
1612 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1613 "Failed to bind socket \"%s:%s\": %s",
1614 host ? host : "*", port, _dbus_strerror (saved_errno));
1615 goto failed;
1616 }
1617
1618 if (listen (fd, 30 /* backlog */) < 0)
1619 {
1620 saved_errno = errno;
1621 _dbus_close (fd, NULL);
1622 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1623 "Failed to listen on socket \"%s:%s\": %s",
1624 host ? host : "*", port, _dbus_strerror (saved_errno));
1625 goto failed;
1626 }
1627
1628 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1629 if (!newlisten_fd)
1630 {
1631 _dbus_close (fd, NULL);
1632 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1633 "Failed to allocate file handle array");
1634 goto failed;
1635 }
1636 listen_fd = newlisten_fd;
1637 listen_fd[nlisten_fd].fd = fd;
1638 nlisten_fd++;
1639
1640 if (!_dbus_string_get_length(retport))
1641 {
1642 /* If the user didn't specify a port, or used 0, then
1643 the kernel chooses a port. After the first address
1644 is bound to, we need to force all remaining addresses
1645 to use the same port */
1646 if (!port || !strcmp(port, "0"))
1647 {
1648 int result;
1649 struct sockaddr_storage addr;
1650 socklen_t addrlen;
1651 char portbuf[50];
1652
1653 addrlen = sizeof(addr);
1654 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1655
1656 if (result == -1)
1657 {
1658 saved_errno = errno;
1659 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1660 "Failed to retrieve socket name for \"%s:%s\": %s",
1661 host ? host : "*", port, _dbus_strerror (saved_errno));
1662 goto failed;
1663 }
1664
1665 if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1666 portbuf, sizeof(portbuf),
1667 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1668 {
1669 saved_errno = errno;
1670 dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
1671 "Failed to resolve port \"%s:%s\": %s (%d)",
1672 host ? host : "*", port, gai_strerror(res), res);
1673 goto failed;
1674 }
1675
1676 if (!_dbus_string_append(retport, portbuf))
1677 {
1678 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1679 goto failed;
1680 }
1681
1682 /* Release current address list & redo lookup */
1683 port = _dbus_string_get_const_data(retport);
1684 freeaddrinfo(ai);
1685 goto redo_lookup_with_port;
1686 }
1687 else
1688 {
1689 if (!_dbus_string_append(retport, port))
1690 {
1691 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1692 goto failed;
1693 }
1694 }
1695 }
1696
1697 tmp = tmp->ai_next;
1698 }
1699 freeaddrinfo(ai);
1700 ai = NULL;
1701
1702 if (!nlisten_fd)
1703 {
1704 errno = EADDRINUSE;
1705 dbus_set_error (error, _dbus_error_from_errno (errno),
1706 "Failed to bind socket \"%s:%s\": %s",
1707 host ? host : "*", port, _dbus_strerror (errno));
1708 goto failed;
1709 }
1710
1711 for (i = 0 ; i < nlisten_fd ; i++)
1712 {
1713 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1714 {
1715 goto failed;
1716 }
1717 }
1718
1719 *fds_p = listen_fd;
1720
1721 return nlisten_fd;
1722
1723 failed:
1724 if (ai)
1725 freeaddrinfo(ai);
1726 for (i = 0 ; i < nlisten_fd ; i++)
1727 _dbus_close(listen_fd[i].fd, NULL);
1728 dbus_free(listen_fd);
1729 return -1;
1730 }
1731
1732 static dbus_bool_t
1733 write_credentials_byte (int server_fd,
1734 DBusError *error)
1735 {
1736 int bytes_written;
1737 char buf[1] = { '\0' };
1738 #if defined(HAVE_CMSGCRED)
1739 union {
1740 struct cmsghdr hdr;
1741 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1742 } cmsg;
1743 struct iovec iov;
1744 struct msghdr msg;
1745 iov.iov_base = buf;
1746 iov.iov_len = 1;
1747
1748 _DBUS_ZERO(msg);
1749 msg.msg_iov = &iov;
1750 msg.msg_iovlen = 1;
1751
1752 msg.msg_control = (caddr_t) &cmsg;
1753 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1754 _DBUS_ZERO(cmsg);
1755 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1756 cmsg.hdr.cmsg_level = SOL_SOCKET;
1757 cmsg.hdr.cmsg_type = SCM_CREDS;
1758 #endif
1759
1760 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1761
1762 again:
1763
1764 #if defined(HAVE_CMSGCRED)
1765 bytes_written = sendmsg (server_fd, &msg, 0
1766 #if HAVE_DECL_MSG_NOSIGNAL
1767 |MSG_NOSIGNAL
1768 #endif
1769 );
1770
1771 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1772 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1773 * only allows that on AF_UNIX. Try just doing a send() instead. */
1774 if (bytes_written < 0 && errno == EINVAL)
1775 #endif
1776 {
1777 bytes_written = send (server_fd, buf, 1, 0
1778 #if HAVE_DECL_MSG_NOSIGNAL
1779 |MSG_NOSIGNAL
1780 #endif
1781 );
1782 }
1783
1784 if (bytes_written < 0 && errno == EINTR)
1785 goto again;
1786
1787 if (bytes_written < 0)
1788 {
1789 dbus_set_error (error, _dbus_error_from_errno (errno),
1790 "Failed to write credentials byte: %s",
1791 _dbus_strerror (errno));
1792 return FALSE;
1793 }
1794 else if (bytes_written == 0)
1795 {
1796 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1797 "wrote zero bytes writing credentials byte");
1798 return FALSE;
1799 }
1800 else
1801 {
1802 _dbus_assert (bytes_written == 1);
1803 _dbus_verbose ("wrote credentials byte\n");
1804 return TRUE;
1805 }
1806 }
1807
1808 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1809 static dbus_bool_t
1810 add_linux_security_label_to_credentials (int client_fd,
1811 DBusCredentials *credentials)
1812 {
1813 #if defined(__linux__) && defined(SO_PEERSEC)
1814 DBusString buf;
1815 socklen_t len = 1024;
1816 dbus_bool_t oom = FALSE;
1817
1818 if (!_dbus_string_init_preallocated (&buf, len) ||
1819 !_dbus_string_set_length (&buf, len))
1820 return FALSE;
1821
1822 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1823 _dbus_string_get_data (&buf), &len) < 0)
1824 {
1825 int e = errno;
1826
1827 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1828 _dbus_strerror (e), (unsigned long) len);
1829
1830 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1831 {
1832 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1833 _dbus_strerror (e));
1834 goto out;
1835 }
1836
1837 /* If not enough space, len is updated to be enough.
1838 * Try again with a large enough buffer. */
1839 if (!_dbus_string_set_length (&buf, len))
1840 {
1841 oom = TRUE;
1842 goto out;
1843 }
1844
1845 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1846 }
1847
1848 if (len <= 0)
1849 {
1850 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1851 (unsigned long) len);
1852 goto out;
1853 }
1854
1855 if (len > _dbus_string_get_length_uint (&buf))
1856 {
1857 _dbus_verbose ("%lu > %u", (unsigned long) len,
1858 _dbus_string_get_length_uint (&buf));
1859 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1860 }
1861
1862 if (_dbus_string_get_byte (&buf, len - 1) == 0)
1863 {
1864 /* the kernel included the trailing \0 in its count,
1865 * but DBusString always has an extra \0 after the data anyway */
1866 _dbus_verbose ("subtracting trailing \\0\n");
1867 len--;
1868 }
1869
1870 if (!_dbus_string_set_length (&buf, len))
1871 {
1872 _dbus_assert_not_reached ("shortening string should not lead to OOM");
1873 oom = TRUE;
1874 goto out;
1875 }
1876
1877 if (strlen (_dbus_string_get_const_data (&buf)) != len)
1878 {
1879 /* LSM people on the linux-security-module@ mailing list say this
1880 * should never happen: the label should be a bytestring with
1881 * an optional trailing \0 */
1882 _dbus_verbose ("security label from kernel had an embedded \\0, "
1883 "ignoring it\n");
1884 goto out;
1885 }
1886
1887 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1888 (unsigned long) len,
1889 _dbus_string_get_const_data (&buf));
1890
1891 if (!_dbus_credentials_add_linux_security_label (credentials,
1892 _dbus_string_get_const_data (&buf)))
1893 {
1894 oom = TRUE;
1895 goto out;
1896 }
1897
1898 out:
1899 _dbus_string_free (&buf);
1900 return !oom;
1901 #else
1902 /* no error */
1903 return TRUE;
1904 #endif
1905 }
1906
1947 dbus_bool_t
1948 _dbus_read_credentials_socket (DBusSocket client_fd,
1949 DBusCredentials *credentials,
1950 DBusError *error)
1951 {
1952 struct msghdr msg;
1953 struct iovec iov;
1954 char buf;
1955 dbus_uid_t uid_read;
1956 dbus_pid_t pid_read;
1957 int bytes_read;
1958
1959 #ifdef HAVE_CMSGCRED
1960 union {
1961 struct cmsghdr hdr;
1962 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1963 } cmsg;
1964 #endif
1965
1966 /* The POSIX spec certainly doesn't promise this, but
1967 * we need these assertions to fail as soon as we're wrong about
1968 * it so we can do the porting fixups
1969 */
1970 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1971 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1972 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1973
1974 uid_read = DBUS_UID_UNSET;
1975 pid_read = DBUS_PID_UNSET;
1976
1977 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1978
1979 _dbus_credentials_clear (credentials);
1980
1981 iov.iov_base = &buf;
1982 iov.iov_len = 1;
1983
1984 _DBUS_ZERO(msg);
1985 msg.msg_iov = &iov;
1986 msg.msg_iovlen = 1;
1987
1988 #if defined(HAVE_CMSGCRED)
1989 _DBUS_ZERO(cmsg);
1990 msg.msg_control = (caddr_t) &cmsg;
1991 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1992 #endif
1993
1994 again:
1995 bytes_read = recvmsg (client_fd.fd, &msg, 0);
1996
1997 if (bytes_read < 0)
1998 {
1999 if (errno == EINTR)
2000 goto again;
2001
2002 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
2003 * normally only call read_credentials if the socket was ready
2004 * for reading
2005 */
2006
2007 dbus_set_error (error, _dbus_error_from_errno (errno),
2008 "Failed to read credentials byte: %s",
2009 _dbus_strerror (errno));
2010 return FALSE;
2011 }
2012 else if (bytes_read == 0)
2013 {
2014 /* this should not happen unless we are using recvmsg wrong,
2015 * so is essentially here for paranoia
2016 */
2017 dbus_set_error (error, DBUS_ERROR_FAILED,
2018 "Failed to read credentials byte (zero-length read)");
2019 return FALSE;
2020 }
2021 else if (buf != '\0')
2022 {
2023 dbus_set_error (error, DBUS_ERROR_FAILED,
2024 "Credentials byte was not nul");
2025 return FALSE;
2026 }
2027
2028 _dbus_verbose ("read credentials byte\n");
2029
2030 {
2031 #ifdef SO_PEERCRED
2032 /* Supported by at least Linux and OpenBSD, with minor differences.
2033 *
2034 * This mechanism passes the process ID through and does not require
2035 * the peer's cooperation, so we prefer it over all others. Notably,
2036 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
2037 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
2038 * because this is much less fragile.
2039 */
2040 #ifdef __OpenBSD__
2041 struct sockpeercred cr;
2042 #else
2043 struct ucred cr;
2044 #endif
2045 socklen_t cr_len = sizeof (cr);
2046
2047 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
2048 {
2049 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
2050 _dbus_strerror (errno));
2051 }
2052 else if (cr_len != sizeof (cr))
2053 {
2054 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2055 cr_len, (int) sizeof (cr));
2056 }
2057 else
2058 {
2059 pid_read = cr.pid;
2060 uid_read = cr.uid;
2061 }
2062 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2063 /* Another variant of the above - used on NetBSD
2064 */
2065 struct unpcbid cr;
2066 socklen_t cr_len = sizeof (cr);
2067
2068 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2069 {
2070 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2071 _dbus_strerror (errno));
2072 }
2073 else if (cr_len != sizeof (cr))
2074 {
2075 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2076 cr_len, (int) sizeof (cr));
2077 }
2078 else
2079 {
2080 pid_read = cr.unp_pid;
2081 uid_read = cr.unp_euid;
2082 }
2083 #elif defined(HAVE_CMSGCRED)
2084 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2085 * presence of that struct implies SCM_CREDS. Supported by at least
2086 * FreeBSD and DragonflyBSD.
2087 *
2088 * This mechanism requires the peer to help us (it has to send us a
2089 * SCM_CREDS message) but it does pass the process ID through,
2090 * which makes it better than getpeereid().
2091 */
2092 struct cmsgcred *cred;
2093 struct cmsghdr *cmsgp;
2094
2095 for (cmsgp = CMSG_FIRSTHDR (&msg);
2096 cmsgp != NULL;
2097 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2098 {
2099 if (cmsgp->cmsg_type == SCM_CREDS &&
2100 cmsgp->cmsg_level == SOL_SOCKET &&
2101 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2102 {
2103 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2104 pid_read = cred->cmcred_pid;
2105 uid_read = cred->cmcred_euid;
2106 break;
2107 }
2108 }
2109
2110 #elif defined(HAVE_GETPEERUCRED)
2111 /* Supported in at least Solaris >= 10. It should probably be higher
2112 * up this list, because it carries the pid and we use this code path
2113 * for audit data. */
2114 ucred_t * ucred = NULL;
2115 if (getpeerucred (client_fd.fd, &ucred) == 0)
2116 {
2117 #ifdef HAVE_ADT
2118 adt_session_data_t *adth = NULL;
2119 #endif
2120 pid_read = ucred_getpid (ucred);
2121 uid_read = ucred_geteuid (ucred);
2122 #ifdef HAVE_ADT
2123 /* generate audit session data based on socket ucred */
2124 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2125 {
2126 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2127 }
2128 else
2129 {
2130 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2131 {
2132 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2133 }
2134 else
2135 {
2136 adt_export_data_t *data = NULL;
2137 size_t size = adt_export_session_data (adth, &data);
2138 if (size <= 0)
2139 {
2140 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2141 }
2142 else
2143 {
2144 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2145 free (data);
2146 }
2147 }
2148 (void) adt_end_session (adth);
2149 }
2150 #endif /* HAVE_ADT */
2151 }
2152 else
2153 {
2154 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2155 }
2156 if (ucred != NULL)
2157 ucred_free (ucred);
2158
2159 /* ----------------------------------------------------------------
2160 * When adding new mechanisms, please add them above this point
2161 * if they support passing the process ID through, or below if not.
2162 * ---------------------------------------------------------------- */
2163
2164 #elif defined(HAVE_GETPEEREID)
2165 /* getpeereid() originates from D.J. Bernstein and is fairly
2166 * widely-supported. According to a web search, it might be present in
2167 * any/all of:
2168 *
2169 * - AIX?
2170 * - Blackberry?
2171 * - Cygwin
2172 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2173 * - Mac OS X
2174 * - Minix 3.1.8+
2175 * - MirBSD?
2176 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2177 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2178 * - QNX?
2179 */
2180 uid_t euid;
2181 gid_t egid;
2182 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2183 {
2184 uid_read = euid;
2185 }
2186 else
2187 {
2188 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2189 }
2190 #else /* no supported mechanism */
2191
2192 #warning Socket credentials not supported on this Unix OS
2193 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2194
2195 /* Please add other operating systems known to support at least one of
2196 * the mechanisms above to this list, keeping alphabetical order.
2197 * Everything not in this list is best-effort.
2198 */
2199 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2200 defined(__linux__) || \
2201 defined(__OpenBSD__) || \
2202 defined(__NetBSD__)
2203 # error Credentials passing not working on this OS is a regression!
2204 #endif
2205
2206 _dbus_verbose ("Socket credentials not supported on this OS\n");
2207 #endif
2208 }
2209
2210 _dbus_verbose ("Credentials:"
2211 " pid "DBUS_PID_FORMAT
2212 " uid "DBUS_UID_FORMAT
2213 "\n",
2214 pid_read,
2215 uid_read);
2216
2217 if (pid_read != DBUS_PID_UNSET)
2218 {
2219 if (!_dbus_credentials_add_pid (credentials, pid_read))
2220 {
2221 _DBUS_SET_OOM (error);
2222 return FALSE;
2223 }
2224 }
2225
2226 if (uid_read != DBUS_UID_UNSET)
2227 {
2228 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2229 {
2230 _DBUS_SET_OOM (error);
2231 return FALSE;
2232 }
2233 }
2234
2235 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2236 {
2237 _DBUS_SET_OOM (error);
2238 return FALSE;
2239 }
2240
2241 return TRUE;
2242 }
2243
2261 dbus_bool_t
2262 _dbus_send_credentials_socket (DBusSocket server_fd,
2263 DBusError *error)
2264 {
2265 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2266
2267 if (write_credentials_byte (server_fd.fd, error))
2268 return TRUE;
2269 else
2270 return FALSE;
2271 }
2272
2282 DBusSocket
2283 _dbus_accept (DBusSocket listen_fd)
2284 {
2285 DBusSocket client_fd;
2286 struct sockaddr addr;
2287 socklen_t addrlen;
2288 #ifdef HAVE_ACCEPT4
2289 dbus_bool_t cloexec_done;
2290 #endif
2291
2292 addrlen = sizeof (addr);
2293
2294 retry:
2295
2296 #ifdef HAVE_ACCEPT4
2297 /*
2298 * At compile-time, we assume that if accept4() is available in
2299 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2300 * not necessarily true that either is supported by the running kernel.
2301 */
2302 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2303 cloexec_done = client_fd.fd >= 0;
2304
2305 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2306 #endif
2307 {
2308 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2309 }
2310
2311 if (client_fd.fd < 0)
2312 {
2313 if (errno == EINTR)
2314 goto retry;
2315 }
2316
2317 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2318
2319 #ifdef HAVE_ACCEPT4
2320 if (!cloexec_done)
2321 #endif
2322 {
2323 _dbus_fd_set_close_on_exec(client_fd.fd);
2324 }
2325
2326 return client_fd;
2327 }
2328
2337 dbus_bool_t
2338 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2339 {
2340 const char *directory;
2341 struct stat sb;
2342
2343 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2344
2345 directory = _dbus_string_get_const_data (dir);
2346
2347 if (stat (directory, &sb) < 0)
2348 {
2349 dbus_set_error (error, _dbus_error_from_errno (errno),
2350 "%s", _dbus_strerror (errno));
2351
2352 return FALSE;
2353 }
2354
2355 if (sb.st_uid != geteuid ())
2356 {
2357 dbus_set_error (error, DBUS_ERROR_FAILED,
2358 "%s directory is owned by user %lu, not %lu",
2359 directory,
2360 (unsigned long) sb.st_uid,
2361 (unsigned long) geteuid ());
2362 return FALSE;
2363 }
2364
2365 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2366 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2367 {
2368 dbus_set_error (error, DBUS_ERROR_FAILED,
2369 "%s directory is not private to the user", directory);
2370 return FALSE;
2371 }
2372
2373 return TRUE;
2374 }
2375
2376 static dbus_bool_t
2377 fill_user_info_from_passwd (struct passwd *p,
2378 DBusUserInfo *info,
2379 DBusError *error)
2380 {
2381 _dbus_assert (p->pw_name != NULL);
2382 _dbus_assert (p->pw_dir != NULL);
2383
2384 info->uid = p->pw_uid;
2385 info->primary_gid = p->pw_gid;
2386 info->username = _dbus_strdup (p->pw_name);
2387 info->homedir = _dbus_strdup (p->pw_dir);
2388
2389 if (info->username == NULL ||
2390 info->homedir == NULL)
2391 {
2392 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2393 return FALSE;
2394 }
2395
2396 return TRUE;
2397 }
2398
2399 static dbus_bool_t
2400 fill_user_info (DBusUserInfo *info,
2401 dbus_uid_t uid,
2402 const DBusString *username,
2403 DBusError *error)
2404 {
2405 const char *username_c;
2406
2407 /* exactly one of username/uid provided */
2408 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2409 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2410
2411 info->uid = DBUS_UID_UNSET;
2412 info->primary_gid = DBUS_GID_UNSET;
2413 info->group_ids = NULL;
2414 info->n_group_ids = 0;
2415 info->username = NULL;
2416 info->homedir = NULL;
2417
2418 if (username != NULL)
2419 username_c = _dbus_string_get_const_data (username);
2420 else
2421 username_c = NULL;
2422
2423 /* For now assuming that the getpwnam() and getpwuid() flavors
2424 * are always symmetrical, if not we have to add more configure
2425 * checks
2426 */
2427
2428 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2429 {
2430 struct passwd *p;
2431 int result;
2432 size_t buflen;
2433 char *buf;
2434 struct passwd p_str;
2435
2436 /* retrieve maximum needed size for buf */
2437 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2438
2439 /* sysconf actually returns a long, but everything else expects size_t,
2440 * so just recast here.
2441 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2442 */
2443 if ((long) buflen <= 0)
2444 buflen = 1024;
2445
2446 result = -1;
2447 while (1)
2448 {
2449 buf = dbus_malloc (buflen);
2450 if (buf == NULL)
2451 {
2452 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2453 return FALSE;
2454 }
2455
2456 p = NULL;
2457 #ifdef HAVE_POSIX_GETPWNAM_R
2458 if (uid != DBUS_UID_UNSET)
2459 result = getpwuid_r (uid, &p_str, buf, buflen,
2460 &p);
2461 else
2462 result = getpwnam_r (username_c, &p_str, buf, buflen,
2463 &p);
2464 #else
2465 if (uid != DBUS_UID_UNSET)
2466 p = getpwuid_r (uid, &p_str, buf, buflen);
2467 else
2468 p = getpwnam_r (username_c, &p_str, buf, buflen);
2469 result = 0;
2470 #endif /* !HAVE_POSIX_GETPWNAM_R */
2471 //Try a bigger buffer if ERANGE was returned
2472 if (result == ERANGE && buflen < 512 * 1024)
2473 {
2474 dbus_free (buf);
2475 buflen *= 2;
2476 }
2477 else
2478 {
2479 break;
2480 }
2481 }
2482 if (result == 0 && p == &p_str)
2483 {
2484 if (!fill_user_info_from_passwd (p, info, error))
2485 {
2486 dbus_free (buf);
2487 return FALSE;
2488 }
2489 dbus_free (buf);
2490 }
2491 else
2492 {
2493 dbus_set_error (error, _dbus_error_from_errno (errno),
2494 "User \"%s\" unknown or no memory to allocate password entry\n",
2495 username_c ? username_c : "???");
2496 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2497 dbus_free (buf);
2498 return FALSE;
2499 }
2500 }
2501 #else /* ! HAVE_GETPWNAM_R */
2502 {
2503 /* I guess we're screwed on thread safety here */
2504 struct passwd *p;
2505
2506 if (uid != DBUS_UID_UNSET)
2507 p = getpwuid (uid);
2508 else
2509 p = getpwnam (username_c);
2510
2511 if (p != NULL)
2512 {
2513 if (!fill_user_info_from_passwd (p, info, error))
2514 {
2515 return FALSE;
2516 }
2517 }
2518 else
2519 {
2520 dbus_set_error (error, _dbus_error_from_errno (errno),
2521 "User \"%s\" unknown or no memory to allocate password entry\n",
2522 username_c ? username_c : "???");
2523 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2524 return FALSE;
2525 }
2526 }
2527 #endif /* ! HAVE_GETPWNAM_R */
2528
2529 /* Fill this in so we can use it to get groups */
2530 username_c = info->username;
2531
2532 #ifdef HAVE_GETGROUPLIST
2533 {
2534 gid_t *buf;
2535 int buf_count;
2536 int i;
2537 int initial_buf_count;
2538
2539 initial_buf_count = 17;
2540 buf_count = initial_buf_count;
2541 buf = dbus_new (gid_t, buf_count);
2542 if (buf == NULL)
2543 {
2544 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2545 goto failed;
2546 }
2547
2548 if (getgrouplist (username_c,
2549 info->primary_gid,
2550 buf, &buf_count) < 0)
2551 {
2552 gid_t *new;
2553 /* Presumed cause of negative return code: buf has insufficient
2554 entries to hold the entire group list. The Linux behavior in this
2555 case is to pass back the actual number of groups in buf_count, but
2556 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2557 So as a hack, try to help out a bit by guessing a larger
2558 number of groups, within reason.. might still fail, of course,
2559 but we can at least print a more informative message. I looked up
2560 the "right way" to do this by downloading Apple's own source code
2561 for the "id" command, and it turns out that they use an
2562 undocumented library function getgrouplist_2 (!) which is not
2563 declared in any header in /usr/include (!!). That did not seem
2564 like the way to go here.
2565 */
2566 if (buf_count == initial_buf_count)
2567 {
2568 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2569 }
2570 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2571 if (new == NULL)
2572 {
2573 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2574 dbus_free (buf);
2575 goto failed;
2576 }
2577
2578 buf = new;
2579
2580 errno = 0;
2581 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2582 {
2583 if (errno == 0)
2584 {
2585 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2586 username_c, buf_count, buf_count);
2587 }
2588 else
2589 {
2590 dbus_set_error (error,
2591 _dbus_error_from_errno (errno),
2592 "Failed to get groups for username \"%s\" primary GID "
2593 DBUS_GID_FORMAT ": %s\n",
2594 username_c, info->primary_gid,
2595 _dbus_strerror (errno));
2596 dbus_free (buf);
2597 goto failed;
2598 }
2599 }
2600 }
2601
2602 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2603 if (info->group_ids == NULL)
2604 {
2605 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2606 dbus_free (buf);
2607 goto failed;
2608 }
2609
2610 for (i = 0; i < buf_count; ++i)
2611 info->group_ids[i] = buf[i];
2612
2613 info->n_group_ids = buf_count;
2614
2615 dbus_free (buf);
2616 }
2617 #else /* HAVE_GETGROUPLIST */
2618 {
2619 /* We just get the one group ID */
2620 info->group_ids = dbus_new (dbus_gid_t, 1);
2621 if (info->group_ids == NULL)
2622 {
2623 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2624 goto failed;
2625 }
2626
2627 info->n_group_ids = 1;
2628
2629 (info->group_ids)[0] = info->primary_gid;
2630 }
2631 #endif /* HAVE_GETGROUPLIST */
2632
2633 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2634
2635 return TRUE;
2636
2637 failed:
2638 _DBUS_ASSERT_ERROR_IS_SET (error);
2639 return FALSE;
2640 }
2641
2650 dbus_bool_t
2651 _dbus_user_info_fill (DBusUserInfo *info,
2652 const DBusString *username,
2653 DBusError *error)
2654 {
2655 return fill_user_info (info, DBUS_UID_UNSET,
2656 username, error);
2657 }
2658
2667 dbus_bool_t
2668 _dbus_user_info_fill_uid (DBusUserInfo *info,
2669 dbus_uid_t uid,
2670 DBusError *error)
2671 {
2672 return fill_user_info (info, uid,
2673 NULL, error);
2674 }
2675
2683 dbus_bool_t
2684 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2685 {
2686 /* The POSIX spec certainly doesn't promise this, but
2687 * we need these assertions to fail as soon as we're wrong about
2688 * it so we can do the porting fixups
2689 */
2690 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2691 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2692 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2693
2694 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2695 return FALSE;
2696 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2697 return FALSE;
2698
2699 return TRUE;
2700 }
2701
2713 dbus_bool_t
2714 _dbus_append_user_from_current_process (DBusString *str)
2715 {
2716 return _dbus_string_append_uint (str,
2717 _dbus_geteuid ());
2718 }
2719
2724 dbus_pid_t
2725 _dbus_getpid (void)
2726 {
2727 return getpid ();
2728 }
2729
2733 dbus_uid_t
2734 _dbus_getuid (void)
2735 {
2736 return getuid ();
2737 }
2738
2742 dbus_uid_t
2743 _dbus_geteuid (void)
2744 {
2745 return geteuid ();
2746 }
2747
2754 unsigned long
2755 _dbus_pid_for_log (void)
2756 {
2757 return getpid ();
2758 }
2759
2767 dbus_bool_t
2768 _dbus_parse_uid (const DBusString *uid_str,
2769 dbus_uid_t *uid)
2770 {
2771 int end;
2772 long val;
2773
2774 if (_dbus_string_get_length (uid_str) == 0)
2775 {
2776 _dbus_verbose ("UID string was zero length\n");
2777 return FALSE;
2778 }
2779
2780 val = -1;
2781 end = 0;
2782 if (!_dbus_string_parse_int (uid_str, 0, &val,
2783 &end))
2784 {
2785 _dbus_verbose ("could not parse string as a UID\n");
2786 return FALSE;
2787 }
2788
2789 if (end != _dbus_string_get_length (uid_str))
2790 {
2791 _dbus_verbose ("string contained trailing stuff after UID\n");
2792 return FALSE;
2793 }
2794
2795 *uid = val;
2796
2797 return TRUE;
2798 }
2799
2800 #if !DBUS_USE_SYNC
2801 /* To be thread-safe by default on platforms that don't necessarily have
2802 * atomic operations (notably Debian armel, which is armv4t), we must
2803 * use a mutex that can be initialized statically, like this.
2804 * GLib >= 2.32 uses a similar system.
2805 */
2806 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2807 #endif
2808
2815 dbus_int32_t
2816 _dbus_atomic_inc (DBusAtomic *atomic)
2817 {
2818 #if DBUS_USE_SYNC
2819 return __sync_add_and_fetch(&atomic->value, 1)-1;
2820 #else
2821 dbus_int32_t res;
2822
2823 pthread_mutex_lock (&atomic_mutex);
2824 res = atomic->value;
2825 atomic->value += 1;
2826 pthread_mutex_unlock (&atomic_mutex);
2827
2828 return res;
2829 #endif
2830 }
2831
2838 dbus_int32_t
2839 _dbus_atomic_dec (DBusAtomic *atomic)
2840 {
2841 #if DBUS_USE_SYNC
2842 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2843 #else
2844 dbus_int32_t res;
2845
2846 pthread_mutex_lock (&atomic_mutex);
2847 res = atomic->value;
2848 atomic->value -= 1;
2849 pthread_mutex_unlock (&atomic_mutex);
2850
2851 return res;
2852 #endif
2853 }
2854
2862 dbus_int32_t
2863 _dbus_atomic_get (DBusAtomic *atomic)
2864 {
2865 #if DBUS_USE_SYNC
2866 __sync_synchronize ();
2867 return atomic->value;
2868 #else
2869 dbus_int32_t res;
2870
2871 pthread_mutex_lock (&atomic_mutex);
2872 res = atomic->value;
2873 pthread_mutex_unlock (&atomic_mutex);
2874
2875 return res;
2876 #endif
2877 }
2878
2887 int
2888 _dbus_poll (DBusPollFD *fds,
2889 int n_fds,
2890 int timeout_milliseconds)
2891 {
2892 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2893 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2894 if (timeout_milliseconds < -1)
2895 {
2896 timeout_milliseconds = -1;
2897 }
2898
2899 return poll (fds,
2900 n_fds,
2901 timeout_milliseconds);
2902 #else /* ! HAVE_POLL */
2903 /* Emulate poll() in terms of select() */
2904 fd_set read_set, write_set, err_set;
2905 int max_fd = 0;
2906 int i;
2907 struct timeval tv;
2908 int ready;
2909
2910 FD_ZERO (&read_set);
2911 FD_ZERO (&write_set);
2912 FD_ZERO (&err_set);
2913
2914 for (i = 0; i < n_fds; i++)
2915 {
2916 DBusPollFD *fdp = &fds[i];
2917
2918 if (fdp->events & _DBUS_POLLIN)
2919 FD_SET (fdp->fd, &read_set);
2920
2921 if (fdp->events & _DBUS_POLLOUT)
2922 FD_SET (fdp->fd, &write_set);
2923
2924 FD_SET (fdp->fd, &err_set);
2925
2926 max_fd = MAX (max_fd, fdp->fd);
2927 }
2928
2929 tv.tv_sec = timeout_milliseconds / 1000;
2930 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2931
2932 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2933 timeout_milliseconds < 0 ? NULL : &tv);
2934
2935 if (ready > 0)
2936 {
2937 for (i = 0; i < n_fds; i++)
2938 {
2939 DBusPollFD *fdp = &fds[i];
2940
2941 fdp->revents = 0;
2942
2943 if (FD_ISSET (fdp->fd, &read_set))
2944 fdp->revents |= _DBUS_POLLIN;
2945
2946 if (FD_ISSET (fdp->fd, &write_set))
2947 fdp->revents |= _DBUS_POLLOUT;
2948
2949 if (FD_ISSET (fdp->fd, &err_set))
2950 fdp->revents |= _DBUS_POLLERR;
2951 }
2952 }
2953
2954 return ready;
2955 #endif
2956 }
2957
2965 void
2966 _dbus_get_monotonic_time (long *tv_sec,
2967 long *tv_usec)
2968 {
2969 #ifdef HAVE_MONOTONIC_CLOCK
2970 struct timespec ts;
2971 clock_gettime (CLOCK_MONOTONIC, &ts);
2972
2973 if (tv_sec)
2974 *tv_sec = ts.tv_sec;
2975 if (tv_usec)
2976 *tv_usec = ts.tv_nsec / 1000;
2977 #else
2978 struct timeval t;
2979
2980 gettimeofday (&t, NULL);
2981
2982 if (tv_sec)
2983 *tv_sec = t.tv_sec;
2984 if (tv_usec)
2985 *tv_usec = t.tv_usec;
2986 #endif
2987 }
2988
2996 void
2997 _dbus_get_real_time (long *tv_sec,
2998 long *tv_usec)
2999 {
3000 struct timeval t;
3001
3002 gettimeofday (&t, NULL);
3003
3004 if (tv_sec)
3005 *tv_sec = t.tv_sec;
3006 if (tv_usec)
3007 *tv_usec = t.tv_usec;
3008 }
3009
3018 dbus_bool_t
3019 _dbus_ensure_directory (const DBusString *filename,
3020 DBusError *error)
3021 {
3022 const char *filename_c;
3023
3024 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3025
3026 filename_c = _dbus_string_get_const_data (filename);
3027
3028 if (mkdir (filename_c, 0700) < 0)
3029 {
3030 if (errno == EEXIST)
3031 return TRUE;
3032
3033 dbus_set_error (error, DBUS_ERROR_FAILED,
3034 "Failed to create directory %s: %s\n",
3035 filename_c, _dbus_strerror (errno));
3036 return FALSE;
3037 }
3038 else
3039 return TRUE;
3040 }
3041
3050 dbus_bool_t
3051 _dbus_create_directory (const DBusString *filename,
3052 DBusError *error)
3053 {
3054 const char *filename_c;
3055
3056 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3057
3058 filename_c = _dbus_string_get_const_data (filename);
3059
3060 if (mkdir (filename_c, 0700) < 0)
3061 {
3062 dbus_set_error (error, DBUS_ERROR_FAILED,
3063 "Failed to create directory %s: %s\n",
3064 filename_c, _dbus_strerror (errno));
3065 return FALSE;
3066 }
3067 else
3068 return TRUE;
3069 }
3070
3081 dbus_bool_t
3082 _dbus_concat_dir_and_file (DBusString *dir,
3083 const DBusString *next_component)
3084 {
3085 dbus_bool_t dir_ends_in_slash;
3086 dbus_bool_t file_starts_with_slash;
3087
3088 if (_dbus_string_get_length (dir) == 0 ||
3089 _dbus_string_get_length (next_component) == 0)
3090 return TRUE;
3091
3092 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3093 _dbus_string_get_length (dir) - 1);
3094
3095 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3096
3097 if (dir_ends_in_slash && file_starts_with_slash)
3098 {
3099 _dbus_string_shorten (dir, 1);
3100 }
3101 else if (!(dir_ends_in_slash || file_starts_with_slash))
3102 {
3103 if (!_dbus_string_append_byte (dir, '/'))
3104 return FALSE;
3105 }
3106
3107 return _dbus_string_copy (next_component, 0, dir,
3108 _dbus_string_get_length (dir));
3109 }
3110
3112 #define NANOSECONDS_PER_SECOND 1000000000
3113
3114 #define MICROSECONDS_PER_SECOND 1000000
3115
3116 #define MILLISECONDS_PER_SECOND 1000
3117
3118 #define NANOSECONDS_PER_MILLISECOND 1000000
3119
3120 #define MICROSECONDS_PER_MILLISECOND 1000
3121
3126 void
3127 _dbus_sleep_milliseconds (int milliseconds)
3128 {
3129 #ifdef HAVE_NANOSLEEP
3130 struct timespec req;
3131 struct timespec rem;
3132
3133 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3134 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3135 rem.tv_sec = 0;
3136 rem.tv_nsec = 0;
3137
3138 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3139 req = rem;
3140 #elif defined (HAVE_USLEEP)
3141 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3142 #else /* ! HAVE_USLEEP */
3143 sleep (MAX (milliseconds / 1000, 1));
3144 #endif
3145 }
3146
3156 dbus_bool_t
3157 _dbus_generate_random_bytes (DBusString *str,
3158 int n_bytes,
3159 DBusError *error)
3160 {
3161 int old_len;
3162 int fd;
3163 int result;
3164
3165 old_len = _dbus_string_get_length (str);
3166 fd = -1;
3167
3168 /* note, urandom on linux will fall back to pseudorandom */
3169 fd = open ("/dev/urandom", O_RDONLY);
3170
3171 if (fd < 0)
3172 {
3173 dbus_set_error (error, _dbus_error_from_errno (errno),
3174 "Could not open /dev/urandom: %s",
3175 _dbus_strerror (errno));
3176 return FALSE;
3177 }
3178
3179 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3180
3181 result = _dbus_read (fd, str, n_bytes);
3182
3183 if (result != n_bytes)
3184 {
3185 if (result < 0)
3186 dbus_set_error (error, _dbus_error_from_errno (errno),
3187 "Could not read /dev/urandom: %s",
3188 _dbus_strerror (errno));
3189 else
3190 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
3191 "Short read from /dev/urandom");
3192
3193 _dbus_close (fd, NULL);
3194 _dbus_string_set_length (str, old_len);
3195 return FALSE;
3196 }
3197
3198 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3199 n_bytes);
3200
3201 _dbus_close (fd, NULL);
3202
3203 return TRUE;
3204 }
3205
3211 void
3212 _dbus_exit (int code)
3213 {
3214 _exit (code);
3215 }
3216
3225 const char*
3226 _dbus_strerror (int error_number)
3227 {
3228 const char *msg;
3229
3230 msg = strerror (error_number);
3231 if (msg == NULL)
3232 msg = "unknown";
3233
3234 return msg;
3235 }
3236
3240 void
3241 _dbus_disable_sigpipe (void)
3242 {
3243 signal (SIGPIPE, SIG_IGN);
3244 }
3245
3253 void
3254 _dbus_fd_set_close_on_exec (int fd)
3255 {
3256 int val;
3257
3258 val = fcntl (fd, F_GETFD, 0);
3259
3260 if (val < 0)
3261 return;
3262
3263 val |= FD_CLOEXEC;
3264
3265 fcntl (fd, F_SETFD, val);
3266 }
3267
3275 dbus_bool_t
3276 _dbus_close (int fd,
3277 DBusError *error)
3278 {
3279 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3280
3281 again:
3282 if (close (fd) < 0)
3283 {
3284 if (errno == EINTR)
3285 goto again;
3286
3287 dbus_set_error (error, _dbus_error_from_errno (errno),
3288 "Could not close fd %d", fd);
3289 return FALSE;
3290 }
3291
3292 return TRUE;
3293 }
3294
3303 int
3304 _dbus_dup(int fd,
3305 DBusError *error)
3306 {
3307 int new_fd;
3308
3309 #ifdef F_DUPFD_CLOEXEC
3310 dbus_bool_t cloexec_done;
3311
3312 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3313 cloexec_done = new_fd >= 0;
3314
3315 if (new_fd < 0 && errno == EINVAL)
3316 #endif
3317 {
3318 new_fd = fcntl(fd, F_DUPFD, 3);
3319 }
3320
3321 if (new_fd < 0) {
3322
3323 dbus_set_error (error, _dbus_error_from_errno (errno),
3324 "Could not duplicate fd %d", fd);
3325 return -1;
3326 }
3327
3328 #ifdef F_DUPFD_CLOEXEC
3329 if (!cloexec_done)
3330 #endif
3331 {
3332 _dbus_fd_set_close_on_exec(new_fd);
3333 }
3334
3335 return new_fd;
3336 }
3337
3345 dbus_bool_t
3346 _dbus_set_socket_nonblocking (DBusSocket fd,
3347 DBusError *error)
3348 {
3349 return _dbus_set_fd_nonblocking (fd.fd, error);
3350 }
3351
3352 static dbus_bool_t
3353 _dbus_set_fd_nonblocking (int fd,
3354 DBusError *error)
3355 {
3356 int val;
3357
3358 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3359
3360 val = fcntl (fd, F_GETFL, 0);
3361 if (val < 0)
3362 {
3363 dbus_set_error (error, _dbus_error_from_errno (errno),
3364 "Failed to get flags from file descriptor %d: %s",
3365 fd, _dbus_strerror (errno));
3366 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3367 _dbus_strerror (errno));
3368 return FALSE;
3369 }
3370
3371 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3372 {
3373 dbus_set_error (error, _dbus_error_from_errno (errno),
3374 "Failed to set nonblocking flag of file descriptor %d: %s",
3375 fd, _dbus_strerror (errno));
3376 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3377 fd, _dbus_strerror (errno));
3378
3379 return FALSE;
3380 }
3381
3382 return TRUE;
3383 }
3384
3390 void
3391 _dbus_print_backtrace (void)
3392 {
3393 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3394 void *bt[500];
3395 int bt_size;
3396 int i;
3397 char **syms;
3398
3399 bt_size = backtrace (bt, 500);
3400
3401 syms = backtrace_symbols (bt, bt_size);
3402
3403 i = 0;
3404 while (i < bt_size)
3405 {
3406 /* don't use dbus_warn since it can _dbus_abort() */
3407 fprintf (stderr, " %s\n", syms[i]);
3408 ++i;
3409 }
3410 fflush (stderr);
3411
3412 free (syms);
3413 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3414 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3415 #else
3416 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3417 #endif
3418 }
3419
3432 dbus_bool_t
3433 _dbus_socketpair (DBusSocket *fd1,
3434 DBusSocket *fd2,
3435 dbus_bool_t blocking,
3436 DBusError *error)
3437 {
3438 #ifdef HAVE_SOCKETPAIR
3439 int fds[2];
3440 int retval;
3441
3442 #ifdef SOCK_CLOEXEC
3443 dbus_bool_t cloexec_done;
3444
3445 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3446 cloexec_done = retval >= 0;
3447
3448 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3449 #endif
3450 {
3451 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3452 }
3453
3454 if (retval < 0)
3455 {
3456 dbus_set_error (error, _dbus_error_from_errno (errno),
3457 "Could not create full-duplex pipe");
3458 return FALSE;
3459 }
3460
3461 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3462
3463 #ifdef SOCK_CLOEXEC
3464 if (!cloexec_done)
3465 #endif
3466 {
3467 _dbus_fd_set_close_on_exec (fds[0]);
3468 _dbus_fd_set_close_on_exec (fds[1]);
3469 }
3470
3471 if (!blocking &&
3472 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3473 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3474 {
3475 dbus_set_error (error, _dbus_error_from_errno (errno),
3476 "Could not set full-duplex pipe nonblocking");
3477
3478 _dbus_close (fds[0], NULL);
3479 _dbus_close (fds[1], NULL);
3480
3481 return FALSE;
3482 }
3483
3484 fd1->fd = fds[0];
3485 fd2->fd = fds[1];
3486
3487 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3488 fd1->fd, fd2->fd);
3489
3490 return TRUE;
3491 #else
3492 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3493 dbus_set_error (error, DBUS_ERROR_FAILED,
3494 "_dbus_socketpair() not implemented on this OS");
3495 return FALSE;
3496 #endif
3497 }
3498
3507 int
3508 _dbus_printf_string_upper_bound (const char *format,
3509 va_list args)
3510 {
3511 char static_buf[1024];
3512 int bufsize = sizeof (static_buf);
3513 int len;
3514 va_list args_copy;
3515
3516 DBUS_VA_COPY (args_copy, args);
3517 len = vsnprintf (static_buf, bufsize, format, args_copy);
3518 va_end (args_copy);
3519
3520 /* If vsnprintf() returned non-negative, then either the string fits in
3521 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3522 * returns the number of characters that were needed, or this OS returns the
3523 * truncated length.
3524 *
3525 * We ignore the possibility that snprintf might just ignore the length and
3526 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3527 * If your libc is really that bad, come back when you have a better one. */
3528 if (len == bufsize)
3529 {
3530 /* This could be the truncated length (Tru64 and IRIX have this bug),
3531 * or the real length could be coincidentally the same. Which is it?
3532 * If vsnprintf returns the truncated length, we'll go to the slow
3533 * path. */
3534 DBUS_VA_COPY (args_copy, args);
3535
3536 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3537 len = -1;
3538
3539 va_end (args_copy);
3540 }
3541
3542 /* If vsnprintf() returned negative, we have to do more work.
3543 * HP-UX returns negative. */
3544 while (len < 0)
3545 {
3546 char *buf;
3547
3548 bufsize *= 2;
3549
3550 buf = dbus_malloc (bufsize);
3551
3552 if (buf == NULL)
3553 return -1;
3554
3555 DBUS_VA_COPY (args_copy, args);
3556 len = vsnprintf (buf, bufsize, format, args_copy);
3557 va_end (args_copy);
3558
3559 dbus_free (buf);
3560
3561 /* If the reported length is exactly the buffer size, round up to the
3562 * next size, in case vsnprintf has been returning the truncated
3563 * length */
3564 if (len == bufsize)
3565 len = -1;
3566 }
3567
3568 return len;
3569 }
3570
3577 const char*
3578 _dbus_get_tmpdir(void)
3579 {
3580 /* Protected by _DBUS_LOCK_sysdeps */
3581 static const char* tmpdir = NULL;
3582
3583 if (!_DBUS_LOCK (sysdeps))
3584 return NULL;
3585
3586 if (tmpdir == NULL)
3587 {
3588 /* TMPDIR is what glibc uses, then
3589 * glibc falls back to the P_tmpdir macro which
3590 * just expands to "/tmp"
3591 */
3592 if (tmpdir == NULL)
3593 tmpdir = getenv("TMPDIR");
3594
3595 /* These two env variables are probably
3596 * broken, but maybe some OS uses them?
3597 */
3598 if (tmpdir == NULL)
3599 tmpdir = getenv("TMP");
3600 if (tmpdir == NULL)
3601 tmpdir = getenv("TEMP");
3602
3603 /* And this is the sane fallback. */
3604 if (tmpdir == NULL)
3605 tmpdir = "/tmp";
3606 }
3607
3608 _DBUS_UNLOCK (sysdeps);
3609
3610 _dbus_assert(tmpdir != NULL);
3611
3612 return tmpdir;
3613 }
3614
3615 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3616
3635 static dbus_bool_t
3636 _read_subprocess_line_argv (const char *progpath,
3637 dbus_bool_t path_fallback,
3638 const char * const *argv,
3639 DBusString *result,
3640 DBusError *error)
3641 {
3642 int result_pipe[2] = { -1, -1 };
3643 int errors_pipe[2] = { -1, -1 };
3644 pid_t pid;
3645 int ret;
3646 int status;
3647 int orig_len;
3648
3649 dbus_bool_t retval;
3650 sigset_t new_set, old_set;
3651
3652 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3653 retval = FALSE;
3654
3655 /* We need to block any existing handlers for SIGCHLD temporarily; they
3656 * will cause waitpid() below to fail.
3657 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3658 */
3659 sigemptyset (&new_set);
3660 sigaddset (&new_set, SIGCHLD);
3661 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3662
3663 orig_len = _dbus_string_get_length (result);
3664
3665 #define READ_END 0
3666 #define WRITE_END 1
3667 if (pipe (result_pipe) < 0)
3668 {
3669 dbus_set_error (error, _dbus_error_from_errno (errno),
3670 "Failed to create a pipe to call %s: %s",
3671 progpath, _dbus_strerror (errno));
3672 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3673 progpath, _dbus_strerror (errno));
3674 goto out;
3675 }
3676 if (pipe (errors_pipe) < 0)
3677 {
3678 dbus_set_error (error, _dbus_error_from_errno (errno),
3679 "Failed to create a pipe to call %s: %s",
3680 progpath, _dbus_strerror (errno));
3681 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3682 progpath, _dbus_strerror (errno));
3683 goto out;
3684 }
3685
3686 pid = fork ();
3687 if (pid < 0)
3688 {
3689 dbus_set_error (error, _dbus_error_from_errno (errno),
3690 "Failed to fork() to call %s: %s",
3691 progpath, _dbus_strerror (errno));
3692 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3693 progpath, _dbus_strerror (errno));
3694 goto out;
3695 }
3696
3697 if (pid == 0)
3698 {
3699 /* child process */
3700 const char *error_str;
3701
3702 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
3703 {
3704 int saved_errno = errno;
3705
3706 /* Try to write details into the pipe, but don't bother
3707 * trying too hard (no retry loop). */
3708
3709 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
3710 write (errors_pipe[WRITE_END], ": ", 2) < 0)
3711 {
3712 /* ignore, not much we can do */
3713 }
3714
3715 error_str = _dbus_strerror (saved_errno);
3716
3717 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
3718 {
3719 /* ignore, not much we can do */
3720 }
3721
3722 _exit (1);
3723 }
3724
3725 /* set-up stdXXX */
3726 close (result_pipe[READ_END]);
3727 close (errors_pipe[READ_END]);
3728
3729 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3730 _exit (1);
3731 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3732 _exit (1);
3733
3734 _dbus_close_all ();
3735
3736 sigprocmask (SIG_SETMASK, &old_set, NULL);
3737
3738 /* If it looks fully-qualified, try execv first */
3739 if (progpath[0] == '/')
3740 {
3741 execv (progpath, (char * const *) argv);
3742 /* Ok, that failed. Now if path_fallback is given, let's
3743 * try unqualified. This is mostly a hack to work
3744 * around systems which ship dbus-launch in /usr/bin
3745 * but everything else in /bin (because dbus-launch
3746 * depends on X11).
3747 */
3748 if (path_fallback)
3749 /* We must have a slash, because we checked above */
3750 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
3751 }
3752 else
3753 execvp (progpath, (char * const *) argv);
3754
3755 /* still nothing, we failed */
3756 _exit (1);
3757 }
3758
3759 /* parent process */
3760 close (result_pipe[WRITE_END]);
3761 close (errors_pipe[WRITE_END]);
3762 result_pipe[WRITE_END] = -1;
3763 errors_pipe[WRITE_END] = -1;
3764
3765 ret = 0;
3766 do
3767 {
3768 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3769 }
3770 while (ret > 0);
3771
3772 /* reap the child process to avoid it lingering as zombie */
3773 do
3774 {
3775 ret = waitpid (pid, &status, 0);
3776 }
3777 while (ret == -1 && errno == EINTR);
3778
3779 /* We succeeded if the process exited with status 0 and
3780 anything was read */
3781 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3782 {
3783 /* The process ended with error */
3784 DBusString error_message;
3785 if (!_dbus_string_init (&error_message))
3786 {
3787 _DBUS_SET_OOM (error);
3788 goto out;
3789 }
3790
3791 ret = 0;
3792 do
3793 {
3794 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3795 }
3796 while (ret > 0);
3797
3798 _dbus_string_set_length (result, orig_len);
3799 if (_dbus_string_get_length (&error_message) > 0)
3800 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3801 "%s terminated abnormally with the following error: %s",
3802 progpath, _dbus_string_get_data (&error_message));
3803 else
3804 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3805 "%s terminated abnormally without any error message",
3806 progpath);
3807 goto out;
3808 }
3809
3810 retval = TRUE;
3811
3812 out:
3813 sigprocmask (SIG_SETMASK, &old_set, NULL);
3814
3815 if (retval)
3816 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3817 else
3818 _DBUS_ASSERT_ERROR_IS_SET (error);
3819
3820 if (result_pipe[0] != -1)
3821 close (result_pipe[0]);
3822 if (result_pipe[1] != -1)
3823 close (result_pipe[1]);
3824 if (errors_pipe[0] != -1)
3825 close (errors_pipe[0]);
3826 if (errors_pipe[1] != -1)
3827 close (errors_pipe[1]);
3828
3829 return retval;
3830 }
3831 #endif
3832
3845 dbus_bool_t
3846 _dbus_get_autolaunch_address (const char *scope,
3847 DBusString *address,
3848 DBusError *error)
3849 {
3850 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3851 static const char arg_dbus_launch[] = "dbus-launch";
3852 static const char arg_autolaunch[] = "--autolaunch";
3853 static const char arg_binary_syntax[] = "--binary-syntax";
3854 static const char arg_close_stderr[] = "--close-stderr";
3855
3856 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3857 * but that's done elsewhere, and if it worked, this function wouldn't
3858 * be called.) */
3859 const char *display;
3860 const char *progpath;
3861 const char *argv[6];
3862 int i;
3863 DBusString uuid;
3864 dbus_bool_t retval;
3865
3866 if (_dbus_check_setuid ())
3867 {
3868 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3869 "Unable to autolaunch when setuid");
3870 return FALSE;
3871 }
3872
3873 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3874 retval = FALSE;
3875
3876 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3877 * dbus-launch-x11 is just going to fail. Rather than trying to
3878 * run it, we might as well bail out early with a nice error.
3879 *
3880 * This is not strictly true in a world where the user bus exists,
3881 * because dbus-launch --autolaunch knows how to connect to that -
3882 * but if we were going to connect to the user bus, we'd have done
3883 * so before trying autolaunch: in any case. */
3884 display = _dbus_getenv ("DISPLAY");
3885
3886 if (display == NULL || display[0] == '\0')
3887 {
3888 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3889 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3890 return FALSE;
3891 }
3892
3893 if (!_dbus_string_init (&uuid))
3894 {
3895 _DBUS_SET_OOM (error);
3896 return FALSE;
3897 }
3898
3899 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3900 {
3901 goto out;
3902 }
3903
3904 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3905 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
3906
3907 if (progpath == NULL)
3908 #endif
3909 progpath = DBUS_BINDIR "/dbus-launch";
3910 /*
3911 * argv[0] is always dbus-launch, that's the name what we'll
3912 * get from /proc, or ps(1), regardless what the progpath is,
3913 * see fd.o#69716
3914 */
3915 i = 0;
3916 argv[i] = arg_dbus_launch;
3917 ++i;
3918 argv[i] = arg_autolaunch;
3919 ++i;
3920 argv[i] = _dbus_string_get_data (&uuid);
3921 ++i;
3922 argv[i] = arg_binary_syntax;
3923 ++i;
3924 argv[i] = arg_close_stderr;
3925 ++i;
3926 argv[i] = NULL;
3927 ++i;
3928
3929 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3930
3931 retval = _read_subprocess_line_argv (progpath,
3932 TRUE,
3933 argv, address, error);
3934
3935 out:
3936 _dbus_string_free (&uuid);
3937 return retval;
3938 #else
3939 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3940 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3941 "set your DBUS_SESSION_BUS_ADDRESS instead");
3942 return FALSE;
3943 #endif
3944 }
3945
3964 dbus_bool_t
3965 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3966 dbus_bool_t create_if_not_found,
3967 DBusError *error)
3968 {
3969 DBusError our_error = DBUS_ERROR_INIT;
3970 DBusError etc_error = DBUS_ERROR_INIT;
3971 DBusString filename;
3972 dbus_bool_t b;
3973
3974 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3975
3976 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
3977 if (b)
3978 return TRUE;
3979
3980 /* Fallback to the system machine ID */
3981 _dbus_string_init_const (&filename, "/etc/machine-id");
3982 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
3983
3984 if (b)
3985 {
3986 if (create_if_not_found)
3987 {
3988 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3989 * complain if that isn't possible for whatever reason */
3990 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3991 _dbus_write_uuid_file (&filename, machine_id, NULL);
3992 }
3993
3994 dbus_error_free (&our_error);
3995 return TRUE;
3996 }
3997
3998 if (!create_if_not_found)
3999 {
4000 dbus_set_error (error, etc_error.name,
4001 "D-Bus library appears to be incorrectly set up: "
4002 "see the manual page for dbus-uuidgen to correct "
4003 "this issue. (%s; %s)",
4004 our_error.message, etc_error.message);
4005 dbus_error_free (&our_error);
4006 dbus_error_free (&etc_error);
4007 return FALSE;
4008 }
4009
4010 dbus_error_free (&our_error);
4011 dbus_error_free (&etc_error);
4012
4013 /* if none found, try to make a new one */
4014 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4015
4016 if (!_dbus_generate_uuid (machine_id, error))
4017 return FALSE;
4018
4019 return _dbus_write_uuid_file (&filename, machine_id, error);
4020 }
4021
4029 dbus_bool_t
4030 _dbus_lookup_launchd_socket (DBusString *socket_path,
4031 const char *launchd_env_var,
4032 DBusError *error)
4033 {
4034 #ifdef DBUS_ENABLE_LAUNCHD
4035 char *argv[4];
4036 int i;
4037
4038 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4039
4040 if (_dbus_check_setuid ())
4041 {
4042 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4043 "Unable to find launchd socket when setuid");
4044 return FALSE;
4045 }
4046
4047 i = 0;
4048 argv[i] = "launchctl";
4049 ++i;
4050 argv[i] = "getenv";
4051 ++i;
4052 argv[i] = (char*)launchd_env_var;
4053 ++i;
4054 argv[i] = NULL;
4055 ++i;
4056
4057 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4058
4059 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4060 {
4061 return FALSE;
4062 }
4063
4064 /* no error, but no result either */
4065 if (_dbus_string_get_length(socket_path) == 0)
4066 {
4067 return FALSE;
4068 }
4069
4070 /* strip the carriage-return */
4071 _dbus_string_shorten(socket_path, 1);
4072 return TRUE;
4073 #else /* DBUS_ENABLE_LAUNCHD */
4074 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
4075 "can't lookup socket from launchd; launchd support not compiled in");
4076 return FALSE;
4077 #endif
4078 }
4079
4080 #ifdef DBUS_ENABLE_LAUNCHD
4081 static dbus_bool_t
4082 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4083 {
4084 dbus_bool_t valid_socket;
4085 DBusString socket_path;
4086
4087 if (_dbus_check_setuid ())
4088 {
4089 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4090 "Unable to find launchd socket when setuid");
4091 return FALSE;
4092 }
4093
4094 if (!_dbus_string_init (&socket_path))
4095 {
4096 _DBUS_SET_OOM (error);
4097 return FALSE;
4098 }
4099
4100 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4101
4102 if (dbus_error_is_set(error))
4103 {
4104 _dbus_string_free(&socket_path);
4105 return FALSE;
4106 }
4107
4108 if (!valid_socket)
4109 {
4110 dbus_set_error(error, "no socket path",
4111 "launchd did not provide a socket path, "
4112 "verify that org.freedesktop.dbus-session.plist is loaded!");
4113 _dbus_string_free(&socket_path);
4114 return FALSE;
4115 }
4116 if (!_dbus_string_append (address, "unix:path="))
4117 {
4118 _DBUS_SET_OOM (error);
4119 _dbus_string_free(&socket_path);
4120 return FALSE;
4121 }
4122 if (!_dbus_string_copy (&socket_path, 0, address,
4123 _dbus_string_get_length (address)))
4124 {
4125 _DBUS_SET_OOM (error);
4126 _dbus_string_free(&socket_path);
4127 return FALSE;
4128 }
4129
4130 _dbus_string_free(&socket_path);
4131 return TRUE;
4132 }
4133 #endif
4134
4135 dbus_bool_t
4136 _dbus_lookup_user_bus (dbus_bool_t *supported,
4137 DBusString *address,
4138 DBusError *error)
4139 {
4140 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4141 dbus_bool_t ret = FALSE;
4142 struct stat stbuf;
4143 DBusString user_bus_path;
4144
4145 if (runtime_dir == NULL)
4146 {
4147 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4148 *supported = FALSE;
4149 return TRUE; /* Cannot use it, but not an error */
4150 }
4151
4152 if (!_dbus_string_init (&user_bus_path))
4153 {
4154 _DBUS_SET_OOM (error);
4155 return FALSE;
4156 }
4157
4158 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4159 {
4160 _DBUS_SET_OOM (error);
4161 goto out;
4162 }
4163
4164 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4165 {
4166 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4167 _dbus_strerror (errno));
4168 *supported = FALSE;
4169 ret = TRUE; /* Cannot use it, but not an error */
4170 goto out;
4171 }
4172
4173 if (stbuf.st_uid != getuid ())
4174 {
4175 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4176 (long) stbuf.st_uid, (long) getuid ());
4177 *supported = FALSE;
4178 ret = TRUE; /* Cannot use it, but not an error */
4179 goto out;
4180 }
4181
4182 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4183 {
4184 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4185 (long) stbuf.st_mode);
4186 *supported = FALSE;
4187 ret = TRUE; /* Cannot use it, but not an error */
4188 goto out;
4189 }
4190
4191 if (!_dbus_string_append (address, "unix:path=") ||
4192 !_dbus_address_append_escaped (address, &user_bus_path))
4193 {
4194 _DBUS_SET_OOM (error);
4195 goto out;
4196 }
4197
4198 *supported = TRUE;
4199 ret = TRUE;
4200
4201 out:
4202 _dbus_string_free (&user_bus_path);
4203 return ret;
4204 }
4205
4225 dbus_bool_t
4226 _dbus_lookup_session_address (dbus_bool_t *supported,
4227 DBusString *address,
4228 DBusError *error)
4229 {
4230 #ifdef DBUS_ENABLE_LAUNCHD
4231 *supported = TRUE;
4232 return _dbus_lookup_session_address_launchd (address, error);
4233 #else
4234 *supported = FALSE;
4235
4236 if (!_dbus_lookup_user_bus (supported, address, error))
4237 return FALSE;
4238 else if (*supported)
4239 return TRUE;
4240
4241 /* On non-Mac Unix platforms, if the session address isn't already
4242 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4243 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4244 * autolaunch: global default; see init_session_address in
4245 * dbus/dbus-bus.c. */
4246 return TRUE;
4247 #endif
4248 }
4249
4257 void
4258 _dbus_flush_caches (void)
4259 {
4260 _dbus_user_database_flush_system ();
4261 }
4262
4276 dbus_bool_t
4277 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
4278 DBusCredentials *credentials)
4279 {
4280 DBusString homedir;
4281 DBusString dotdir;
4282 dbus_uid_t uid;
4283
4284 _dbus_assert (credentials != NULL);
4285 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
4286
4287 if (!_dbus_string_init (&homedir))
4288 return FALSE;
4289
4290 uid = _dbus_credentials_get_unix_uid (credentials);
4291 _dbus_assert (uid != DBUS_UID_UNSET);
4292
4293 if (!_dbus_homedir_from_uid (uid, &homedir))
4294 goto failed;
4295
4296 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4297 {
4298 const char *override;
4299
4300 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4301 if (override != NULL && *override != '\0')
4302 {
4303 _dbus_string_set_length (&homedir, 0);
4304 if (!_dbus_string_append (&homedir, override))
4305 goto failed;
4306
4307 _dbus_verbose ("Using fake homedir for testing: %s\n",
4308 _dbus_string_get_const_data (&homedir));
4309 }
4310 else
4311 {
4312 /* Not strictly thread-safe, but if we fail at thread-safety here,
4313 * the worst that will happen is some extra warnings. */
4314 static dbus_bool_t already_warned = FALSE;
4315 if (!already_warned)
4316 {
4317 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4318 _dbus_string_get_const_data (&homedir));
4319 already_warned = TRUE;
4320 }
4321 }
4322 }
4323 #endif
4324
4325 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4326 if (!_dbus_concat_dir_and_file (&homedir,
4327 &dotdir))
4328 goto failed;
4329
4330 if (!_dbus_string_copy (&homedir, 0,
4331 directory, _dbus_string_get_length (directory))) {
4332 goto failed;
4333 }
4334
4335 _dbus_string_free (&homedir);
4336 return TRUE;
4337
4338 failed:
4339 _dbus_string_free (&homedir);
4340 return FALSE;
4341 }
4342
4343 //PENDING(kdab) docs
4344 dbus_bool_t
4345 _dbus_daemon_publish_session_bus_address (const char* addr,
4346 const char *scope)
4347 {
4348 return TRUE;
4349 }
4350
4351 //PENDING(kdab) docs
4352 void
4353 _dbus_daemon_unpublish_session_bus_address (void)
4354 {
4355
4356 }
4357
4364 dbus_bool_t
4365 _dbus_get_is_errno_eagain_or_ewouldblock (int e)
4366 {
4367 /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
4368 * EWOULDBLOCK are numerically equal, which is permitted as described by
4369 * errno(3).
4370 */
4371 #if EAGAIN == EWOULDBLOCK
4372 return e == EAGAIN;
4373 #else
4374 return e == EAGAIN || e == EWOULDBLOCK;
4375 #endif
4376 }
4377
4385 dbus_bool_t
4386 _dbus_delete_directory (const DBusString *filename,
4387 DBusError *error)
4388 {
4389 const char *filename_c;
4390
4391 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4392
4393 filename_c = _dbus_string_get_const_data (filename);
4394
4395 if (rmdir (filename_c) != 0)
4396 {
4397 dbus_set_error (error, DBUS_ERROR_FAILED,
4398 "Failed to remove directory %s: %s\n",
4399 filename_c, _dbus_strerror (errno));
4400 return FALSE;
4401 }
4402
4403 return TRUE;
4404 }
4405
4413 dbus_bool_t
4414 _dbus_socket_can_pass_unix_fd (DBusSocket fd)
4415 {
4416 #ifdef SCM_RIGHTS
4417 union {
4418 struct sockaddr sa;
4419 struct sockaddr_storage storage;
4420 struct sockaddr_un un;
4421 } sa_buf;
4422
4423 socklen_t sa_len = sizeof(sa_buf);
4424
4425 _DBUS_ZERO(sa_buf);
4426
4427 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4428 return FALSE;
4429
4430 return sa_buf.sa.sa_family == AF_UNIX;
4431
4432 #else
4433 return FALSE;
4434
4435 #endif
4436 }
4437
4442 void
4443 _dbus_close_all (void)
4444 {
4445 int maxfds, i;
4446
4447 #ifdef __linux__
4448 DIR *d;
4449
4450 /* On Linux we can optimize this a bit if /proc is available. If it
4451 isn't available, fall back to the brute force way. */
4452
4453 d = opendir ("/proc/self/fd");
4454 if (d)
4455 {
4456 for (;;)
4457 {
4458 struct dirent *de;
4459 int fd;
4460 long l;
4461 char *e = NULL;
4462
4463 de = readdir (d);
4464 if (!de)
4465 break;
4466
4467 if (de->d_name[0] == '.')
4468 continue;
4469
4470 errno = 0;
4471 l = strtol (de->d_name, &e, 10);
4472 if (errno != 0 || e == NULL || *e != '\0')
4473 continue;
4474
4475 fd = (int) l;
4476 if (fd < 3)
4477 continue;
4478
4479 if (fd == dirfd (d))
4480 continue;
4481
4482 close (fd);
4483 }
4484
4485 closedir (d);
4486 return;
4487 }
4488 #endif
4489
4490 maxfds = sysconf (_SC_OPEN_MAX);
4491
4492 /* Pick something reasonable if for some reason sysconf says
4493 * unlimited.
4494 */
4495 if (maxfds < 0)
4496 maxfds = 1024;
4497
4498 /* close all inherited fds */
4499 for (i = 3; i < maxfds; i++)
4500 close (i);
4501 }
4502
4512 dbus_bool_t
4513 _dbus_check_setuid (void)
4514 {
4515 /* TODO: get __libc_enable_secure exported from glibc.
4516 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4517 */
4518 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4519 {
4520 /* See glibc/include/unistd.h */
4521 extern int __libc_enable_secure;
4522 return __libc_enable_secure;
4523 }
4524 #elif defined(HAVE_ISSETUGID)
4525 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4526 return issetugid ();
4527 #else
4528 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4529 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4530
4531 /* We call into this function from _dbus_threads_init_platform_specific()
4532 * to make sure these are initialized before we start threading. */
4533 static dbus_bool_t check_setuid_initialised;
4534 static dbus_bool_t is_setuid;
4535
4536 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4537 {
4538 #ifdef HAVE_GETRESUID
4539 if (getresuid (&ruid, &euid, &suid) != 0 ||
4540 getresgid (&rgid, &egid, &sgid) != 0)
4541 #endif /* HAVE_GETRESUID */
4542 {
4543 suid = ruid = getuid ();
4544 sgid = rgid = getgid ();
4545 euid = geteuid ();
4546 egid = getegid ();
4547 }
4548
4549 check_setuid_initialised = TRUE;
4550 is_setuid = (ruid != euid || ruid != suid ||
4551 rgid != egid || rgid != sgid);
4552
4553 }
4554 return is_setuid;
4555 #endif
4556 }
4557
4565 dbus_bool_t
4566 _dbus_append_address_from_socket (DBusSocket fd,
4567 DBusString *address,
4568 DBusError *error)
4569 {
4570 union {
4571 struct sockaddr sa;
4572 struct sockaddr_storage storage;
4573 struct sockaddr_un un;
4574 struct sockaddr_in ipv4;
4575 struct sockaddr_in6 ipv6;
4576 } socket;
4577 char hostip[INET6_ADDRSTRLEN];
4578 socklen_t size = sizeof (socket);
4579 DBusString path_str;
4580
4581 if (getsockname (fd.fd, &socket.sa, &size))
4582 goto err;
4583
4584 switch (socket.sa.sa_family)
4585 {
4586 case AF_UNIX:
4587 if (socket.un.sun_path[0]=='\0')
4588 {
4589 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4590 if (_dbus_string_append (address, "unix:abstract=") &&
4591 _dbus_address_append_escaped (address, &path_str))
4592 return TRUE;
4593 }
4594 else
4595 {
4596 _dbus_string_init_const (&path_str, socket.un.sun_path);
4597 if (_dbus_string_append (address, "unix:path=") &&
4598 _dbus_address_append_escaped (address, &path_str))
4599 return TRUE;
4600 }
4601 break;
4602 case AF_INET:
4603 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4604 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4605 hostip, ntohs (socket.ipv4.sin_port)))
4606 return TRUE;
4607 break;
4608 #ifdef AF_INET6
4609 case AF_INET6:
4610 _dbus_string_init_const (&path_str, hostip);
4611 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4612 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4613 ntohs (socket.ipv6.sin6_port)) &&
4614 _dbus_address_append_escaped (address, &path_str))
4615 return TRUE;
4616 break;
4617 #endif
4618 default:
4619 dbus_set_error (error,
4620 _dbus_error_from_errno (EINVAL),
4621 "Failed to read address from socket: Unknown socket type.");
4622 return FALSE;
4623 }
4624 err:
4625 dbus_set_error (error,
4626 _dbus_error_from_errno (errno),
4627 "Failed to open socket: %s",
4628 _dbus_strerror (errno));
4629 return FALSE;
4630 }
4631
4632 int
4633 _dbus_save_socket_errno (void)
4634 {
4635 return errno;
4636 }
4637
4638 void
4639 _dbus_restore_socket_errno (int saved_errno)
4640 {
4641 errno = saved_errno;
4642 }
4643
4644 static const char *syslog_tag = "dbus";
4645 #ifdef HAVE_SYSLOG_H
4646 static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4647 #endif
4648
4663 void
4664 _dbus_init_system_log (const char *tag,
4665 DBusLogFlags flags)
4666 {
4667 /* We never want to turn off logging completely */
4668 _dbus_assert (
4669 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
4670
4671 syslog_tag = tag;
4672
4673 #ifdef HAVE_SYSLOG_H
4674 log_flags = flags;
4675
4676 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4677 openlog (tag, LOG_PID, LOG_DAEMON);
4678 #endif
4679 }
4680
4688 void
4689 _dbus_logv (DBusSystemLogSeverity severity,
4690 const char *msg,
4691 va_list args)
4692 {
4693 va_list tmp;
4694 #ifdef HAVE_SYSLOG_H
4695 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4696 {
4697 int flags;
4698 switch (severity)
4699 {
4700 case DBUS_SYSTEM_LOG_INFO:
4701 flags = LOG_DAEMON | LOG_INFO;
4702 break;
4703 case DBUS_SYSTEM_LOG_WARNING:
4704 flags = LOG_DAEMON | LOG_WARNING;
4705 break;
4706 case DBUS_SYSTEM_LOG_SECURITY:
4707 flags = LOG_AUTH | LOG_NOTICE;
4708 break;
4709 case DBUS_SYSTEM_LOG_ERROR:
4710 flags = LOG_DAEMON|LOG_CRIT;
4711 break;
4712 default:
4713 _dbus_assert_not_reached ("invalid log severity");
4714 }
4715
4716 DBUS_VA_COPY (tmp, args);
4717 vsyslog (flags, msg, tmp);
4718 va_end (tmp);
4719 }
4720
4721 /* If we don't have syslog.h, we always behave as though stderr was in
4722 * the flags */
4723 if (log_flags & DBUS_LOG_FLAGS_STDERR)
4724 #endif
4725 {
4726 DBUS_VA_COPY (tmp, args);
4727 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
4728 vfprintf (stderr, msg, tmp);
4729 fputc ('\n', stderr);
4730 va_end (tmp);
4731 }
4732 }
4733
4734 /* 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:2338
_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:3965
_dbus_close_all
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:4443
_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:3019
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:3433
_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:764
_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:4566
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:4513
_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:2725
_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:3082
_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:3304
_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:2262
_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:2768
_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:3846
_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:2651
_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:4030
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:2714
_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:4365
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:1239
_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:631
_dbus_accept
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
Definition: dbus-sysdeps-unix.c:2283
_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:2816
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:3391
_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:704
_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:4277
_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:1948
_dbus_create_directory
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
Definition: dbus-sysdeps-unix.c:3051
_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:4386
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:2966
_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:1514
_dbus_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition: dbus-sysdeps-unix.c:3241
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:4258
_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:1006
_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:3578
_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:2743
_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:2684
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:3212
_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:2755
_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:3254
_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:1389
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:2839
_dbus_getuid
dbus_uid_t _dbus_getuid(void)
Gets our UID.
Definition: dbus-sysdeps-unix.c:2734
_dbus_init_system_log
void _dbus_init_system_log(const char *tag, DBusLogFlags flags)
Initialize the system log.
Definition: dbus-sysdeps-unix.c:4664
_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:3157
_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:2668
_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:3346
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:4226
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3276
_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:4689
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:810
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition: dbus-sysdeps-unix.c:2863
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition: dbus-sysdeps-unix.c:3127
_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:3508
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:4414
_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:2888
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:909
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:1112
_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:2997
DBusUserInfo
Information about a UNIX user.
Definition: dbus-sysdeps-unix.h:106
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:411