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

D-Bus 1.12.4

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
917 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
918
919 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
920 path, abstract);
921
922
923 if (!_dbus_open_unix_socket (&fd, error))
924 {
925 _DBUS_ASSERT_ERROR_IS_SET(error);
926 return -1;
927 }
928 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
929
930 _DBUS_ZERO (addr);
931 addr.sun_family = AF_UNIX;
932 path_len = strlen (path);
933
934 if (abstract)
935 {
936 #ifdef __linux__
937 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
938 path_len++; /* Account for the extra nul byte added to the start of sun_path */
939
940 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
941 {
942 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
943 "Abstract socket name too long\n");
944 _dbus_close (fd, NULL);
945 return -1;
946 }
947
948 strncpy (&addr.sun_path[1], path, path_len);
949 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
950 #else /* !__linux__ */
951 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
952 "Operating system does not support abstract socket namespace\n");
953 _dbus_close (fd, NULL);
954 return -1;
955 #endif /* !__linux__ */
956 }
957 else
958 {
959 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
960 {
961 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
962 "Socket name too long\n");
963 _dbus_close (fd, NULL);
964 return -1;
965 }
966
967 strncpy (addr.sun_path, path, path_len);
968 }
969
970 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
971 {
972 dbus_set_error (error,
973 _dbus_error_from_errno (errno),
974 "Failed to connect to socket %s: %s",
975 path, _dbus_strerror (errno));
976
977 _dbus_close (fd, NULL);
978 return -1;
979 }
980
981 if (!_dbus_set_fd_nonblocking (fd, error))
982 {
983 _DBUS_ASSERT_ERROR_IS_SET (error);
984
985 _dbus_close (fd, NULL);
986 return -1;
987 }
988
989 return fd;
990 }
991
1004 int
1005 _dbus_connect_exec (const char *path,
1006 char *const argv[],
1007 DBusError *error)
1008 {
1009 int fds[2];
1010 pid_t pid;
1011 int retval;
1012 dbus_bool_t cloexec_done = 0;
1013
1014 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1015
1016 _dbus_verbose ("connecting to process %s\n", path);
1017
1018 #ifdef SOCK_CLOEXEC
1019 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1020 cloexec_done = (retval >= 0);
1021
1022 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1023 #endif
1024 {
1025 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1026 }
1027
1028 if (retval < 0)
1029 {
1030 dbus_set_error (error,
1031 _dbus_error_from_errno (errno),
1032 "Failed to create socket pair: %s",
1033 _dbus_strerror (errno));
1034 return -1;
1035 }
1036
1037 if (!cloexec_done)
1038 {
1039 _dbus_fd_set_close_on_exec (fds[0]);
1040 _dbus_fd_set_close_on_exec (fds[1]);
1041 }
1042
1043 pid = fork ();
1044 if (pid < 0)
1045 {
1046 dbus_set_error (error,
1047 _dbus_error_from_errno (errno),
1048 "Failed to fork() to call %s: %s",
1049 path, _dbus_strerror (errno));
1050 close (fds[0]);
1051 close (fds[1]);
1052 return -1;
1053 }
1054
1055 if (pid == 0)
1056 {
1057 /* child */
1058 close (fds[0]);
1059
1060 dup2 (fds[1], STDIN_FILENO);
1061 dup2 (fds[1], STDOUT_FILENO);
1062
1063 if (fds[1] != STDIN_FILENO &&
1064 fds[1] != STDOUT_FILENO)
1065 close (fds[1]);
1066
1067 /* Inherit STDERR and the controlling terminal from the
1068 parent */
1069
1070 _dbus_close_all ();
1071
1072 execvp (path, (char * const *) argv);
1073
1074 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1075
1076 _exit(1);
1077 }
1078
1079 /* parent */
1080 close (fds[1]);
1081
1082 if (!_dbus_set_fd_nonblocking (fds[0], error))
1083 {
1084 _DBUS_ASSERT_ERROR_IS_SET (error);
1085
1086 close (fds[0]);
1087 return -1;
1088 }
1089
1090 return fds[0];
1091 }
1092
1110 int
1111 _dbus_listen_unix_socket (const char *path,
1112 dbus_bool_t abstract,
1113 DBusError *error)
1114 {
1115 int listen_fd;
1116 struct sockaddr_un addr;
1117 size_t path_len;
1118
1119 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1120
1121 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1122 path, abstract);
1123
1124 if (!_dbus_open_unix_socket (&listen_fd, error))
1125 {
1126 _DBUS_ASSERT_ERROR_IS_SET(error);
1127 return -1;
1128 }
1129 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1130
1131 _DBUS_ZERO (addr);
1132 addr.sun_family = AF_UNIX;
1133 path_len = strlen (path);
1134
1135 if (abstract)
1136 {
1137 #ifdef __linux__
1138 /* remember that abstract names aren't nul-terminated so we rely
1139 * on sun_path being filled in with zeroes above.
1140 */
1141 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1142 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1143
1144 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1145 {
1146 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1147 "Abstract socket name too long\n");
1148 _dbus_close (listen_fd, NULL);
1149 return -1;
1150 }
1151
1152 strncpy (&addr.sun_path[1], path, path_len);
1153 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1154 #else /* !__linux__ */
1155 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1156 "Operating system does not support abstract socket namespace\n");
1157 _dbus_close (listen_fd, NULL);
1158 return -1;
1159 #endif /* !__linux__ */
1160 }
1161 else
1162 {
1163 /* Discussed security implications of this with Nalin,
1164 * and we couldn't think of where it would kick our ass, but
1165 * it still seems a bit sucky. It also has non-security suckage;
1166 * really we'd prefer to exit if the socket is already in use.
1167 * But there doesn't seem to be a good way to do this.
1168 *
1169 * Just to be extra careful, I threw in the stat() - clearly
1170 * the stat() can't *fix* any security issue, but it at least
1171 * avoids inadvertent/accidental data loss.
1172 */
1173 {
1174 struct stat sb;
1175
1176 if (stat (path, &sb) == 0 &&
1177 S_ISSOCK (sb.st_mode))
1178 unlink (path);
1179 }
1180
1181 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1182 {
1183 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1184 "Socket name too long\n");
1185 _dbus_close (listen_fd, NULL);
1186 return -1;
1187 }
1188
1189 strncpy (addr.sun_path, path, path_len);
1190 }
1191
1192 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1193 {
1194 dbus_set_error (error, _dbus_error_from_errno (errno),
1195 "Failed to bind socket \"%s\": %s",
1196 path, _dbus_strerror (errno));
1197 _dbus_close (listen_fd, NULL);
1198 return -1;
1199 }
1200
1201 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1202 {
1203 dbus_set_error (error, _dbus_error_from_errno (errno),
1204 "Failed to listen on socket \"%s\": %s",
1205 path, _dbus_strerror (errno));
1206 _dbus_close (listen_fd, NULL);
1207 return -1;
1208 }
1209
1210 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1211 {
1212 _DBUS_ASSERT_ERROR_IS_SET (error);
1213 _dbus_close (listen_fd, NULL);
1214 return -1;
1215 }
1216
1217 /* Try opening up the permissions, but if we can't, just go ahead
1218 * and continue, maybe it will be good enough.
1219 */
1220 if (!abstract && chmod (path, 0777) < 0)
1221 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1222
1223 return listen_fd;
1224 }
1225
1236 int
1237 _dbus_listen_systemd_sockets (DBusSocket **fds,
1238 DBusError *error)
1239 {
1240 #ifdef HAVE_SYSTEMD
1241 int r, n;
1242 int fd;
1243 DBusSocket *new_fds;
1244
1245 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1246
1247 n = sd_listen_fds (TRUE);
1248 if (n < 0)
1249 {
1250 dbus_set_error (error, _dbus_error_from_errno (-n),
1251 "Failed to acquire systemd socket: %s",
1252 _dbus_strerror (-n));
1253 return -1;
1254 }
1255
1256 if (n <= 0)
1257 {
1258 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1259 "No socket received.");
1260 return -1;
1261 }
1262
1263 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1264 {
1265 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1266 if (r < 0)
1267 {
1268 dbus_set_error (error, _dbus_error_from_errno (-r),
1269 "Failed to verify systemd socket type: %s",
1270 _dbus_strerror (-r));
1271 return -1;
1272 }
1273
1274 if (!r)
1275 {
1276 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1277 "Passed socket has wrong type.");
1278 return -1;
1279 }
1280 }
1281
1282 /* OK, the file descriptors are all good, so let's take posession of
1283 them then. */
1284
1285 new_fds = dbus_new (DBusSocket, n);
1286 if (!new_fds)
1287 {
1288 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1289 "Failed to allocate file handle array.");
1290 goto fail;
1291 }
1292
1293 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1294 {
1295 if (!_dbus_set_fd_nonblocking (fd, error))
1296 {
1297 _DBUS_ASSERT_ERROR_IS_SET (error);
1298 goto fail;
1299 }
1300
1301 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1302 }
1303
1304 *fds = new_fds;
1305 return n;
1306
1307 fail:
1308
1309 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1310 {
1311 _dbus_close (fd, NULL);
1312 }
1313
1314 dbus_free (new_fds);
1315 return -1;
1316 #else
1317 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
1318 "dbus was compiled without systemd support");
1319 return -1;
1320 #endif
1321 }
1322
1336 DBusSocket
1337 _dbus_connect_tcp_socket (const char *host,
1338 const char *port,
1339 const char *family,
1340 DBusError *error)
1341 {
1342 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1343 }
1344
1345 DBusSocket
1346 _dbus_connect_tcp_socket_with_nonce (const char *host,
1347 const char *port,
1348 const char *family,
1349 const char *noncefile,
1350 DBusError *error)
1351 {
1352 int saved_errno = 0;
1353 DBusSocket fd = DBUS_SOCKET_INIT;
1354 int res;
1355 struct addrinfo hints;
1356 struct addrinfo *ai, *tmp;
1357
1358 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1359
1360 _DBUS_ZERO (hints);
1361
1362 if (!family)
1363 hints.ai_family = AF_UNSPEC;
1364 else if (!strcmp(family, "ipv4"))
1365 hints.ai_family = AF_INET;
1366 else if (!strcmp(family, "ipv6"))
1367 hints.ai_family = AF_INET6;
1368 else
1369 {
1370 dbus_set_error (error,
1371 DBUS_ERROR_BAD_ADDRESS,
1372 "Unknown address family %s", family);
1373 return _dbus_socket_get_invalid ();
1374 }
1375 hints.ai_protocol = IPPROTO_TCP;
1376 hints.ai_socktype = SOCK_STREAM;
1377 hints.ai_flags = AI_ADDRCONFIG;
1378
1379 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1380 {
1381 dbus_set_error (error,
1382 _dbus_error_from_errno (errno),
1383 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1384 host, port, gai_strerror(res), res);
1385 return _dbus_socket_get_invalid ();
1386 }
1387
1388 tmp = ai;
1389 while (tmp)
1390 {
1391 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1392 {
1393 freeaddrinfo(ai);
1394 _DBUS_ASSERT_ERROR_IS_SET(error);
1395 return _dbus_socket_get_invalid ();
1396 }
1397 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1398
1399 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1400 {
1401 saved_errno = errno;
1402 _dbus_close (fd.fd, NULL);
1403 fd.fd = -1;
1404 tmp = tmp->ai_next;
1405 continue;
1406 }
1407
1408 break;
1409 }
1410 freeaddrinfo(ai);
1411
1412 if (fd.fd == -1)
1413 {
1414 dbus_set_error (error,
1415 _dbus_error_from_errno (saved_errno),
1416 "Failed to connect to socket \"%s:%s\" %s",
1417 host, port, _dbus_strerror(saved_errno));
1418 return _dbus_socket_get_invalid ();
1419 }
1420
1421 if (noncefile != NULL)
1422 {
1423 DBusString noncefileStr;
1424 dbus_bool_t ret;
1425 _dbus_string_init_const (&noncefileStr, noncefile);
1426 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1427 _dbus_string_free (&noncefileStr);
1428
1429 if (!ret)
1430 {
1431 _dbus_close (fd.fd, NULL);
1432 return _dbus_socket_get_invalid ();
1433 }
1434 }
1435
1436 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1437 {
1438 _dbus_close (fd.fd, NULL);
1439 return _dbus_socket_get_invalid ();
1440 }
1441
1442 return fd;
1443 }
1444
1461 int
1462 _dbus_listen_tcp_socket (const char *host,
1463 const char *port,
1464 const char *family,
1465 DBusString *retport,
1466 DBusSocket **fds_p,
1467 DBusError *error)
1468 {
1469 int saved_errno;
1470 int nlisten_fd = 0, res, i;
1471 DBusSocket *listen_fd = NULL;
1472 struct addrinfo hints;
1473 struct addrinfo *ai, *tmp;
1474 unsigned int reuseaddr;
1475
1476 *fds_p = NULL;
1477 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1478
1479 _DBUS_ZERO (hints);
1480
1481 if (!family)
1482 hints.ai_family = AF_UNSPEC;
1483 else if (!strcmp(family, "ipv4"))
1484 hints.ai_family = AF_INET;
1485 else if (!strcmp(family, "ipv6"))
1486 hints.ai_family = AF_INET6;
1487 else
1488 {
1489 dbus_set_error (error,
1490 DBUS_ERROR_BAD_ADDRESS,
1491 "Unknown address family %s", family);
1492 return -1;
1493 }
1494
1495 hints.ai_protocol = IPPROTO_TCP;
1496 hints.ai_socktype = SOCK_STREAM;
1497 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1498
1499 redo_lookup_with_port:
1500 ai = NULL;
1501 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1502 {
1503 dbus_set_error (error,
1504 _dbus_error_from_errno (errno),
1505 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1506 host ? host : "*", port, gai_strerror(res), res);
1507 goto failed;
1508 }
1509
1510 tmp = ai;
1511 while (tmp)
1512 {
1513 int fd = -1, tcp_nodelay_on;
1514 DBusSocket *newlisten_fd;
1515
1516 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1517 {
1518 _DBUS_ASSERT_ERROR_IS_SET(error);
1519 goto failed;
1520 }
1521 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1522
1523 reuseaddr = 1;
1524 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1525 {
1526 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1527 host ? host : "*", port, _dbus_strerror (errno));
1528 }
1529
1530 /* Nagle's algorithm imposes a huge delay on the initial messages
1531 going over TCP. */
1532 tcp_nodelay_on = 1;
1533 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1534 {
1535 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1536 host ? host : "*", port, _dbus_strerror (errno));
1537 }
1538
1539 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1540 {
1541 saved_errno = errno;
1542 _dbus_close(fd, NULL);
1543 if (saved_errno == EADDRINUSE)
1544 {
1545 /* Depending on kernel policy, binding to an IPv6 address
1546 might implicitly bind to a corresponding IPv4
1547 address or vice versa, resulting in EADDRINUSE for the
1548 other one (e.g. bindv6only=0 on Linux).
1549
1550 Also, after we "goto redo_lookup_with_port" after binding
1551 a port on one of the possible addresses, we will
1552 try to bind that same port on every address, including the
1553 same address again for a second time; that one will
1554 also fail with EADDRINUSE.
1555
1556 For both those reasons, ignore EADDRINUSE here */
1557 tmp = tmp->ai_next;
1558 continue;
1559 }
1560 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1561 "Failed to bind socket \"%s:%s\": %s",
1562 host ? host : "*", port, _dbus_strerror (saved_errno));
1563 goto failed;
1564 }
1565
1566 if (listen (fd, 30 /* backlog */) < 0)
1567 {
1568 saved_errno = errno;
1569 _dbus_close (fd, NULL);
1570 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1571 "Failed to listen on socket \"%s:%s\": %s",
1572 host ? host : "*", port, _dbus_strerror (saved_errno));
1573 goto failed;
1574 }
1575
1576 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1577 if (!newlisten_fd)
1578 {
1579 _dbus_close (fd, NULL);
1580 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1581 "Failed to allocate file handle array");
1582 goto failed;
1583 }
1584 listen_fd = newlisten_fd;
1585 listen_fd[nlisten_fd].fd = fd;
1586 nlisten_fd++;
1587
1588 if (!_dbus_string_get_length(retport))
1589 {
1590 /* If the user didn't specify a port, or used 0, then
1591 the kernel chooses a port. After the first address
1592 is bound to, we need to force all remaining addresses
1593 to use the same port */
1594 if (!port || !strcmp(port, "0"))
1595 {
1596 int result;
1597 struct sockaddr_storage addr;
1598 socklen_t addrlen;
1599 char portbuf[50];
1600
1601 addrlen = sizeof(addr);
1602 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1603
1604 if (result == -1 ||
1605 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1606 portbuf, sizeof(portbuf),
1607 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1608 {
1609 dbus_set_error (error, _dbus_error_from_errno (errno),
1610 "Failed to resolve port \"%s:%s\": %s (%d)",
1611 host ? host : "*", port, gai_strerror(res), res);
1612 goto failed;
1613 }
1614 if (!_dbus_string_append(retport, portbuf))
1615 {
1616 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1617 goto failed;
1618 }
1619
1620 /* Release current address list & redo lookup */
1621 port = _dbus_string_get_const_data(retport);
1622 freeaddrinfo(ai);
1623 goto redo_lookup_with_port;
1624 }
1625 else
1626 {
1627 if (!_dbus_string_append(retport, port))
1628 {
1629 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1630 goto failed;
1631 }
1632 }
1633 }
1634
1635 tmp = tmp->ai_next;
1636 }
1637 freeaddrinfo(ai);
1638 ai = NULL;
1639
1640 if (!nlisten_fd)
1641 {
1642 errno = EADDRINUSE;
1643 dbus_set_error (error, _dbus_error_from_errno (errno),
1644 "Failed to bind socket \"%s:%s\": %s",
1645 host ? host : "*", port, _dbus_strerror (errno));
1646 goto failed;
1647 }
1648
1649 for (i = 0 ; i < nlisten_fd ; i++)
1650 {
1651 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1652 {
1653 goto failed;
1654 }
1655 }
1656
1657 *fds_p = listen_fd;
1658
1659 return nlisten_fd;
1660
1661 failed:
1662 if (ai)
1663 freeaddrinfo(ai);
1664 for (i = 0 ; i < nlisten_fd ; i++)
1665 _dbus_close(listen_fd[i].fd, NULL);
1666 dbus_free(listen_fd);
1667 return -1;
1668 }
1669
1670 static dbus_bool_t
1671 write_credentials_byte (int server_fd,
1672 DBusError *error)
1673 {
1674 int bytes_written;
1675 char buf[1] = { '\0' };
1676 #if defined(HAVE_CMSGCRED)
1677 union {
1678 struct cmsghdr hdr;
1679 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1680 } cmsg;
1681 struct iovec iov;
1682 struct msghdr msg;
1683 iov.iov_base = buf;
1684 iov.iov_len = 1;
1685
1686 _DBUS_ZERO(msg);
1687 msg.msg_iov = &iov;
1688 msg.msg_iovlen = 1;
1689
1690 msg.msg_control = (caddr_t) &cmsg;
1691 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1692 _DBUS_ZERO(cmsg);
1693 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1694 cmsg.hdr.cmsg_level = SOL_SOCKET;
1695 cmsg.hdr.cmsg_type = SCM_CREDS;
1696 #endif
1697
1698 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1699
1700 again:
1701
1702 #if defined(HAVE_CMSGCRED)
1703 bytes_written = sendmsg (server_fd, &msg, 0
1704 #if HAVE_DECL_MSG_NOSIGNAL
1705 |MSG_NOSIGNAL
1706 #endif
1707 );
1708
1709 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1710 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1711 * only allows that on AF_UNIX. Try just doing a send() instead. */
1712 if (bytes_written < 0 && errno == EINVAL)
1713 #endif
1714 {
1715 bytes_written = send (server_fd, buf, 1, 0
1716 #if HAVE_DECL_MSG_NOSIGNAL
1717 |MSG_NOSIGNAL
1718 #endif
1719 );
1720 }
1721
1722 if (bytes_written < 0 && errno == EINTR)
1723 goto again;
1724
1725 if (bytes_written < 0)
1726 {
1727 dbus_set_error (error, _dbus_error_from_errno (errno),
1728 "Failed to write credentials byte: %s",
1729 _dbus_strerror (errno));
1730 return FALSE;
1731 }
1732 else if (bytes_written == 0)
1733 {
1734 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1735 "wrote zero bytes writing credentials byte");
1736 return FALSE;
1737 }
1738 else
1739 {
1740 _dbus_assert (bytes_written == 1);
1741 _dbus_verbose ("wrote credentials byte\n");
1742 return TRUE;
1743 }
1744 }
1745
1746 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1747 static dbus_bool_t
1748 add_linux_security_label_to_credentials (int client_fd,
1749 DBusCredentials *credentials)
1750 {
1751 #if defined(__linux__) && defined(SO_PEERSEC)
1752 DBusString buf;
1753 socklen_t len = 1024;
1754 dbus_bool_t oom = FALSE;
1755
1756 if (!_dbus_string_init_preallocated (&buf, len) ||
1757 !_dbus_string_set_length (&buf, len))
1758 return FALSE;
1759
1760 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1761 _dbus_string_get_data (&buf), &len) < 0)
1762 {
1763 int e = errno;
1764
1765 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1766 _dbus_strerror (e), (unsigned long) len);
1767
1768 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1769 {
1770 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1771 _dbus_strerror (e));
1772 goto out;
1773 }
1774
1775 /* If not enough space, len is updated to be enough.
1776 * Try again with a large enough buffer. */
1777 if (!_dbus_string_set_length (&buf, len))
1778 {
1779 oom = TRUE;
1780 goto out;
1781 }
1782
1783 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1784 }
1785
1786 if (len <= 0)
1787 {
1788 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1789 (unsigned long) len);
1790 goto out;
1791 }
1792
1793 if (len > _dbus_string_get_length_uint (&buf))
1794 {
1795 _dbus_verbose ("%lu > %u", (unsigned long) len,
1796 _dbus_string_get_length_uint (&buf));
1797 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1798 }
1799
1800 if (_dbus_string_get_byte (&buf, len - 1) == 0)
1801 {
1802 /* the kernel included the trailing \0 in its count,
1803 * but DBusString always has an extra \0 after the data anyway */
1804 _dbus_verbose ("subtracting trailing \\0\n");
1805 len--;
1806 }
1807
1808 if (!_dbus_string_set_length (&buf, len))
1809 {
1810 _dbus_assert_not_reached ("shortening string should not lead to OOM");
1811 oom = TRUE;
1812 goto out;
1813 }
1814
1815 if (strlen (_dbus_string_get_const_data (&buf)) != len)
1816 {
1817 /* LSM people on the linux-security-module@ mailing list say this
1818 * should never happen: the label should be a bytestring with
1819 * an optional trailing \0 */
1820 _dbus_verbose ("security label from kernel had an embedded \\0, "
1821 "ignoring it\n");
1822 goto out;
1823 }
1824
1825 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1826 (unsigned long) len,
1827 _dbus_string_get_const_data (&buf));
1828
1829 if (!_dbus_credentials_add_linux_security_label (credentials,
1830 _dbus_string_get_const_data (&buf)))
1831 {
1832 oom = TRUE;
1833 goto out;
1834 }
1835
1836 out:
1837 _dbus_string_free (&buf);
1838 return !oom;
1839 #else
1840 /* no error */
1841 return TRUE;
1842 #endif
1843 }
1844
1885 dbus_bool_t
1886 _dbus_read_credentials_socket (DBusSocket client_fd,
1887 DBusCredentials *credentials,
1888 DBusError *error)
1889 {
1890 struct msghdr msg;
1891 struct iovec iov;
1892 char buf;
1893 dbus_uid_t uid_read;
1894 dbus_pid_t pid_read;
1895 int bytes_read;
1896
1897 #ifdef HAVE_CMSGCRED
1898 union {
1899 struct cmsghdr hdr;
1900 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1901 } cmsg;
1902 #endif
1903
1904 /* The POSIX spec certainly doesn't promise this, but
1905 * we need these assertions to fail as soon as we're wrong about
1906 * it so we can do the porting fixups
1907 */
1908 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1909 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1910 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1911
1912 uid_read = DBUS_UID_UNSET;
1913 pid_read = DBUS_PID_UNSET;
1914
1915 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1916
1917 _dbus_credentials_clear (credentials);
1918
1919 iov.iov_base = &buf;
1920 iov.iov_len = 1;
1921
1922 _DBUS_ZERO(msg);
1923 msg.msg_iov = &iov;
1924 msg.msg_iovlen = 1;
1925
1926 #if defined(HAVE_CMSGCRED)
1927 _DBUS_ZERO(cmsg);
1928 msg.msg_control = (caddr_t) &cmsg;
1929 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1930 #endif
1931
1932 again:
1933 bytes_read = recvmsg (client_fd.fd, &msg, 0);
1934
1935 if (bytes_read < 0)
1936 {
1937 if (errno == EINTR)
1938 goto again;
1939
1940 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1941 * normally only call read_credentials if the socket was ready
1942 * for reading
1943 */
1944
1945 dbus_set_error (error, _dbus_error_from_errno (errno),
1946 "Failed to read credentials byte: %s",
1947 _dbus_strerror (errno));
1948 return FALSE;
1949 }
1950 else if (bytes_read == 0)
1951 {
1952 /* this should not happen unless we are using recvmsg wrong,
1953 * so is essentially here for paranoia
1954 */
1955 dbus_set_error (error, DBUS_ERROR_FAILED,
1956 "Failed to read credentials byte (zero-length read)");
1957 return FALSE;
1958 }
1959 else if (buf != '\0')
1960 {
1961 dbus_set_error (error, DBUS_ERROR_FAILED,
1962 "Credentials byte was not nul");
1963 return FALSE;
1964 }
1965
1966 _dbus_verbose ("read credentials byte\n");
1967
1968 {
1969 #ifdef SO_PEERCRED
1970 /* Supported by at least Linux and OpenBSD, with minor differences.
1971 *
1972 * This mechanism passes the process ID through and does not require
1973 * the peer's cooperation, so we prefer it over all others. Notably,
1974 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
1975 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
1976 * because this is much less fragile.
1977 */
1978 #ifdef __OpenBSD__
1979 struct sockpeercred cr;
1980 #else
1981 struct ucred cr;
1982 #endif
1983 socklen_t cr_len = sizeof (cr);
1984
1985 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
1986 {
1987 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
1988 _dbus_strerror (errno));
1989 }
1990 else if (cr_len != sizeof (cr))
1991 {
1992 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
1993 cr_len, (int) sizeof (cr));
1994 }
1995 else
1996 {
1997 pid_read = cr.pid;
1998 uid_read = cr.uid;
1999 }
2000 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2001 /* Another variant of the above - used on NetBSD
2002 */
2003 struct unpcbid cr;
2004 socklen_t cr_len = sizeof (cr);
2005
2006 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2007 {
2008 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2009 _dbus_strerror (errno));
2010 }
2011 else if (cr_len != sizeof (cr))
2012 {
2013 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2014 cr_len, (int) sizeof (cr));
2015 }
2016 else
2017 {
2018 pid_read = cr.unp_pid;
2019 uid_read = cr.unp_euid;
2020 }
2021 #elif defined(HAVE_CMSGCRED)
2022 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2023 * presence of that struct implies SCM_CREDS. Supported by at least
2024 * FreeBSD and DragonflyBSD.
2025 *
2026 * This mechanism requires the peer to help us (it has to send us a
2027 * SCM_CREDS message) but it does pass the process ID through,
2028 * which makes it better than getpeereid().
2029 */
2030 struct cmsgcred *cred;
2031 struct cmsghdr *cmsgp;
2032
2033 for (cmsgp = CMSG_FIRSTHDR (&msg);
2034 cmsgp != NULL;
2035 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2036 {
2037 if (cmsgp->cmsg_type == SCM_CREDS &&
2038 cmsgp->cmsg_level == SOL_SOCKET &&
2039 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2040 {
2041 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2042 pid_read = cred->cmcred_pid;
2043 uid_read = cred->cmcred_euid;
2044 break;
2045 }
2046 }
2047
2048 #elif defined(HAVE_GETPEERUCRED)
2049 /* Supported in at least Solaris >= 10. It should probably be higher
2050 * up this list, because it carries the pid and we use this code path
2051 * for audit data. */
2052 ucred_t * ucred = NULL;
2053 if (getpeerucred (client_fd.fd, &ucred) == 0)
2054 {
2055 #ifdef HAVE_ADT
2056 adt_session_data_t *adth = NULL;
2057 #endif
2058 pid_read = ucred_getpid (ucred);
2059 uid_read = ucred_geteuid (ucred);
2060 #ifdef HAVE_ADT
2061 /* generate audit session data based on socket ucred */
2062 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2063 {
2064 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2065 }
2066 else
2067 {
2068 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2069 {
2070 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2071 }
2072 else
2073 {
2074 adt_export_data_t *data = NULL;
2075 size_t size = adt_export_session_data (adth, &data);
2076 if (size <= 0)
2077 {
2078 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2079 }
2080 else
2081 {
2082 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2083 free (data);
2084 }
2085 }
2086 (void) adt_end_session (adth);
2087 }
2088 #endif /* HAVE_ADT */
2089 }
2090 else
2091 {
2092 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2093 }
2094 if (ucred != NULL)
2095 ucred_free (ucred);
2096
2097 /* ----------------------------------------------------------------
2098 * When adding new mechanisms, please add them above this point
2099 * if they support passing the process ID through, or below if not.
2100 * ---------------------------------------------------------------- */
2101
2102 #elif defined(HAVE_GETPEEREID)
2103 /* getpeereid() originates from D.J. Bernstein and is fairly
2104 * widely-supported. According to a web search, it might be present in
2105 * any/all of:
2106 *
2107 * - AIX?
2108 * - Blackberry?
2109 * - Cygwin
2110 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2111 * - Mac OS X
2112 * - Minix 3.1.8+
2113 * - MirBSD?
2114 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2115 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2116 * - QNX?
2117 */
2118 uid_t euid;
2119 gid_t egid;
2120 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2121 {
2122 uid_read = euid;
2123 }
2124 else
2125 {
2126 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2127 }
2128 #else /* no supported mechanism */
2129
2130 #warning Socket credentials not supported on this Unix OS
2131 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2132
2133 /* Please add other operating systems known to support at least one of
2134 * the mechanisms above to this list, keeping alphabetical order.
2135 * Everything not in this list is best-effort.
2136 */
2137 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2138 defined(__linux__) || \
2139 defined(__OpenBSD__) || \
2140 defined(__NetBSD__)
2141 # error Credentials passing not working on this OS is a regression!
2142 #endif
2143
2144 _dbus_verbose ("Socket credentials not supported on this OS\n");
2145 #endif
2146 }
2147
2148 _dbus_verbose ("Credentials:"
2149 " pid "DBUS_PID_FORMAT
2150 " uid "DBUS_UID_FORMAT
2151 "\n",
2152 pid_read,
2153 uid_read);
2154
2155 if (pid_read != DBUS_PID_UNSET)
2156 {
2157 if (!_dbus_credentials_add_pid (credentials, pid_read))
2158 {
2159 _DBUS_SET_OOM (error);
2160 return FALSE;
2161 }
2162 }
2163
2164 if (uid_read != DBUS_UID_UNSET)
2165 {
2166 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2167 {
2168 _DBUS_SET_OOM (error);
2169 return FALSE;
2170 }
2171 }
2172
2173 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2174 {
2175 _DBUS_SET_OOM (error);
2176 return FALSE;
2177 }
2178
2179 return TRUE;
2180 }
2181
2199 dbus_bool_t
2200 _dbus_send_credentials_socket (DBusSocket server_fd,
2201 DBusError *error)
2202 {
2203 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2204
2205 if (write_credentials_byte (server_fd.fd, error))
2206 return TRUE;
2207 else
2208 return FALSE;
2209 }
2210
2220 DBusSocket
2221 _dbus_accept (DBusSocket listen_fd)
2222 {
2223 DBusSocket client_fd;
2224 struct sockaddr addr;
2225 socklen_t addrlen;
2226 #ifdef HAVE_ACCEPT4
2227 dbus_bool_t cloexec_done;
2228 #endif
2229
2230 addrlen = sizeof (addr);
2231
2232 retry:
2233
2234 #ifdef HAVE_ACCEPT4
2235 /*
2236 * At compile-time, we assume that if accept4() is available in
2237 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2238 * not necessarily true that either is supported by the running kernel.
2239 */
2240 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2241 cloexec_done = client_fd.fd >= 0;
2242
2243 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2244 #endif
2245 {
2246 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2247 }
2248
2249 if (client_fd.fd < 0)
2250 {
2251 if (errno == EINTR)
2252 goto retry;
2253 }
2254
2255 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2256
2257 #ifdef HAVE_ACCEPT4
2258 if (!cloexec_done)
2259 #endif
2260 {
2261 _dbus_fd_set_close_on_exec(client_fd.fd);
2262 }
2263
2264 return client_fd;
2265 }
2266
2275 dbus_bool_t
2276 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2277 {
2278 const char *directory;
2279 struct stat sb;
2280
2281 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2282
2283 directory = _dbus_string_get_const_data (dir);
2284
2285 if (stat (directory, &sb) < 0)
2286 {
2287 dbus_set_error (error, _dbus_error_from_errno (errno),
2288 "%s", _dbus_strerror (errno));
2289
2290 return FALSE;
2291 }
2292
2293 if (sb.st_uid != geteuid ())
2294 {
2295 dbus_set_error (error, DBUS_ERROR_FAILED,
2296 "%s directory is owned by user %lu, not %lu",
2297 directory,
2298 (unsigned long) sb.st_uid,
2299 (unsigned long) geteuid ());
2300 return FALSE;
2301 }
2302
2303 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2304 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2305 {
2306 dbus_set_error (error, DBUS_ERROR_FAILED,
2307 "%s directory is not private to the user", directory);
2308 return FALSE;
2309 }
2310
2311 return TRUE;
2312 }
2313
2314 static dbus_bool_t
2315 fill_user_info_from_passwd (struct passwd *p,
2316 DBusUserInfo *info,
2317 DBusError *error)
2318 {
2319 _dbus_assert (p->pw_name != NULL);
2320 _dbus_assert (p->pw_dir != NULL);
2321
2322 info->uid = p->pw_uid;
2323 info->primary_gid = p->pw_gid;
2324 info->username = _dbus_strdup (p->pw_name);
2325 info->homedir = _dbus_strdup (p->pw_dir);
2326
2327 if (info->username == NULL ||
2328 info->homedir == NULL)
2329 {
2330 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2331 return FALSE;
2332 }
2333
2334 return TRUE;
2335 }
2336
2337 static dbus_bool_t
2338 fill_user_info (DBusUserInfo *info,
2339 dbus_uid_t uid,
2340 const DBusString *username,
2341 DBusError *error)
2342 {
2343 const char *username_c;
2344
2345 /* exactly one of username/uid provided */
2346 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2347 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2348
2349 info->uid = DBUS_UID_UNSET;
2350 info->primary_gid = DBUS_GID_UNSET;
2351 info->group_ids = NULL;
2352 info->n_group_ids = 0;
2353 info->username = NULL;
2354 info->homedir = NULL;
2355
2356 if (username != NULL)
2357 username_c = _dbus_string_get_const_data (username);
2358 else
2359 username_c = NULL;
2360
2361 /* For now assuming that the getpwnam() and getpwuid() flavors
2362 * are always symmetrical, if not we have to add more configure
2363 * checks
2364 */
2365
2366 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2367 {
2368 struct passwd *p;
2369 int result;
2370 size_t buflen;
2371 char *buf;
2372 struct passwd p_str;
2373
2374 /* retrieve maximum needed size for buf */
2375 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2376
2377 /* sysconf actually returns a long, but everything else expects size_t,
2378 * so just recast here.
2379 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2380 */
2381 if ((long) buflen <= 0)
2382 buflen = 1024;
2383
2384 result = -1;
2385 while (1)
2386 {
2387 buf = dbus_malloc (buflen);
2388 if (buf == NULL)
2389 {
2390 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2391 return FALSE;
2392 }
2393
2394 p = NULL;
2395 #ifdef HAVE_POSIX_GETPWNAM_R
2396 if (uid != DBUS_UID_UNSET)
2397 result = getpwuid_r (uid, &p_str, buf, buflen,
2398 &p);
2399 else
2400 result = getpwnam_r (username_c, &p_str, buf, buflen,
2401 &p);
2402 #else
2403 if (uid != DBUS_UID_UNSET)
2404 p = getpwuid_r (uid, &p_str, buf, buflen);
2405 else
2406 p = getpwnam_r (username_c, &p_str, buf, buflen);
2407 result = 0;
2408 #endif /* !HAVE_POSIX_GETPWNAM_R */
2409 //Try a bigger buffer if ERANGE was returned
2410 if (result == ERANGE && buflen < 512 * 1024)
2411 {
2412 dbus_free (buf);
2413 buflen *= 2;
2414 }
2415 else
2416 {
2417 break;
2418 }
2419 }
2420 if (result == 0 && p == &p_str)
2421 {
2422 if (!fill_user_info_from_passwd (p, info, error))
2423 {
2424 dbus_free (buf);
2425 return FALSE;
2426 }
2427 dbus_free (buf);
2428 }
2429 else
2430 {
2431 dbus_set_error (error, _dbus_error_from_errno (errno),
2432 "User \"%s\" unknown or no memory to allocate password entry\n",
2433 username_c ? username_c : "???");
2434 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2435 dbus_free (buf);
2436 return FALSE;
2437 }
2438 }
2439 #else /* ! HAVE_GETPWNAM_R */
2440 {
2441 /* I guess we're screwed on thread safety here */
2442 struct passwd *p;
2443
2444 if (uid != DBUS_UID_UNSET)
2445 p = getpwuid (uid);
2446 else
2447 p = getpwnam (username_c);
2448
2449 if (p != NULL)
2450 {
2451 if (!fill_user_info_from_passwd (p, info, error))
2452 {
2453 return FALSE;
2454 }
2455 }
2456 else
2457 {
2458 dbus_set_error (error, _dbus_error_from_errno (errno),
2459 "User \"%s\" unknown or no memory to allocate password entry\n",
2460 username_c ? username_c : "???");
2461 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2462 return FALSE;
2463 }
2464 }
2465 #endif /* ! HAVE_GETPWNAM_R */
2466
2467 /* Fill this in so we can use it to get groups */
2468 username_c = info->username;
2469
2470 #ifdef HAVE_GETGROUPLIST
2471 {
2472 gid_t *buf;
2473 int buf_count;
2474 int i;
2475 int initial_buf_count;
2476
2477 initial_buf_count = 17;
2478 buf_count = initial_buf_count;
2479 buf = dbus_new (gid_t, buf_count);
2480 if (buf == NULL)
2481 {
2482 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2483 goto failed;
2484 }
2485
2486 if (getgrouplist (username_c,
2487 info->primary_gid,
2488 buf, &buf_count) < 0)
2489 {
2490 gid_t *new;
2491 /* Presumed cause of negative return code: buf has insufficient
2492 entries to hold the entire group list. The Linux behavior in this
2493 case is to pass back the actual number of groups in buf_count, but
2494 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2495 So as a hack, try to help out a bit by guessing a larger
2496 number of groups, within reason.. might still fail, of course,
2497 but we can at least print a more informative message. I looked up
2498 the "right way" to do this by downloading Apple's own source code
2499 for the "id" command, and it turns out that they use an
2500 undocumented library function getgrouplist_2 (!) which is not
2501 declared in any header in /usr/include (!!). That did not seem
2502 like the way to go here.
2503 */
2504 if (buf_count == initial_buf_count)
2505 {
2506 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2507 }
2508 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2509 if (new == NULL)
2510 {
2511 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2512 dbus_free (buf);
2513 goto failed;
2514 }
2515
2516 buf = new;
2517
2518 errno = 0;
2519 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2520 {
2521 if (errno == 0)
2522 {
2523 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2524 username_c, buf_count, buf_count);
2525 }
2526 else
2527 {
2528 dbus_set_error (error,
2529 _dbus_error_from_errno (errno),
2530 "Failed to get groups for username \"%s\" primary GID "
2531 DBUS_GID_FORMAT ": %s\n",
2532 username_c, info->primary_gid,
2533 _dbus_strerror (errno));
2534 dbus_free (buf);
2535 goto failed;
2536 }
2537 }
2538 }
2539
2540 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2541 if (info->group_ids == NULL)
2542 {
2543 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2544 dbus_free (buf);
2545 goto failed;
2546 }
2547
2548 for (i = 0; i < buf_count; ++i)
2549 info->group_ids[i] = buf[i];
2550
2551 info->n_group_ids = buf_count;
2552
2553 dbus_free (buf);
2554 }
2555 #else /* HAVE_GETGROUPLIST */
2556 {
2557 /* We just get the one group ID */
2558 info->group_ids = dbus_new (dbus_gid_t, 1);
2559 if (info->group_ids == NULL)
2560 {
2561 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2562 goto failed;
2563 }
2564
2565 info->n_group_ids = 1;
2566
2567 (info->group_ids)[0] = info->primary_gid;
2568 }
2569 #endif /* HAVE_GETGROUPLIST */
2570
2571 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2572
2573 return TRUE;
2574
2575 failed:
2576 _DBUS_ASSERT_ERROR_IS_SET (error);
2577 return FALSE;
2578 }
2579
2588 dbus_bool_t
2589 _dbus_user_info_fill (DBusUserInfo *info,
2590 const DBusString *username,
2591 DBusError *error)
2592 {
2593 return fill_user_info (info, DBUS_UID_UNSET,
2594 username, error);
2595 }
2596
2605 dbus_bool_t
2606 _dbus_user_info_fill_uid (DBusUserInfo *info,
2607 dbus_uid_t uid,
2608 DBusError *error)
2609 {
2610 return fill_user_info (info, uid,
2611 NULL, error);
2612 }
2613
2621 dbus_bool_t
2622 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2623 {
2624 /* The POSIX spec certainly doesn't promise this, but
2625 * we need these assertions to fail as soon as we're wrong about
2626 * it so we can do the porting fixups
2627 */
2628 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2629 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2630 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2631
2632 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2633 return FALSE;
2634 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2635 return FALSE;
2636
2637 return TRUE;
2638 }
2639
2651 dbus_bool_t
2652 _dbus_append_user_from_current_process (DBusString *str)
2653 {
2654 return _dbus_string_append_uint (str,
2655 _dbus_geteuid ());
2656 }
2657
2662 dbus_pid_t
2663 _dbus_getpid (void)
2664 {
2665 return getpid ();
2666 }
2667
2671 dbus_uid_t
2672 _dbus_getuid (void)
2673 {
2674 return getuid ();
2675 }
2676
2680 dbus_uid_t
2681 _dbus_geteuid (void)
2682 {
2683 return geteuid ();
2684 }
2685
2692 unsigned long
2693 _dbus_pid_for_log (void)
2694 {
2695 return getpid ();
2696 }
2697
2705 dbus_bool_t
2706 _dbus_parse_uid (const DBusString *uid_str,
2707 dbus_uid_t *uid)
2708 {
2709 int end;
2710 long val;
2711
2712 if (_dbus_string_get_length (uid_str) == 0)
2713 {
2714 _dbus_verbose ("UID string was zero length\n");
2715 return FALSE;
2716 }
2717
2718 val = -1;
2719 end = 0;
2720 if (!_dbus_string_parse_int (uid_str, 0, &val,
2721 &end))
2722 {
2723 _dbus_verbose ("could not parse string as a UID\n");
2724 return FALSE;
2725 }
2726
2727 if (end != _dbus_string_get_length (uid_str))
2728 {
2729 _dbus_verbose ("string contained trailing stuff after UID\n");
2730 return FALSE;
2731 }
2732
2733 *uid = val;
2734
2735 return TRUE;
2736 }
2737
2738 #if !DBUS_USE_SYNC
2739 /* To be thread-safe by default on platforms that don't necessarily have
2740 * atomic operations (notably Debian armel, which is armv4t), we must
2741 * use a mutex that can be initialized statically, like this.
2742 * GLib >= 2.32 uses a similar system.
2743 */
2744 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2745 #endif
2746
2753 dbus_int32_t
2754 _dbus_atomic_inc (DBusAtomic *atomic)
2755 {
2756 #if DBUS_USE_SYNC
2757 return __sync_add_and_fetch(&atomic->value, 1)-1;
2758 #else
2759 dbus_int32_t res;
2760
2761 pthread_mutex_lock (&atomic_mutex);
2762 res = atomic->value;
2763 atomic->value += 1;
2764 pthread_mutex_unlock (&atomic_mutex);
2765
2766 return res;
2767 #endif
2768 }
2769
2776 dbus_int32_t
2777 _dbus_atomic_dec (DBusAtomic *atomic)
2778 {
2779 #if DBUS_USE_SYNC
2780 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2781 #else
2782 dbus_int32_t res;
2783
2784 pthread_mutex_lock (&atomic_mutex);
2785 res = atomic->value;
2786 atomic->value -= 1;
2787 pthread_mutex_unlock (&atomic_mutex);
2788
2789 return res;
2790 #endif
2791 }
2792
2800 dbus_int32_t
2801 _dbus_atomic_get (DBusAtomic *atomic)
2802 {
2803 #if DBUS_USE_SYNC
2804 __sync_synchronize ();
2805 return atomic->value;
2806 #else
2807 dbus_int32_t res;
2808
2809 pthread_mutex_lock (&atomic_mutex);
2810 res = atomic->value;
2811 pthread_mutex_unlock (&atomic_mutex);
2812
2813 return res;
2814 #endif
2815 }
2816
2825 int
2826 _dbus_poll (DBusPollFD *fds,
2827 int n_fds,
2828 int timeout_milliseconds)
2829 {
2830 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2831 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2832 if (timeout_milliseconds < -1)
2833 {
2834 timeout_milliseconds = -1;
2835 }
2836
2837 return poll (fds,
2838 n_fds,
2839 timeout_milliseconds);
2840 #else /* ! HAVE_POLL */
2841 /* Emulate poll() in terms of select() */
2842 fd_set read_set, write_set, err_set;
2843 int max_fd = 0;
2844 int i;
2845 struct timeval tv;
2846 int ready;
2847
2848 FD_ZERO (&read_set);
2849 FD_ZERO (&write_set);
2850 FD_ZERO (&err_set);
2851
2852 for (i = 0; i < n_fds; i++)
2853 {
2854 DBusPollFD *fdp = &fds[i];
2855
2856 if (fdp->events & _DBUS_POLLIN)
2857 FD_SET (fdp->fd, &read_set);
2858
2859 if (fdp->events & _DBUS_POLLOUT)
2860 FD_SET (fdp->fd, &write_set);
2861
2862 FD_SET (fdp->fd, &err_set);
2863
2864 max_fd = MAX (max_fd, fdp->fd);
2865 }
2866
2867 tv.tv_sec = timeout_milliseconds / 1000;
2868 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2869
2870 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2871 timeout_milliseconds < 0 ? NULL : &tv);
2872
2873 if (ready > 0)
2874 {
2875 for (i = 0; i < n_fds; i++)
2876 {
2877 DBusPollFD *fdp = &fds[i];
2878
2879 fdp->revents = 0;
2880
2881 if (FD_ISSET (fdp->fd, &read_set))
2882 fdp->revents |= _DBUS_POLLIN;
2883
2884 if (FD_ISSET (fdp->fd, &write_set))
2885 fdp->revents |= _DBUS_POLLOUT;
2886
2887 if (FD_ISSET (fdp->fd, &err_set))
2888 fdp->revents |= _DBUS_POLLERR;
2889 }
2890 }
2891
2892 return ready;
2893 #endif
2894 }
2895
2903 void
2904 _dbus_get_monotonic_time (long *tv_sec,
2905 long *tv_usec)
2906 {
2907 #ifdef HAVE_MONOTONIC_CLOCK
2908 struct timespec ts;
2909 clock_gettime (CLOCK_MONOTONIC, &ts);
2910
2911 if (tv_sec)
2912 *tv_sec = ts.tv_sec;
2913 if (tv_usec)
2914 *tv_usec = ts.tv_nsec / 1000;
2915 #else
2916 struct timeval t;
2917
2918 gettimeofday (&t, NULL);
2919
2920 if (tv_sec)
2921 *tv_sec = t.tv_sec;
2922 if (tv_usec)
2923 *tv_usec = t.tv_usec;
2924 #endif
2925 }
2926
2934 void
2935 _dbus_get_real_time (long *tv_sec,
2936 long *tv_usec)
2937 {
2938 struct timeval t;
2939
2940 gettimeofday (&t, NULL);
2941
2942 if (tv_sec)
2943 *tv_sec = t.tv_sec;
2944 if (tv_usec)
2945 *tv_usec = t.tv_usec;
2946 }
2947
2956 dbus_bool_t
2957 _dbus_ensure_directory (const DBusString *filename,
2958 DBusError *error)
2959 {
2960 const char *filename_c;
2961
2962 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2963
2964 filename_c = _dbus_string_get_const_data (filename);
2965
2966 if (mkdir (filename_c, 0700) < 0)
2967 {
2968 if (errno == EEXIST)
2969 return TRUE;
2970
2971 dbus_set_error (error, DBUS_ERROR_FAILED,
2972 "Failed to create directory %s: %s\n",
2973 filename_c, _dbus_strerror (errno));
2974 return FALSE;
2975 }
2976 else
2977 return TRUE;
2978 }
2979
2988 dbus_bool_t
2989 _dbus_create_directory (const DBusString *filename,
2990 DBusError *error)
2991 {
2992 const char *filename_c;
2993
2994 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2995
2996 filename_c = _dbus_string_get_const_data (filename);
2997
2998 if (mkdir (filename_c, 0700) < 0)
2999 {
3000 dbus_set_error (error, DBUS_ERROR_FAILED,
3001 "Failed to create directory %s: %s\n",
3002 filename_c, _dbus_strerror (errno));
3003 return FALSE;
3004 }
3005 else
3006 return TRUE;
3007 }
3008
3019 dbus_bool_t
3020 _dbus_concat_dir_and_file (DBusString *dir,
3021 const DBusString *next_component)
3022 {
3023 dbus_bool_t dir_ends_in_slash;
3024 dbus_bool_t file_starts_with_slash;
3025
3026 if (_dbus_string_get_length (dir) == 0 ||
3027 _dbus_string_get_length (next_component) == 0)
3028 return TRUE;
3029
3030 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3031 _dbus_string_get_length (dir) - 1);
3032
3033 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3034
3035 if (dir_ends_in_slash && file_starts_with_slash)
3036 {
3037 _dbus_string_shorten (dir, 1);
3038 }
3039 else if (!(dir_ends_in_slash || file_starts_with_slash))
3040 {
3041 if (!_dbus_string_append_byte (dir, '/'))
3042 return FALSE;
3043 }
3044
3045 return _dbus_string_copy (next_component, 0, dir,
3046 _dbus_string_get_length (dir));
3047 }
3048
3050 #define NANOSECONDS_PER_SECOND 1000000000
3051
3052 #define MICROSECONDS_PER_SECOND 1000000
3053
3054 #define MILLISECONDS_PER_SECOND 1000
3055
3056 #define NANOSECONDS_PER_MILLISECOND 1000000
3057
3058 #define MICROSECONDS_PER_MILLISECOND 1000
3059
3064 void
3065 _dbus_sleep_milliseconds (int milliseconds)
3066 {
3067 #ifdef HAVE_NANOSLEEP
3068 struct timespec req;
3069 struct timespec rem;
3070
3071 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3072 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3073 rem.tv_sec = 0;
3074 rem.tv_nsec = 0;
3075
3076 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3077 req = rem;
3078 #elif defined (HAVE_USLEEP)
3079 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3080 #else /* ! HAVE_USLEEP */
3081 sleep (MAX (milliseconds / 1000, 1));
3082 #endif
3083 }
3084
3094 dbus_bool_t
3095 _dbus_generate_random_bytes (DBusString *str,
3096 int n_bytes,
3097 DBusError *error)
3098 {
3099 int old_len;
3100 int fd;
3101 int result;
3102
3103 old_len = _dbus_string_get_length (str);
3104 fd = -1;
3105
3106 /* note, urandom on linux will fall back to pseudorandom */
3107 fd = open ("/dev/urandom", O_RDONLY);
3108
3109 if (fd < 0)
3110 {
3111 dbus_set_error (error, _dbus_error_from_errno (errno),
3112 "Could not open /dev/urandom: %s",
3113 _dbus_strerror (errno));
3114 return FALSE;
3115 }
3116
3117 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3118
3119 result = _dbus_read (fd, str, n_bytes);
3120
3121 if (result != n_bytes)
3122 {
3123 if (result < 0)
3124 dbus_set_error (error, _dbus_error_from_errno (errno),
3125 "Could not read /dev/urandom: %s",
3126 _dbus_strerror (errno));
3127 else
3128 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
3129 "Short read from /dev/urandom");
3130
3131 _dbus_close (fd, NULL);
3132 _dbus_string_set_length (str, old_len);
3133 return FALSE;
3134 }
3135
3136 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3137 n_bytes);
3138
3139 _dbus_close (fd, NULL);
3140
3141 return TRUE;
3142 }
3143
3149 void
3150 _dbus_exit (int code)
3151 {
3152 _exit (code);
3153 }
3154
3163 const char*
3164 _dbus_strerror (int error_number)
3165 {
3166 const char *msg;
3167
3168 msg = strerror (error_number);
3169 if (msg == NULL)
3170 msg = "unknown";
3171
3172 return msg;
3173 }
3174
3178 void
3179 _dbus_disable_sigpipe (void)
3180 {
3181 signal (SIGPIPE, SIG_IGN);
3182 }
3183
3191 void
3192 _dbus_fd_set_close_on_exec (int fd)
3193 {
3194 int val;
3195
3196 val = fcntl (fd, F_GETFD, 0);
3197
3198 if (val < 0)
3199 return;
3200
3201 val |= FD_CLOEXEC;
3202
3203 fcntl (fd, F_SETFD, val);
3204 }
3205
3213 dbus_bool_t
3214 _dbus_close (int fd,
3215 DBusError *error)
3216 {
3217 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3218
3219 again:
3220 if (close (fd) < 0)
3221 {
3222 if (errno == EINTR)
3223 goto again;
3224
3225 dbus_set_error (error, _dbus_error_from_errno (errno),
3226 "Could not close fd %d", fd);
3227 return FALSE;
3228 }
3229
3230 return TRUE;
3231 }
3232
3241 int
3242 _dbus_dup(int fd,
3243 DBusError *error)
3244 {
3245 int new_fd;
3246
3247 #ifdef F_DUPFD_CLOEXEC
3248 dbus_bool_t cloexec_done;
3249
3250 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3251 cloexec_done = new_fd >= 0;
3252
3253 if (new_fd < 0 && errno == EINVAL)
3254 #endif
3255 {
3256 new_fd = fcntl(fd, F_DUPFD, 3);
3257 }
3258
3259 if (new_fd < 0) {
3260
3261 dbus_set_error (error, _dbus_error_from_errno (errno),
3262 "Could not duplicate fd %d", fd);
3263 return -1;
3264 }
3265
3266 #ifdef F_DUPFD_CLOEXEC
3267 if (!cloexec_done)
3268 #endif
3269 {
3270 _dbus_fd_set_close_on_exec(new_fd);
3271 }
3272
3273 return new_fd;
3274 }
3275
3283 dbus_bool_t
3284 _dbus_set_socket_nonblocking (DBusSocket fd,
3285 DBusError *error)
3286 {
3287 return _dbus_set_fd_nonblocking (fd.fd, error);
3288 }
3289
3290 static dbus_bool_t
3291 _dbus_set_fd_nonblocking (int fd,
3292 DBusError *error)
3293 {
3294 int val;
3295
3296 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3297
3298 val = fcntl (fd, F_GETFL, 0);
3299 if (val < 0)
3300 {
3301 dbus_set_error (error, _dbus_error_from_errno (errno),
3302 "Failed to get flags from file descriptor %d: %s",
3303 fd, _dbus_strerror (errno));
3304 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3305 _dbus_strerror (errno));
3306 return FALSE;
3307 }
3308
3309 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3310 {
3311 dbus_set_error (error, _dbus_error_from_errno (errno),
3312 "Failed to set nonblocking flag of file descriptor %d: %s",
3313 fd, _dbus_strerror (errno));
3314 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3315 fd, _dbus_strerror (errno));
3316
3317 return FALSE;
3318 }
3319
3320 return TRUE;
3321 }
3322
3328 void
3329 _dbus_print_backtrace (void)
3330 {
3331 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3332 void *bt[500];
3333 int bt_size;
3334 int i;
3335 char **syms;
3336
3337 bt_size = backtrace (bt, 500);
3338
3339 syms = backtrace_symbols (bt, bt_size);
3340
3341 i = 0;
3342 while (i < bt_size)
3343 {
3344 /* don't use dbus_warn since it can _dbus_abort() */
3345 fprintf (stderr, " %s\n", syms[i]);
3346 ++i;
3347 }
3348 fflush (stderr);
3349
3350 free (syms);
3351 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3352 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3353 #else
3354 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3355 #endif
3356 }
3357
3370 dbus_bool_t
3371 _dbus_socketpair (DBusSocket *fd1,
3372 DBusSocket *fd2,
3373 dbus_bool_t blocking,
3374 DBusError *error)
3375 {
3376 #ifdef HAVE_SOCKETPAIR
3377 int fds[2];
3378 int retval;
3379
3380 #ifdef SOCK_CLOEXEC
3381 dbus_bool_t cloexec_done;
3382
3383 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3384 cloexec_done = retval >= 0;
3385
3386 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3387 #endif
3388 {
3389 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3390 }
3391
3392 if (retval < 0)
3393 {
3394 dbus_set_error (error, _dbus_error_from_errno (errno),
3395 "Could not create full-duplex pipe");
3396 return FALSE;
3397 }
3398
3399 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3400
3401 #ifdef SOCK_CLOEXEC
3402 if (!cloexec_done)
3403 #endif
3404 {
3405 _dbus_fd_set_close_on_exec (fds[0]);
3406 _dbus_fd_set_close_on_exec (fds[1]);
3407 }
3408
3409 if (!blocking &&
3410 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3411 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3412 {
3413 dbus_set_error (error, _dbus_error_from_errno (errno),
3414 "Could not set full-duplex pipe nonblocking");
3415
3416 _dbus_close (fds[0], NULL);
3417 _dbus_close (fds[1], NULL);
3418
3419 return FALSE;
3420 }
3421
3422 fd1->fd = fds[0];
3423 fd2->fd = fds[1];
3424
3425 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3426 fd1->fd, fd2->fd);
3427
3428 return TRUE;
3429 #else
3430 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3431 dbus_set_error (error, DBUS_ERROR_FAILED,
3432 "_dbus_socketpair() not implemented on this OS");
3433 return FALSE;
3434 #endif
3435 }
3436
3445 int
3446 _dbus_printf_string_upper_bound (const char *format,
3447 va_list args)
3448 {
3449 char static_buf[1024];
3450 int bufsize = sizeof (static_buf);
3451 int len;
3452 va_list args_copy;
3453
3454 DBUS_VA_COPY (args_copy, args);
3455 len = vsnprintf (static_buf, bufsize, format, args_copy);
3456 va_end (args_copy);
3457
3458 /* If vsnprintf() returned non-negative, then either the string fits in
3459 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3460 * returns the number of characters that were needed, or this OS returns the
3461 * truncated length.
3462 *
3463 * We ignore the possibility that snprintf might just ignore the length and
3464 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3465 * If your libc is really that bad, come back when you have a better one. */
3466 if (len == bufsize)
3467 {
3468 /* This could be the truncated length (Tru64 and IRIX have this bug),
3469 * or the real length could be coincidentally the same. Which is it?
3470 * If vsnprintf returns the truncated length, we'll go to the slow
3471 * path. */
3472 DBUS_VA_COPY (args_copy, args);
3473
3474 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3475 len = -1;
3476
3477 va_end (args_copy);
3478 }
3479
3480 /* If vsnprintf() returned negative, we have to do more work.
3481 * HP-UX returns negative. */
3482 while (len < 0)
3483 {
3484 char *buf;
3485
3486 bufsize *= 2;
3487
3488 buf = dbus_malloc (bufsize);
3489
3490 if (buf == NULL)
3491 return -1;
3492
3493 DBUS_VA_COPY (args_copy, args);
3494 len = vsnprintf (buf, bufsize, format, args_copy);
3495 va_end (args_copy);
3496
3497 dbus_free (buf);
3498
3499 /* If the reported length is exactly the buffer size, round up to the
3500 * next size, in case vsnprintf has been returning the truncated
3501 * length */
3502 if (len == bufsize)
3503 len = -1;
3504 }
3505
3506 return len;
3507 }
3508
3515 const char*
3516 _dbus_get_tmpdir(void)
3517 {
3518 /* Protected by _DBUS_LOCK_sysdeps */
3519 static const char* tmpdir = NULL;
3520
3521 if (!_DBUS_LOCK (sysdeps))
3522 return NULL;
3523
3524 if (tmpdir == NULL)
3525 {
3526 /* TMPDIR is what glibc uses, then
3527 * glibc falls back to the P_tmpdir macro which
3528 * just expands to "/tmp"
3529 */
3530 if (tmpdir == NULL)
3531 tmpdir = getenv("TMPDIR");
3532
3533 /* These two env variables are probably
3534 * broken, but maybe some OS uses them?
3535 */
3536 if (tmpdir == NULL)
3537 tmpdir = getenv("TMP");
3538 if (tmpdir == NULL)
3539 tmpdir = getenv("TEMP");
3540
3541 /* And this is the sane fallback. */
3542 if (tmpdir == NULL)
3543 tmpdir = "/tmp";
3544 }
3545
3546 _DBUS_UNLOCK (sysdeps);
3547
3548 _dbus_assert(tmpdir != NULL);
3549
3550 return tmpdir;
3551 }
3552
3553 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3554
3573 static dbus_bool_t
3574 _read_subprocess_line_argv (const char *progpath,
3575 dbus_bool_t path_fallback,
3576 const char * const *argv,
3577 DBusString *result,
3578 DBusError *error)
3579 {
3580 int result_pipe[2] = { -1, -1 };
3581 int errors_pipe[2] = { -1, -1 };
3582 pid_t pid;
3583 int ret;
3584 int status;
3585 int orig_len;
3586
3587 dbus_bool_t retval;
3588 sigset_t new_set, old_set;
3589
3590 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3591 retval = FALSE;
3592
3593 /* We need to block any existing handlers for SIGCHLD temporarily; they
3594 * will cause waitpid() below to fail.
3595 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3596 */
3597 sigemptyset (&new_set);
3598 sigaddset (&new_set, SIGCHLD);
3599 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3600
3601 orig_len = _dbus_string_get_length (result);
3602
3603 #define READ_END 0
3604 #define WRITE_END 1
3605 if (pipe (result_pipe) < 0)
3606 {
3607 dbus_set_error (error, _dbus_error_from_errno (errno),
3608 "Failed to create a pipe to call %s: %s",
3609 progpath, _dbus_strerror (errno));
3610 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3611 progpath, _dbus_strerror (errno));
3612 goto out;
3613 }
3614 if (pipe (errors_pipe) < 0)
3615 {
3616 dbus_set_error (error, _dbus_error_from_errno (errno),
3617 "Failed to create a pipe to call %s: %s",
3618 progpath, _dbus_strerror (errno));
3619 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3620 progpath, _dbus_strerror (errno));
3621 goto out;
3622 }
3623
3624 pid = fork ();
3625 if (pid < 0)
3626 {
3627 dbus_set_error (error, _dbus_error_from_errno (errno),
3628 "Failed to fork() to call %s: %s",
3629 progpath, _dbus_strerror (errno));
3630 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3631 progpath, _dbus_strerror (errno));
3632 goto out;
3633 }
3634
3635 if (pid == 0)
3636 {
3637 /* child process */
3638 const char *error_str;
3639
3640 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
3641 {
3642 int saved_errno = errno;
3643
3644 /* Try to write details into the pipe, but don't bother
3645 * trying too hard (no retry loop). */
3646
3647 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
3648 write (errors_pipe[WRITE_END], ": ", 2) < 0)
3649 {
3650 /* ignore, not much we can do */
3651 }
3652
3653 error_str = _dbus_strerror (saved_errno);
3654
3655 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
3656 {
3657 /* ignore, not much we can do */
3658 }
3659
3660 _exit (1);
3661 }
3662
3663 /* set-up stdXXX */
3664 close (result_pipe[READ_END]);
3665 close (errors_pipe[READ_END]);
3666
3667 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3668 _exit (1);
3669 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3670 _exit (1);
3671
3672 _dbus_close_all ();
3673
3674 sigprocmask (SIG_SETMASK, &old_set, NULL);
3675
3676 /* If it looks fully-qualified, try execv first */
3677 if (progpath[0] == '/')
3678 {
3679 execv (progpath, (char * const *) argv);
3680 /* Ok, that failed. Now if path_fallback is given, let's
3681 * try unqualified. This is mostly a hack to work
3682 * around systems which ship dbus-launch in /usr/bin
3683 * but everything else in /bin (because dbus-launch
3684 * depends on X11).
3685 */
3686 if (path_fallback)
3687 /* We must have a slash, because we checked above */
3688 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
3689 }
3690 else
3691 execvp (progpath, (char * const *) argv);
3692
3693 /* still nothing, we failed */
3694 _exit (1);
3695 }
3696
3697 /* parent process */
3698 close (result_pipe[WRITE_END]);
3699 close (errors_pipe[WRITE_END]);
3700 result_pipe[WRITE_END] = -1;
3701 errors_pipe[WRITE_END] = -1;
3702
3703 ret = 0;
3704 do
3705 {
3706 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3707 }
3708 while (ret > 0);
3709
3710 /* reap the child process to avoid it lingering as zombie */
3711 do
3712 {
3713 ret = waitpid (pid, &status, 0);
3714 }
3715 while (ret == -1 && errno == EINTR);
3716
3717 /* We succeeded if the process exited with status 0 and
3718 anything was read */
3719 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3720 {
3721 /* The process ended with error */
3722 DBusString error_message;
3723 if (!_dbus_string_init (&error_message))
3724 {
3725 _DBUS_SET_OOM (error);
3726 goto out;
3727 }
3728
3729 ret = 0;
3730 do
3731 {
3732 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3733 }
3734 while (ret > 0);
3735
3736 _dbus_string_set_length (result, orig_len);
3737 if (_dbus_string_get_length (&error_message) > 0)
3738 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3739 "%s terminated abnormally with the following error: %s",
3740 progpath, _dbus_string_get_data (&error_message));
3741 else
3742 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3743 "%s terminated abnormally without any error message",
3744 progpath);
3745 goto out;
3746 }
3747
3748 retval = TRUE;
3749
3750 out:
3751 sigprocmask (SIG_SETMASK, &old_set, NULL);
3752
3753 if (retval)
3754 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3755 else
3756 _DBUS_ASSERT_ERROR_IS_SET (error);
3757
3758 if (result_pipe[0] != -1)
3759 close (result_pipe[0]);
3760 if (result_pipe[1] != -1)
3761 close (result_pipe[1]);
3762 if (errors_pipe[0] != -1)
3763 close (errors_pipe[0]);
3764 if (errors_pipe[1] != -1)
3765 close (errors_pipe[1]);
3766
3767 return retval;
3768 }
3769 #endif
3770
3783 dbus_bool_t
3784 _dbus_get_autolaunch_address (const char *scope,
3785 DBusString *address,
3786 DBusError *error)
3787 {
3788 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3789 static const char arg_dbus_launch[] = "dbus-launch";
3790 static const char arg_autolaunch[] = "--autolaunch";
3791 static const char arg_binary_syntax[] = "--binary-syntax";
3792 static const char arg_close_stderr[] = "--close-stderr";
3793
3794 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3795 * but that's done elsewhere, and if it worked, this function wouldn't
3796 * be called.) */
3797 const char *display;
3798 const char *progpath;
3799 const char *argv[6];
3800 int i;
3801 DBusString uuid;
3802 dbus_bool_t retval;
3803
3804 if (_dbus_check_setuid ())
3805 {
3806 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3807 "Unable to autolaunch when setuid");
3808 return FALSE;
3809 }
3810
3811 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3812 retval = FALSE;
3813
3814 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3815 * dbus-launch-x11 is just going to fail. Rather than trying to
3816 * run it, we might as well bail out early with a nice error.
3817 *
3818 * This is not strictly true in a world where the user bus exists,
3819 * because dbus-launch --autolaunch knows how to connect to that -
3820 * but if we were going to connect to the user bus, we'd have done
3821 * so before trying autolaunch: in any case. */
3822 display = _dbus_getenv ("DISPLAY");
3823
3824 if (display == NULL || display[0] == '\0')
3825 {
3826 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3827 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3828 return FALSE;
3829 }
3830
3831 if (!_dbus_string_init (&uuid))
3832 {
3833 _DBUS_SET_OOM (error);
3834 return FALSE;
3835 }
3836
3837 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3838 {
3839 goto out;
3840 }
3841
3842 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3843 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
3844
3845 if (progpath == NULL)
3846 #endif
3847 progpath = DBUS_BINDIR "/dbus-launch";
3848 /*
3849 * argv[0] is always dbus-launch, that's the name what we'll
3850 * get from /proc, or ps(1), regardless what the progpath is,
3851 * see fd.o#69716
3852 */
3853 i = 0;
3854 argv[i] = arg_dbus_launch;
3855 ++i;
3856 argv[i] = arg_autolaunch;
3857 ++i;
3858 argv[i] = _dbus_string_get_data (&uuid);
3859 ++i;
3860 argv[i] = arg_binary_syntax;
3861 ++i;
3862 argv[i] = arg_close_stderr;
3863 ++i;
3864 argv[i] = NULL;
3865 ++i;
3866
3867 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3868
3869 retval = _read_subprocess_line_argv (progpath,
3870 TRUE,
3871 argv, address, error);
3872
3873 out:
3874 _dbus_string_free (&uuid);
3875 return retval;
3876 #else
3877 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3878 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3879 "set your DBUS_SESSION_BUS_ADDRESS instead");
3880 return FALSE;
3881 #endif
3882 }
3883
3902 dbus_bool_t
3903 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3904 dbus_bool_t create_if_not_found,
3905 DBusError *error)
3906 {
3907 DBusError our_error = DBUS_ERROR_INIT;
3908 DBusError etc_error = DBUS_ERROR_INIT;
3909 DBusString filename;
3910 dbus_bool_t b;
3911
3912 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3913
3914 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
3915 if (b)
3916 return TRUE;
3917
3918 /* Fallback to the system machine ID */
3919 _dbus_string_init_const (&filename, "/etc/machine-id");
3920 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
3921
3922 if (b)
3923 {
3924 if (create_if_not_found)
3925 {
3926 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3927 * complain if that isn't possible for whatever reason */
3928 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3929 _dbus_write_uuid_file (&filename, machine_id, NULL);
3930 }
3931
3932 dbus_error_free (&our_error);
3933 return TRUE;
3934 }
3935
3936 if (!create_if_not_found)
3937 {
3938 dbus_set_error (error, etc_error.name,
3939 "D-Bus library appears to be incorrectly set up: "
3940 "see the manual page for dbus-uuidgen to correct "
3941 "this issue. (%s; %s)",
3942 our_error.message, etc_error.message);
3943 dbus_error_free (&our_error);
3944 dbus_error_free (&etc_error);
3945 return FALSE;
3946 }
3947
3948 dbus_error_free (&our_error);
3949 dbus_error_free (&etc_error);
3950
3951 /* if none found, try to make a new one */
3952 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3953
3954 if (!_dbus_generate_uuid (machine_id, error))
3955 return FALSE;
3956
3957 return _dbus_write_uuid_file (&filename, machine_id, error);
3958 }
3959
3967 dbus_bool_t
3968 _dbus_lookup_launchd_socket (DBusString *socket_path,
3969 const char *launchd_env_var,
3970 DBusError *error)
3971 {
3972 #ifdef DBUS_ENABLE_LAUNCHD
3973 char *argv[4];
3974 int i;
3975
3976 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3977
3978 if (_dbus_check_setuid ())
3979 {
3980 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3981 "Unable to find launchd socket when setuid");
3982 return FALSE;
3983 }
3984
3985 i = 0;
3986 argv[i] = "launchctl";
3987 ++i;
3988 argv[i] = "getenv";
3989 ++i;
3990 argv[i] = (char*)launchd_env_var;
3991 ++i;
3992 argv[i] = NULL;
3993 ++i;
3994
3995 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3996
3997 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
3998 {
3999 return FALSE;
4000 }
4001
4002 /* no error, but no result either */
4003 if (_dbus_string_get_length(socket_path) == 0)
4004 {
4005 return FALSE;
4006 }
4007
4008 /* strip the carriage-return */
4009 _dbus_string_shorten(socket_path, 1);
4010 return TRUE;
4011 #else /* DBUS_ENABLE_LAUNCHD */
4012 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
4013 "can't lookup socket from launchd; launchd support not compiled in");
4014 return FALSE;
4015 #endif
4016 }
4017
4018 #ifdef DBUS_ENABLE_LAUNCHD
4019 static dbus_bool_t
4020 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4021 {
4022 dbus_bool_t valid_socket;
4023 DBusString socket_path;
4024
4025 if (_dbus_check_setuid ())
4026 {
4027 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4028 "Unable to find launchd socket when setuid");
4029 return FALSE;
4030 }
4031
4032 if (!_dbus_string_init (&socket_path))
4033 {
4034 _DBUS_SET_OOM (error);
4035 return FALSE;
4036 }
4037
4038 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4039
4040 if (dbus_error_is_set(error))
4041 {
4042 _dbus_string_free(&socket_path);
4043 return FALSE;
4044 }
4045
4046 if (!valid_socket)
4047 {
4048 dbus_set_error(error, "no socket path",
4049 "launchd did not provide a socket path, "
4050 "verify that org.freedesktop.dbus-session.plist is loaded!");
4051 _dbus_string_free(&socket_path);
4052 return FALSE;
4053 }
4054 if (!_dbus_string_append (address, "unix:path="))
4055 {
4056 _DBUS_SET_OOM (error);
4057 _dbus_string_free(&socket_path);
4058 return FALSE;
4059 }
4060 if (!_dbus_string_copy (&socket_path, 0, address,
4061 _dbus_string_get_length (address)))
4062 {
4063 _DBUS_SET_OOM (error);
4064 _dbus_string_free(&socket_path);
4065 return FALSE;
4066 }
4067
4068 _dbus_string_free(&socket_path);
4069 return TRUE;
4070 }
4071 #endif
4072
4073 dbus_bool_t
4074 _dbus_lookup_user_bus (dbus_bool_t *supported,
4075 DBusString *address,
4076 DBusError *error)
4077 {
4078 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4079 dbus_bool_t ret = FALSE;
4080 struct stat stbuf;
4081 DBusString user_bus_path;
4082
4083 if (runtime_dir == NULL)
4084 {
4085 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4086 *supported = FALSE;
4087 return TRUE; /* Cannot use it, but not an error */
4088 }
4089
4090 if (!_dbus_string_init (&user_bus_path))
4091 {
4092 _DBUS_SET_OOM (error);
4093 return FALSE;
4094 }
4095
4096 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4097 {
4098 _DBUS_SET_OOM (error);
4099 goto out;
4100 }
4101
4102 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4103 {
4104 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4105 _dbus_strerror (errno));
4106 *supported = FALSE;
4107 ret = TRUE; /* Cannot use it, but not an error */
4108 goto out;
4109 }
4110
4111 if (stbuf.st_uid != getuid ())
4112 {
4113 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4114 (long) stbuf.st_uid, (long) getuid ());
4115 *supported = FALSE;
4116 ret = TRUE; /* Cannot use it, but not an error */
4117 goto out;
4118 }
4119
4120 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4121 {
4122 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4123 (long) stbuf.st_mode);
4124 *supported = FALSE;
4125 ret = TRUE; /* Cannot use it, but not an error */
4126 goto out;
4127 }
4128
4129 if (!_dbus_string_append (address, "unix:path=") ||
4130 !_dbus_address_append_escaped (address, &user_bus_path))
4131 {
4132 _DBUS_SET_OOM (error);
4133 goto out;
4134 }
4135
4136 *supported = TRUE;
4137 ret = TRUE;
4138
4139 out:
4140 _dbus_string_free (&user_bus_path);
4141 return ret;
4142 }
4143
4163 dbus_bool_t
4164 _dbus_lookup_session_address (dbus_bool_t *supported,
4165 DBusString *address,
4166 DBusError *error)
4167 {
4168 #ifdef DBUS_ENABLE_LAUNCHD
4169 *supported = TRUE;
4170 return _dbus_lookup_session_address_launchd (address, error);
4171 #else
4172 *supported = FALSE;
4173
4174 if (!_dbus_lookup_user_bus (supported, address, error))
4175 return FALSE;
4176 else if (*supported)
4177 return TRUE;
4178
4179 /* On non-Mac Unix platforms, if the session address isn't already
4180 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4181 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4182 * autolaunch: global default; see init_session_address in
4183 * dbus/dbus-bus.c. */
4184 return TRUE;
4185 #endif
4186 }
4187
4195 void
4196 _dbus_flush_caches (void)
4197 {
4198 _dbus_user_database_flush_system ();
4199 }
4200
4214 dbus_bool_t
4215 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
4216 DBusCredentials *credentials)
4217 {
4218 DBusString homedir;
4219 DBusString dotdir;
4220 dbus_uid_t uid;
4221
4222 _dbus_assert (credentials != NULL);
4223 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
4224
4225 if (!_dbus_string_init (&homedir))
4226 return FALSE;
4227
4228 uid = _dbus_credentials_get_unix_uid (credentials);
4229 _dbus_assert (uid != DBUS_UID_UNSET);
4230
4231 if (!_dbus_homedir_from_uid (uid, &homedir))
4232 goto failed;
4233
4234 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4235 {
4236 const char *override;
4237
4238 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4239 if (override != NULL && *override != '\0')
4240 {
4241 _dbus_string_set_length (&homedir, 0);
4242 if (!_dbus_string_append (&homedir, override))
4243 goto failed;
4244
4245 _dbus_verbose ("Using fake homedir for testing: %s\n",
4246 _dbus_string_get_const_data (&homedir));
4247 }
4248 else
4249 {
4250 /* Not strictly thread-safe, but if we fail at thread-safety here,
4251 * the worst that will happen is some extra warnings. */
4252 static dbus_bool_t already_warned = FALSE;
4253 if (!already_warned)
4254 {
4255 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4256 _dbus_string_get_const_data (&homedir));
4257 already_warned = TRUE;
4258 }
4259 }
4260 }
4261 #endif
4262
4263 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4264 if (!_dbus_concat_dir_and_file (&homedir,
4265 &dotdir))
4266 goto failed;
4267
4268 if (!_dbus_string_copy (&homedir, 0,
4269 directory, _dbus_string_get_length (directory))) {
4270 goto failed;
4271 }
4272
4273 _dbus_string_free (&homedir);
4274 return TRUE;
4275
4276 failed:
4277 _dbus_string_free (&homedir);
4278 return FALSE;
4279 }
4280
4281 //PENDING(kdab) docs
4282 dbus_bool_t
4283 _dbus_daemon_publish_session_bus_address (const char* addr,
4284 const char *scope)
4285 {
4286 return TRUE;
4287 }
4288
4289 //PENDING(kdab) docs
4290 void
4291 _dbus_daemon_unpublish_session_bus_address (void)
4292 {
4293
4294 }
4295
4302 dbus_bool_t
4303 _dbus_get_is_errno_eagain_or_ewouldblock (int e)
4304 {
4305 return e == EAGAIN || e == EWOULDBLOCK;
4306 }
4307
4315 dbus_bool_t
4316 _dbus_delete_directory (const DBusString *filename,
4317 DBusError *error)
4318 {
4319 const char *filename_c;
4320
4321 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4322
4323 filename_c = _dbus_string_get_const_data (filename);
4324
4325 if (rmdir (filename_c) != 0)
4326 {
4327 dbus_set_error (error, DBUS_ERROR_FAILED,
4328 "Failed to remove directory %s: %s\n",
4329 filename_c, _dbus_strerror (errno));
4330 return FALSE;
4331 }
4332
4333 return TRUE;
4334 }
4335
4343 dbus_bool_t
4344 _dbus_socket_can_pass_unix_fd (DBusSocket fd)
4345 {
4346 #ifdef SCM_RIGHTS
4347 union {
4348 struct sockaddr sa;
4349 struct sockaddr_storage storage;
4350 struct sockaddr_un un;
4351 } sa_buf;
4352
4353 socklen_t sa_len = sizeof(sa_buf);
4354
4355 _DBUS_ZERO(sa_buf);
4356
4357 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4358 return FALSE;
4359
4360 return sa_buf.sa.sa_family == AF_UNIX;
4361
4362 #else
4363 return FALSE;
4364
4365 #endif
4366 }
4367
4372 void
4373 _dbus_close_all (void)
4374 {
4375 int maxfds, i;
4376
4377 #ifdef __linux__
4378 DIR *d;
4379
4380 /* On Linux we can optimize this a bit if /proc is available. If it
4381 isn't available, fall back to the brute force way. */
4382
4383 d = opendir ("/proc/self/fd");
4384 if (d)
4385 {
4386 for (;;)
4387 {
4388 struct dirent *de;
4389 int fd;
4390 long l;
4391 char *e = NULL;
4392
4393 de = readdir (d);
4394 if (!de)
4395 break;
4396
4397 if (de->d_name[0] == '.')
4398 continue;
4399
4400 errno = 0;
4401 l = strtol (de->d_name, &e, 10);
4402 if (errno != 0 || e == NULL || *e != '\0')
4403 continue;
4404
4405 fd = (int) l;
4406 if (fd < 3)
4407 continue;
4408
4409 if (fd == dirfd (d))
4410 continue;
4411
4412 close (fd);
4413 }
4414
4415 closedir (d);
4416 return;
4417 }
4418 #endif
4419
4420 maxfds = sysconf (_SC_OPEN_MAX);
4421
4422 /* Pick something reasonable if for some reason sysconf says
4423 * unlimited.
4424 */
4425 if (maxfds < 0)
4426 maxfds = 1024;
4427
4428 /* close all inherited fds */
4429 for (i = 3; i < maxfds; i++)
4430 close (i);
4431 }
4432
4442 dbus_bool_t
4443 _dbus_check_setuid (void)
4444 {
4445 /* TODO: get __libc_enable_secure exported from glibc.
4446 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4447 */
4448 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4449 {
4450 /* See glibc/include/unistd.h */
4451 extern int __libc_enable_secure;
4452 return __libc_enable_secure;
4453 }
4454 #elif defined(HAVE_ISSETUGID)
4455 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4456 return issetugid ();
4457 #else
4458 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4459 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4460
4461 /* We call into this function from _dbus_threads_init_platform_specific()
4462 * to make sure these are initialized before we start threading. */
4463 static dbus_bool_t check_setuid_initialised;
4464 static dbus_bool_t is_setuid;
4465
4466 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4467 {
4468 #ifdef HAVE_GETRESUID
4469 if (getresuid (&ruid, &euid, &suid) != 0 ||
4470 getresgid (&rgid, &egid, &sgid) != 0)
4471 #endif /* HAVE_GETRESUID */
4472 {
4473 suid = ruid = getuid ();
4474 sgid = rgid = getgid ();
4475 euid = geteuid ();
4476 egid = getegid ();
4477 }
4478
4479 check_setuid_initialised = TRUE;
4480 is_setuid = (ruid != euid || ruid != suid ||
4481 rgid != egid || rgid != sgid);
4482
4483 }
4484 return is_setuid;
4485 #endif
4486 }
4487
4495 dbus_bool_t
4496 _dbus_append_address_from_socket (DBusSocket fd,
4497 DBusString *address,
4498 DBusError *error)
4499 {
4500 union {
4501 struct sockaddr sa;
4502 struct sockaddr_storage storage;
4503 struct sockaddr_un un;
4504 struct sockaddr_in ipv4;
4505 struct sockaddr_in6 ipv6;
4506 } socket;
4507 char hostip[INET6_ADDRSTRLEN];
4508 socklen_t size = sizeof (socket);
4509 DBusString path_str;
4510
4511 if (getsockname (fd.fd, &socket.sa, &size))
4512 goto err;
4513
4514 switch (socket.sa.sa_family)
4515 {
4516 case AF_UNIX:
4517 if (socket.un.sun_path[0]=='\0')
4518 {
4519 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4520 if (_dbus_string_append (address, "unix:abstract=") &&
4521 _dbus_address_append_escaped (address, &path_str))
4522 return TRUE;
4523 }
4524 else
4525 {
4526 _dbus_string_init_const (&path_str, socket.un.sun_path);
4527 if (_dbus_string_append (address, "unix:path=") &&
4528 _dbus_address_append_escaped (address, &path_str))
4529 return TRUE;
4530 }
4531 break;
4532 case AF_INET:
4533 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4534 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4535 hostip, ntohs (socket.ipv4.sin_port)))
4536 return TRUE;
4537 break;
4538 #ifdef AF_INET6
4539 case AF_INET6:
4540 _dbus_string_init_const (&path_str, hostip);
4541 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4542 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4543 ntohs (socket.ipv6.sin6_port)) &&
4544 _dbus_address_append_escaped (address, &path_str))
4545 return TRUE;
4546 break;
4547 #endif
4548 default:
4549 dbus_set_error (error,
4550 _dbus_error_from_errno (EINVAL),
4551 "Failed to read address from socket: Unknown socket type.");
4552 return FALSE;
4553 }
4554 err:
4555 dbus_set_error (error,
4556 _dbus_error_from_errno (errno),
4557 "Failed to open socket: %s",
4558 _dbus_strerror (errno));
4559 return FALSE;
4560 }
4561
4562 int
4563 _dbus_save_socket_errno (void)
4564 {
4565 return errno;
4566 }
4567
4568 void
4569 _dbus_restore_socket_errno (int saved_errno)
4570 {
4571 errno = saved_errno;
4572 }
4573
4574 static const char *syslog_tag = "dbus";
4575 #ifdef HAVE_SYSLOG_H
4576 static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4577 #endif
4578
4593 void
4594 _dbus_init_system_log (const char *tag,
4595 DBusLogFlags flags)
4596 {
4597 /* We never want to turn off logging completely */
4598 _dbus_assert (
4599 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
4600
4601 syslog_tag = tag;
4602
4603 #ifdef HAVE_SYSLOG_H
4604 log_flags = flags;
4605
4606 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4607 openlog (tag, LOG_PID, LOG_DAEMON);
4608 #endif
4609 }
4610
4618 void
4619 _dbus_logv (DBusSystemLogSeverity severity,
4620 const char *msg,
4621 va_list args)
4622 {
4623 va_list tmp;
4624 #ifdef HAVE_SYSLOG_H
4625 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4626 {
4627 int flags;
4628 switch (severity)
4629 {
4630 case DBUS_SYSTEM_LOG_INFO:
4631 flags = LOG_DAEMON | LOG_INFO;
4632 break;
4633 case DBUS_SYSTEM_LOG_WARNING:
4634 flags = LOG_DAEMON | LOG_WARNING;
4635 break;
4636 case DBUS_SYSTEM_LOG_SECURITY:
4637 flags = LOG_AUTH | LOG_NOTICE;
4638 break;
4639 case DBUS_SYSTEM_LOG_ERROR:
4640 flags = LOG_DAEMON|LOG_CRIT;
4641 break;
4642 default:
4643 _dbus_assert_not_reached ("invalid log severity");
4644 }
4645
4646 DBUS_VA_COPY (tmp, args);
4647 vsyslog (flags, msg, tmp);
4648 va_end (tmp);
4649 }
4650
4651 /* If we don't have syslog.h, we always behave as though stderr was in
4652 * the flags */
4653 if (log_flags & DBUS_LOG_FLAGS_STDERR)
4654 #endif
4655 {
4656 DBUS_VA_COPY (tmp, args);
4657 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
4658 vfprintf (stderr, msg, tmp);
4659 fputc ('\n', stderr);
4660 va_end (tmp);
4661 }
4662 }
4663
4664 /* 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:280
_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&#39;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:285
_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:2276
_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&#39;re running on from the dbus configuration.
Definition: dbus-sysdeps-unix.c:3903
_dbus_close_all
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:4373
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_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:2957
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:3371
_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&#39;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:58
DBUS_GID_FORMAT
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
Definition: dbus-sysdeps.h:124
DBUS_PID_FORMAT
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:120
_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:4496
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:4443
_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&#39;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:371
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:2663
_DBUS_POLLIN
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:379
_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:3020
_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:3242
_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:374
_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&#39;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:113
_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:2200
_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:115
_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:2706
_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:3784
_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:2589
_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:106
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:149
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:3968
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:2652
_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:4303
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:1237
_DBUS_POLLOUT
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:383
_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:2221
_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:2754
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:3329
_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:4215
_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:1886
_dbus_create_directory
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
Definition: dbus-sysdeps-unix.c:2989
_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:4316
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:2904
_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:1462
_dbus_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition: dbus-sysdeps-unix.c:3179
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:4196
_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:1005
_dbus_get_tmpdir
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory by inspecting the environment variables TMPDIR, TMP, and TEMP in that order.
Definition: dbus-sysdeps-unix.c:3516
_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:117
_dbus_geteuid
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
Definition: dbus-sysdeps-unix.c:2681
_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:2622
TRUE
#define TRUE
Expands to "1".
DBusPollFD::fd
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:373
_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:122
_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:3150
_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:2693
_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:3192
_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:1337
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:2777
_dbus_getuid
dbus_uid_t _dbus_getuid(void)
Gets our UID.
Definition: dbus-sysdeps-unix.c:2672
_dbus_init_system_log
void _dbus_init_system_log(const char *tag, DBusLogFlags flags)
Initialize the system log.
Definition: dbus-sysdeps-unix.c:4594
_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:3095
_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:2606
_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:3284
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:4164
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3214
_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:4619
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:2801
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition: dbus-sysdeps-unix.c:3065
_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:110
_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:3446
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:4344
_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:108
_dbus_poll
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
Definition: dbus-sysdeps-unix.c:2826
DBusPollFD::revents
short revents
Events that occurred.
Definition: dbus-sysdeps.h:375
_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:1111
_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:2935
DBusUserInfo
Information about a UNIX user.
Definition: dbus-sysdeps-unix.h:106
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:385