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

D-Bus 1.10.18

dbus-sysdeps-unix.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #include <config.h>
26
27 #include "dbus-internals.h"
28 #include "dbus-sysdeps.h"
29 #include "dbus-sysdeps-unix.h"
30 #include "dbus-threads.h"
31 #include "dbus-protocol.h"
32 #include "dbus-file.h"
33 #include "dbus-transport.h"
34 #include "dbus-string.h"
35 #include "dbus-userdb.h"
36 #include "dbus-list.h"
37 #include "dbus-credentials.h"
38 #include "dbus-nonce.h"
39
40 #include <sys/types.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <fcntl.h>
47 #include <sys/socket.h>
48 #include <dirent.h>
49 #include <sys/un.h>
50 #include <pwd.h>
51 #include <time.h>
52 #include <locale.h>
53 #include <sys/time.h>
54 #include <sys/stat.h>
55 #include <sys/wait.h>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <netdb.h>
59 #include <grp.h>
60 #include <arpa/inet.h>
61
62 #ifdef HAVE_ERRNO_H
63 #include <errno.h>
64 #endif
65 #ifdef HAVE_WRITEV
66 #include <sys/uio.h>
67 #endif
68 #ifdef HAVE_POLL
69 #include <sys/poll.h>
70 #endif
71 #ifdef HAVE_BACKTRACE
72 #include <execinfo.h>
73 #endif
74 #ifdef HAVE_GETPEERUCRED
75 #include <ucred.h>
76 #endif
77 #ifdef HAVE_ALLOCA_H
78 #include <alloca.h>
79 #endif
80
81 #ifdef HAVE_ADT
82 #include <bsm/adt.h>
83 #endif
84
85 #ifdef HAVE_SYSTEMD
86 #include <systemd/sd-daemon.h>
87 #endif
88
89 #if !DBUS_USE_SYNC
90 #include <pthread.h>
91 #endif
92
93 #ifndef O_BINARY
94 #define O_BINARY 0
95 #endif
96
97 #ifndef AI_ADDRCONFIG
98 #define AI_ADDRCONFIG 0
99 #endif
100
101 #ifndef HAVE_SOCKLEN_T
102 #define socklen_t int
103 #endif
104
105 #if defined (__sun) || defined (__sun__)
106 /*
107 * CMS_SPACE etc. definitions for Solaris < 10, based on
108 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
109 * via
110 * http://wiki.opencsw.org/porting-faq#toc10
111 *
112 * These are only redefined for Solaris, for now: if your OS needs these too,
113 * please file a bug. (Or preferably, improve your OS so they're not needed.)
114 */
115
116 # ifndef CMSG_ALIGN
117 # ifdef __sun__
118 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
119 # else
120 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
121 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
122 ~(sizeof (long) - 1))
123 # endif
124 # endif
125
126 # ifndef CMSG_SPACE
127 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
128 CMSG_ALIGN (len))
129 # endif
130
131 # ifndef CMSG_LEN
132 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
133 # endif
134
135 #endif /* Solaris */
136
151 dbus_bool_t
152 _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
153 const char **error_str_p)
154 {
155 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
156 DBUS_FORCE_STDOUT_NULL,
157 DBUS_FORCE_STDERR_NULL };
158 /* Should always get replaced with the real error before use */
159 const char *error_str = "Failed mysteriously";
160 int devnull = -1;
161 int saved_errno;
162 /* This function relies on the standard fds having their POSIX values. */
163 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
164 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
165 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
166 int i;
167
168 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
169 {
170 /* Because we rely on being single-threaded, and we want the
171 * standard fds to not be close-on-exec, we don't set it
172 * close-on-exec. */
173 if (devnull < i)
174 devnull = open ("/dev/null", O_RDWR);
175
176 if (devnull < 0)
177 {
178 error_str = "Failed to open /dev/null";
179 goto out;
180 }
181
182 /* We already opened all fds < i, so the only way this assertion
183 * could fail is if another thread closed one, and we document
184 * this function as not safe for multi-threading. */
185 _dbus_assert (devnull >= i);
186
187 if (devnull != i && (flags & relevant_flag[i]) != 0)
188 {
189 if (dup2 (devnull, i) < 0)
190 {
191 error_str = "Failed to dup2 /dev/null onto a standard fd";
192 goto out;
193 }
194 }
195 }
196
197 error_str = NULL;
198
199 out:
200 saved_errno = errno;
201
202 if (devnull > STDERR_FILENO)
203 close (devnull);
204
205 if (error_str_p != NULL)
206 *error_str_p = error_str;
207
208 errno = saved_errno;
209 return (error_str == NULL);
210 }
211
212 static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
213 DBusError *error);
214
215 static dbus_bool_t
216 _dbus_open_socket (int *fd_p,
217 int domain,
218 int type,
219 int protocol,
220 DBusError *error)
221 {
222 #ifdef SOCK_CLOEXEC
223 dbus_bool_t cloexec_done;
224
225 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
226 cloexec_done = *fd_p >= 0;
227
228 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
229 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
230 #endif
231 {
232 *fd_p = socket (domain, type, protocol);
233 }
234
235 if (*fd_p >= 0)
236 {
237 #ifdef SOCK_CLOEXEC
238 if (!cloexec_done)
239 #endif
240 {
241 _dbus_fd_set_close_on_exec(*fd_p);
242 }
243
244 _dbus_verbose ("socket fd %d opened\n", *fd_p);
245 return TRUE;
246 }
247 else
248 {
249 dbus_set_error(error,
250 _dbus_error_from_errno (errno),
251 "Failed to open socket: %s",
252 _dbus_strerror (errno));
253 return FALSE;
254 }
255 }
256
267 static dbus_bool_t
268 _dbus_open_unix_socket (int *fd,
269 DBusError *error)
270 {
271 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
272 }
273
282 dbus_bool_t
283 _dbus_close_socket (DBusSocket fd,
284 DBusError *error)
285 {
286 return _dbus_close (fd.fd, error);
287 }
288
298 int
299 _dbus_read_socket (DBusSocket fd,
300 DBusString *buffer,
301 int count)
302 {
303 return _dbus_read (fd.fd, buffer, count);
304 }
305
316 int
317 _dbus_write_socket (DBusSocket fd,
318 const DBusString *buffer,
319 int start,
320 int len)
321 {
322 #if HAVE_DECL_MSG_NOSIGNAL
323 const char *data;
324 int bytes_written;
325
326 data = _dbus_string_get_const_data_len (buffer, start, len);
327
328 again:
329
330 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
331
332 if (bytes_written < 0 && errno == EINTR)
333 goto again;
334
335 return bytes_written;
336
337 #else
338 return _dbus_write (fd.fd, buffer, start, len);
339 #endif
340 }
341
354 int
355 _dbus_read_socket_with_unix_fds (DBusSocket fd,
356 DBusString *buffer,
357 int count,
358 int *fds,
359 int *n_fds) {
360 #ifndef HAVE_UNIX_FD_PASSING
361 int r;
362
363 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
364 return r;
365
366 *n_fds = 0;
367 return r;
368
369 #else
370 int bytes_read;
371 int start;
372 struct msghdr m;
373 struct iovec iov;
374
375 _dbus_assert (count >= 0);
376 _dbus_assert (*n_fds >= 0);
377
378 start = _dbus_string_get_length (buffer);
379
380 if (!_dbus_string_lengthen (buffer, count))
381 {
382 errno = ENOMEM;
383 return -1;
384 }
385
386 _DBUS_ZERO(iov);
387 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
388 iov.iov_len = count;
389
390 _DBUS_ZERO(m);
391 m.msg_iov = &iov;
392 m.msg_iovlen = 1;
393
394 /* Hmm, we have no clue how long the control data will actually be
395 that is queued for us. The least we can do is assume that the
396 caller knows. Hence let's make space for the number of fds that
397 we shall read at max plus the cmsg header. */
398 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
399
400 /* It's probably safe to assume that systems with SCM_RIGHTS also
401 know alloca() */
402 m.msg_control = alloca(m.msg_controllen);
403 memset(m.msg_control, 0, m.msg_controllen);
404
405 /* Do not include the padding at the end when we tell the kernel
406 * how much we're willing to receive. This avoids getting
407 * the padding filled with additional fds that we weren't expecting,
408 * if a (potentially malicious) sender included them. (fd.o #83622) */
409 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
410
411 again:
412
413 bytes_read = recvmsg (fd.fd, &m, 0
414 #ifdef MSG_CMSG_CLOEXEC
415 |MSG_CMSG_CLOEXEC
416 #endif
417 );
418
419 if (bytes_read < 0)
420 {
421 if (errno == EINTR)
422 goto again;
423 else
424 {
425 /* put length back (note that this doesn't actually realloc anything) */
426 _dbus_string_set_length (buffer, start);
427 return -1;
428 }
429 }
430 else
431 {
432 struct cmsghdr *cm;
433 dbus_bool_t found = FALSE;
434
435 if (m.msg_flags & MSG_CTRUNC)
436 {
437 /* Hmm, apparently the control data was truncated. The bad
438 thing is that we might have completely lost a couple of fds
439 without chance to recover them. Hence let's treat this as a
440 serious error. */
441
442 errno = ENOSPC;
443 _dbus_string_set_length (buffer, start);
444 return -1;
445 }
446
447 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
448 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
449 {
450 size_t i;
451 int *payload = (int *) CMSG_DATA (cm);
452 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
453 size_t payload_len_fds = payload_len_bytes / sizeof (int);
454 size_t fds_to_use;
455
456 /* Every non-negative int fits in a size_t without truncation,
457 * and we already know that *n_fds is non-negative, so
458 * casting (size_t) *n_fds is OK */
459 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
460
461 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
462 {
463 /* The fds in the payload will fit in our buffer */
464 fds_to_use = payload_len_fds;
465 }
466 else
467 {
468 /* Too many fds in the payload. This shouldn't happen
469 * any more because we're setting m.msg_controllen to
470 * the exact number we can accept, but be safe and
471 * truncate. */
472 fds_to_use = (size_t) *n_fds;
473
474 /* Close the excess fds to avoid DoS: if they stayed open,
475 * someone could send us an extra fd per message
476 * and we'd eventually run out. */
477 for (i = fds_to_use; i < payload_len_fds; i++)
478 {
479 close (payload[i]);
480 }
481 }
482
483 memcpy (fds, payload, fds_to_use * sizeof (int));
484 found = TRUE;
485 /* This cannot overflow because we have chosen fds_to_use
486 * to be <= *n_fds */
487 *n_fds = (int) fds_to_use;
488
489 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
490 worked, hence we need to go through this list and set
491 CLOEXEC everywhere in any case */
492 for (i = 0; i < fds_to_use; i++)
493 _dbus_fd_set_close_on_exec(fds[i]);
494
495 break;
496 }
497
498 if (!found)
499 *n_fds = 0;
500
501 /* put length back (doesn't actually realloc) */
502 _dbus_string_set_length (buffer, start + bytes_read);
503
504 #if 0
505 if (bytes_read > 0)
506 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
507 #endif
508
509 return bytes_read;
510 }
511 #endif
512 }
513
514 int
515 _dbus_write_socket_with_unix_fds(DBusSocket fd,
516 const DBusString *buffer,
517 int start,
518 int len,
519 const int *fds,
520 int n_fds) {
521
522 #ifndef HAVE_UNIX_FD_PASSING
523
524 if (n_fds > 0) {
525 errno = ENOTSUP;
526 return -1;
527 }
528
529 return _dbus_write_socket(fd, buffer, start, len);
530 #else
531 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
532 #endif
533 }
534
535 int
536 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
537 const DBusString *buffer1,
538 int start1,
539 int len1,
540 const DBusString *buffer2,
541 int start2,
542 int len2,
543 const int *fds,
544 int n_fds) {
545
546 #ifndef HAVE_UNIX_FD_PASSING
547
548 if (n_fds > 0) {
549 errno = ENOTSUP;
550 return -1;
551 }
552
553 return _dbus_write_socket_two(fd,
554 buffer1, start1, len1,
555 buffer2, start2, len2);
556 #else
557
558 struct msghdr m;
559 struct cmsghdr *cm;
560 struct iovec iov[2];
561 int bytes_written;
562
563 _dbus_assert (len1 >= 0);
564 _dbus_assert (len2 >= 0);
565 _dbus_assert (n_fds >= 0);
566
567 _DBUS_ZERO(iov);
568 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
569 iov[0].iov_len = len1;
570
571 if (buffer2)
572 {
573 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
574 iov[1].iov_len = len2;
575 }
576
577 _DBUS_ZERO(m);
578 m.msg_iov = iov;
579 m.msg_iovlen = buffer2 ? 2 : 1;
580
581 if (n_fds > 0)
582 {
583 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
584 m.msg_control = alloca(m.msg_controllen);
585 memset(m.msg_control, 0, m.msg_controllen);
586
587 cm = CMSG_FIRSTHDR(&m);
588 cm->cmsg_level = SOL_SOCKET;
589 cm->cmsg_type = SCM_RIGHTS;
590 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
591 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
592 }
593
594 again:
595
596 bytes_written = sendmsg (fd.fd, &m, 0
597 #if HAVE_DECL_MSG_NOSIGNAL
598 |MSG_NOSIGNAL
599 #endif
600 );
601
602 if (bytes_written < 0 && errno == EINTR)
603 goto again;
604
605 #if 0
606 if (bytes_written > 0)
607 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
608 #endif
609
610 return bytes_written;
611 #endif
612 }
613
627 int
628 _dbus_write_socket_two (DBusSocket fd,
629 const DBusString *buffer1,
630 int start1,
631 int len1,
632 const DBusString *buffer2,
633 int start2,
634 int len2)
635 {
636 #if HAVE_DECL_MSG_NOSIGNAL
637 struct iovec vectors[2];
638 const char *data1;
639 const char *data2;
640 int bytes_written;
641 struct msghdr m;
642
643 _dbus_assert (buffer1 != NULL);
644 _dbus_assert (start1 >= 0);
645 _dbus_assert (start2 >= 0);
646 _dbus_assert (len1 >= 0);
647 _dbus_assert (len2 >= 0);
648
649 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
650
651 if (buffer2 != NULL)
652 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
653 else
654 {
655 data2 = NULL;
656 start2 = 0;
657 len2 = 0;
658 }
659
660 vectors[0].iov_base = (char*) data1;
661 vectors[0].iov_len = len1;
662 vectors[1].iov_base = (char*) data2;
663 vectors[1].iov_len = len2;
664
665 _DBUS_ZERO(m);
666 m.msg_iov = vectors;
667 m.msg_iovlen = data2 ? 2 : 1;
668
669 again:
670
671 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
672
673 if (bytes_written < 0 && errno == EINTR)
674 goto again;
675
676 return bytes_written;
677
678 #else
679 return _dbus_write_two (fd.fd, buffer1, start1, len1,
680 buffer2, start2, len2);
681 #endif
682 }
683
700 int
701 _dbus_read (int fd,
702 DBusString *buffer,
703 int count)
704 {
705 int bytes_read;
706 int start;
707 char *data;
708
709 _dbus_assert (count >= 0);
710
711 start = _dbus_string_get_length (buffer);
712
713 if (!_dbus_string_lengthen (buffer, count))
714 {
715 errno = ENOMEM;
716 return -1;
717 }
718
719 data = _dbus_string_get_data_len (buffer, start, count);
720
721 again:
722
723 bytes_read = read (fd, data, count);
724
725 if (bytes_read < 0)
726 {
727 if (errno == EINTR)
728 goto again;
729 else
730 {
731 /* put length back (note that this doesn't actually realloc anything) */
732 _dbus_string_set_length (buffer, start);
733 return -1;
734 }
735 }
736 else
737 {
738 /* put length back (doesn't actually realloc) */
739 _dbus_string_set_length (buffer, start + bytes_read);
740
741 #if 0
742 if (bytes_read > 0)
743 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
744 #endif
745
746 return bytes_read;
747 }
748 }
749
760 int
761 _dbus_write (int fd,
762 const DBusString *buffer,
763 int start,
764 int len)
765 {
766 const char *data;
767 int bytes_written;
768
769 data = _dbus_string_get_const_data_len (buffer, start, len);
770
771 again:
772
773 bytes_written = write (fd, data, len);
774
775 if (bytes_written < 0 && errno == EINTR)
776 goto again;
777
778 #if 0
779 if (bytes_written > 0)
780 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
781 #endif
782
783 return bytes_written;
784 }
785
806 int
807 _dbus_write_two (int fd,
808 const DBusString *buffer1,
809 int start1,
810 int len1,
811 const DBusString *buffer2,
812 int start2,
813 int len2)
814 {
815 _dbus_assert (buffer1 != NULL);
816 _dbus_assert (start1 >= 0);
817 _dbus_assert (start2 >= 0);
818 _dbus_assert (len1 >= 0);
819 _dbus_assert (len2 >= 0);
820
821 #ifdef HAVE_WRITEV
822 {
823 struct iovec vectors[2];
824 const char *data1;
825 const char *data2;
826 int bytes_written;
827
828 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
829
830 if (buffer2 != NULL)
831 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
832 else
833 {
834 data2 = NULL;
835 start2 = 0;
836 len2 = 0;
837 }
838
839 vectors[0].iov_base = (char*) data1;
840 vectors[0].iov_len = len1;
841 vectors[1].iov_base = (char*) data2;
842 vectors[1].iov_len = len2;
843
844 again:
845
846 bytes_written = writev (fd,
847 vectors,
848 data2 ? 2 : 1);
849
850 if (bytes_written < 0 && errno == EINTR)
851 goto again;
852
853 return bytes_written;
854 }
855 #else /* HAVE_WRITEV */
856 {
857 int ret1, ret2;
858
859 ret1 = _dbus_write (fd, buffer1, start1, len1);
860 if (ret1 == len1 && buffer2 != NULL)
861 {
862 ret2 = _dbus_write (fd, buffer2, start2, len2);
863 if (ret2 < 0)
864 ret2 = 0; /* we can't report an error as the first write was OK */
865
866 return ret1 + ret2;
867 }
868 else
869 return ret1;
870 }
871 #endif /* !HAVE_WRITEV */
872 }
873
874 #define _DBUS_MAX_SUN_PATH_LENGTH 99
875
905 int
906 _dbus_connect_unix_socket (const char *path,
907 dbus_bool_t abstract,
908 DBusError *error)
909 {
910 int fd;
911 size_t path_len;
912 struct sockaddr_un addr;
913
914 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
915
916 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
917 path, abstract);
918
919
920 if (!_dbus_open_unix_socket (&fd, error))
921 {
922 _DBUS_ASSERT_ERROR_IS_SET(error);
923 return -1;
924 }
925 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
926
927 _DBUS_ZERO (addr);
928 addr.sun_family = AF_UNIX;
929 path_len = strlen (path);
930
931 if (abstract)
932 {
933 #ifdef HAVE_ABSTRACT_SOCKETS
934 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
935 path_len++; /* Account for the extra nul byte added to the start of sun_path */
936
937 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
938 {
939 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
940 "Abstract socket name too long\n");
941 _dbus_close (fd, NULL);
942 return -1;
943 }
944
945 strncpy (&addr.sun_path[1], path, path_len);
946 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
947 #else /* HAVE_ABSTRACT_SOCKETS */
948 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
949 "Operating system does not support abstract socket namespace\n");
950 _dbus_close (fd, NULL);
951 return -1;
952 #endif /* ! HAVE_ABSTRACT_SOCKETS */
953 }
954 else
955 {
956 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
957 {
958 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
959 "Socket name too long\n");
960 _dbus_close (fd, NULL);
961 return -1;
962 }
963
964 strncpy (addr.sun_path, path, path_len);
965 }
966
967 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
968 {
969 dbus_set_error (error,
970 _dbus_error_from_errno (errno),
971 "Failed to connect to socket %s: %s",
972 path, _dbus_strerror (errno));
973
974 _dbus_close (fd, NULL);
975 return -1;
976 }
977
978 if (!_dbus_set_fd_nonblocking (fd, error))
979 {
980 _DBUS_ASSERT_ERROR_IS_SET (error);
981
982 _dbus_close (fd, NULL);
983 return -1;
984 }
985
986 return fd;
987 }
988
1001 int
1002 _dbus_connect_exec (const char *path,
1003 char *const argv[],
1004 DBusError *error)
1005 {
1006 int fds[2];
1007 pid_t pid;
1008 int retval;
1009 dbus_bool_t cloexec_done = 0;
1010
1011 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1012
1013 _dbus_verbose ("connecting to process %s\n", path);
1014
1015 #ifdef SOCK_CLOEXEC
1016 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1017 cloexec_done = (retval >= 0);
1018
1019 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1020 #endif
1021 {
1022 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1023 }
1024
1025 if (retval < 0)
1026 {
1027 dbus_set_error (error,
1028 _dbus_error_from_errno (errno),
1029 "Failed to create socket pair: %s",
1030 _dbus_strerror (errno));
1031 return -1;
1032 }
1033
1034 if (!cloexec_done)
1035 {
1036 _dbus_fd_set_close_on_exec (fds[0]);
1037 _dbus_fd_set_close_on_exec (fds[1]);
1038 }
1039
1040 pid = fork ();
1041 if (pid < 0)
1042 {
1043 dbus_set_error (error,
1044 _dbus_error_from_errno (errno),
1045 "Failed to fork() to call %s: %s",
1046 path, _dbus_strerror (errno));
1047 close (fds[0]);
1048 close (fds[1]);
1049 return -1;
1050 }
1051
1052 if (pid == 0)
1053 {
1054 /* child */
1055 close (fds[0]);
1056
1057 dup2 (fds[1], STDIN_FILENO);
1058 dup2 (fds[1], STDOUT_FILENO);
1059
1060 if (fds[1] != STDIN_FILENO &&
1061 fds[1] != STDOUT_FILENO)
1062 close (fds[1]);
1063
1064 /* Inherit STDERR and the controlling terminal from the
1065 parent */
1066
1067 _dbus_close_all ();
1068
1069 execvp (path, argv);
1070
1071 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1072
1073 _exit(1);
1074 }
1075
1076 /* parent */
1077 close (fds[1]);
1078
1079 if (!_dbus_set_fd_nonblocking (fds[0], error))
1080 {
1081 _DBUS_ASSERT_ERROR_IS_SET (error);
1082
1083 close (fds[0]);
1084 return -1;
1085 }
1086
1087 return fds[0];
1088 }
1089
1107 int
1108 _dbus_listen_unix_socket (const char *path,
1109 dbus_bool_t abstract,
1110 DBusError *error)
1111 {
1112 int listen_fd;
1113 struct sockaddr_un addr;
1114 size_t path_len;
1115
1116 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1117
1118 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1119 path, abstract);
1120
1121 if (!_dbus_open_unix_socket (&listen_fd, error))
1122 {
1123 _DBUS_ASSERT_ERROR_IS_SET(error);
1124 return -1;
1125 }
1126 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1127
1128 _DBUS_ZERO (addr);
1129 addr.sun_family = AF_UNIX;
1130 path_len = strlen (path);
1131
1132 if (abstract)
1133 {
1134 #ifdef HAVE_ABSTRACT_SOCKETS
1135 /* remember that abstract names aren't nul-terminated so we rely
1136 * on sun_path being filled in with zeroes above.
1137 */
1138 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1139 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1140
1141 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1142 {
1143 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1144 "Abstract socket name too long\n");
1145 _dbus_close (listen_fd, NULL);
1146 return -1;
1147 }
1148
1149 strncpy (&addr.sun_path[1], path, path_len);
1150 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1151 #else /* HAVE_ABSTRACT_SOCKETS */
1152 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1153 "Operating system does not support abstract socket namespace\n");
1154 _dbus_close (listen_fd, NULL);
1155 return -1;
1156 #endif /* ! HAVE_ABSTRACT_SOCKETS */
1157 }
1158 else
1159 {
1160 /* Discussed security implications of this with Nalin,
1161 * and we couldn't think of where it would kick our ass, but
1162 * it still seems a bit sucky. It also has non-security suckage;
1163 * really we'd prefer to exit if the socket is already in use.
1164 * But there doesn't seem to be a good way to do this.
1165 *
1166 * Just to be extra careful, I threw in the stat() - clearly
1167 * the stat() can't *fix* any security issue, but it at least
1168 * avoids inadvertent/accidental data loss.
1169 */
1170 {
1171 struct stat sb;
1172
1173 if (stat (path, &sb) == 0 &&
1174 S_ISSOCK (sb.st_mode))
1175 unlink (path);
1176 }
1177
1178 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1179 {
1180 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1181 "Socket name too long\n");
1182 _dbus_close (listen_fd, NULL);
1183 return -1;
1184 }
1185
1186 strncpy (addr.sun_path, path, path_len);
1187 }
1188
1189 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1190 {
1191 dbus_set_error (error, _dbus_error_from_errno (errno),
1192 "Failed to bind socket \"%s\": %s",
1193 path, _dbus_strerror (errno));
1194 _dbus_close (listen_fd, NULL);
1195 return -1;
1196 }
1197
1198 if (listen (listen_fd, 30 /* backlog */) < 0)
1199 {
1200 dbus_set_error (error, _dbus_error_from_errno (errno),
1201 "Failed to listen on socket \"%s\": %s",
1202 path, _dbus_strerror (errno));
1203 _dbus_close (listen_fd, NULL);
1204 return -1;
1205 }
1206
1207 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1208 {
1209 _DBUS_ASSERT_ERROR_IS_SET (error);
1210 _dbus_close (listen_fd, NULL);
1211 return -1;
1212 }
1213
1214 /* Try opening up the permissions, but if we can't, just go ahead
1215 * and continue, maybe it will be good enough.
1216 */
1217 if (!abstract && chmod (path, 0777) < 0)
1218 _dbus_warn ("Could not set mode 0777 on socket %s\n",
1219 path);
1220
1221 return listen_fd;
1222 }
1223
1234 int
1235 _dbus_listen_systemd_sockets (DBusSocket **fds,
1236 DBusError *error)
1237 {
1238 #ifdef HAVE_SYSTEMD
1239 int r, n;
1240 int fd;
1241 DBusSocket *new_fds;
1242
1243 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1244
1245 n = sd_listen_fds (TRUE);
1246 if (n < 0)
1247 {
1248 dbus_set_error (error, _dbus_error_from_errno (-n),
1249 "Failed to acquire systemd socket: %s",
1250 _dbus_strerror (-n));
1251 return -1;
1252 }
1253
1254 if (n <= 0)
1255 {
1256 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1257 "No socket received.");
1258 return -1;
1259 }
1260
1261 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1262 {
1263 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1264 if (r < 0)
1265 {
1266 dbus_set_error (error, _dbus_error_from_errno (-r),
1267 "Failed to verify systemd socket type: %s",
1268 _dbus_strerror (-r));
1269 return -1;
1270 }
1271
1272 if (!r)
1273 {
1274 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1275 "Passed socket has wrong type.");
1276 return -1;
1277 }
1278 }
1279
1280 /* OK, the file descriptors are all good, so let's take posession of
1281 them then. */
1282
1283 new_fds = dbus_new (DBusSocket, n);
1284 if (!new_fds)
1285 {
1286 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1287 "Failed to allocate file handle array.");
1288 goto fail;
1289 }
1290
1291 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1292 {
1293 if (!_dbus_set_fd_nonblocking (fd, error))
1294 {
1295 _DBUS_ASSERT_ERROR_IS_SET (error);
1296 goto fail;
1297 }
1298
1299 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1300 }
1301
1302 *fds = new_fds;
1303 return n;
1304
1305 fail:
1306
1307 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1308 {
1309 _dbus_close (fd, NULL);
1310 }
1311
1312 dbus_free (new_fds);
1313 return -1;
1314 #else
1315 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
1316 "dbus was compiled without systemd support");
1317 return -1;
1318 #endif
1319 }
1320
1334 DBusSocket
1335 _dbus_connect_tcp_socket (const char *host,
1336 const char *port,
1337 const char *family,
1338 DBusError *error)
1339 {
1340 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1341 }
1342
1343 DBusSocket
1344 _dbus_connect_tcp_socket_with_nonce (const char *host,
1345 const char *port,
1346 const char *family,
1347 const char *noncefile,
1348 DBusError *error)
1349 {
1350 int saved_errno = 0;
1351 DBusSocket fd = DBUS_SOCKET_INIT;
1352 int res;
1353 struct addrinfo hints;
1354 struct addrinfo *ai, *tmp;
1355
1356 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1357
1358 _DBUS_ZERO (hints);
1359
1360 if (!family)
1361 hints.ai_family = AF_UNSPEC;
1362 else if (!strcmp(family, "ipv4"))
1363 hints.ai_family = AF_INET;
1364 else if (!strcmp(family, "ipv6"))
1365 hints.ai_family = AF_INET6;
1366 else
1367 {
1368 dbus_set_error (error,
1369 DBUS_ERROR_BAD_ADDRESS,
1370 "Unknown address family %s", family);
1371 return _dbus_socket_get_invalid ();
1372 }
1373 hints.ai_protocol = IPPROTO_TCP;
1374 hints.ai_socktype = SOCK_STREAM;
1375 hints.ai_flags = AI_ADDRCONFIG;
1376
1377 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1378 {
1379 dbus_set_error (error,
1380 _dbus_error_from_errno (errno),
1381 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1382 host, port, gai_strerror(res), res);
1383 return _dbus_socket_get_invalid ();
1384 }
1385
1386 tmp = ai;
1387 while (tmp)
1388 {
1389 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1390 {
1391 freeaddrinfo(ai);
1392 _DBUS_ASSERT_ERROR_IS_SET(error);
1393 return _dbus_socket_get_invalid ();
1394 }
1395 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1396
1397 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1398 {
1399 saved_errno = errno;
1400 _dbus_close (fd.fd, NULL);
1401 fd.fd = -1;
1402 tmp = tmp->ai_next;
1403 continue;
1404 }
1405
1406 break;
1407 }
1408 freeaddrinfo(ai);
1409
1410 if (fd.fd == -1)
1411 {
1412 dbus_set_error (error,
1413 _dbus_error_from_errno (saved_errno),
1414 "Failed to connect to socket \"%s:%s\" %s",
1415 host, port, _dbus_strerror(saved_errno));
1416 return _dbus_socket_get_invalid ();
1417 }
1418
1419 if (noncefile != NULL)
1420 {
1421 DBusString noncefileStr;
1422 dbus_bool_t ret;
1423 _dbus_string_init_const (&noncefileStr, noncefile);
1424 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1425 _dbus_string_free (&noncefileStr);
1426
1427 if (!ret)
1428 {
1429 _dbus_close (fd.fd, NULL);
1430 return _dbus_socket_get_invalid ();
1431 }
1432 }
1433
1434 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1435 {
1436 _dbus_close (fd.fd, NULL);
1437 return _dbus_socket_get_invalid ();
1438 }
1439
1440 return fd;
1441 }
1442
1459 int
1460 _dbus_listen_tcp_socket (const char *host,
1461 const char *port,
1462 const char *family,
1463 DBusString *retport,
1464 DBusSocket **fds_p,
1465 DBusError *error)
1466 {
1467 int saved_errno;
1468 int nlisten_fd = 0, res, i;
1469 DBusSocket *listen_fd = NULL;
1470 struct addrinfo hints;
1471 struct addrinfo *ai, *tmp;
1472 unsigned int reuseaddr;
1473
1474 *fds_p = NULL;
1475 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1476
1477 _DBUS_ZERO (hints);
1478
1479 if (!family)
1480 hints.ai_family = AF_UNSPEC;
1481 else if (!strcmp(family, "ipv4"))
1482 hints.ai_family = AF_INET;
1483 else if (!strcmp(family, "ipv6"))
1484 hints.ai_family = AF_INET6;
1485 else
1486 {
1487 dbus_set_error (error,
1488 DBUS_ERROR_BAD_ADDRESS,
1489 "Unknown address family %s", family);
1490 return -1;
1491 }
1492
1493 hints.ai_protocol = IPPROTO_TCP;
1494 hints.ai_socktype = SOCK_STREAM;
1495 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1496
1497 redo_lookup_with_port:
1498 ai = NULL;
1499 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1500 {
1501 dbus_set_error (error,
1502 _dbus_error_from_errno (errno),
1503 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1504 host ? host : "*", port, gai_strerror(res), res);
1505 goto failed;
1506 }
1507
1508 tmp = ai;
1509 while (tmp)
1510 {
1511 int fd = -1, tcp_nodelay_on;
1512 DBusSocket *newlisten_fd;
1513
1514 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1515 {
1516 _DBUS_ASSERT_ERROR_IS_SET(error);
1517 goto failed;
1518 }
1519 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1520
1521 reuseaddr = 1;
1522 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1523 {
1524 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1525 host ? host : "*", port, _dbus_strerror (errno));
1526 }
1527
1528 /* Nagle's algorithm imposes a huge delay on the initial messages
1529 going over TCP. */
1530 tcp_nodelay_on = 1;
1531 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1532 {
1533 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1534 host ? host : "*", port, _dbus_strerror (errno));
1535 }
1536
1537 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1538 {
1539 saved_errno = errno;
1540 _dbus_close(fd, NULL);
1541 if (saved_errno == EADDRINUSE)
1542 {
1543 /* Depending on kernel policy, binding to an IPv6 address
1544 might implicitly bind to a corresponding IPv4
1545 address or vice versa, resulting in EADDRINUSE for the
1546 other one (e.g. bindv6only=0 on Linux).
1547
1548 Also, after we "goto redo_lookup_with_port" after binding
1549 a port on one of the possible addresses, we will
1550 try to bind that same port on every address, including the
1551 same address again for a second time; that one will
1552 also fail with EADDRINUSE.
1553
1554 For both those reasons, ignore EADDRINUSE here */
1555 tmp = tmp->ai_next;
1556 continue;
1557 }
1558 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1559 "Failed to bind socket \"%s:%s\": %s",
1560 host ? host : "*", port, _dbus_strerror (saved_errno));
1561 goto failed;
1562 }
1563
1564 if (listen (fd, 30 /* backlog */) < 0)
1565 {
1566 saved_errno = errno;
1567 _dbus_close (fd, NULL);
1568 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1569 "Failed to listen on socket \"%s:%s\": %s",
1570 host ? host : "*", port, _dbus_strerror (saved_errno));
1571 goto failed;
1572 }
1573
1574 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1575 if (!newlisten_fd)
1576 {
1577 saved_errno = errno;
1578 _dbus_close (fd, NULL);
1579 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1580 "Failed to allocate file handle array: %s",
1581 _dbus_strerror (saved_errno));
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 (%s)",
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 int 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 pid_read = ucred_getpid (ucred);
2056 uid_read = ucred_geteuid (ucred);
2057 #ifdef HAVE_ADT
2058 /* generate audit session data based on socket ucred */
2059 adt_session_data_t *adth = NULL;
2060 adt_export_data_t *data = NULL;
2061 size_t size = 0;
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 size = adt_export_session_data (adth, &data);
2075 if (size <= 0)
2076 {
2077 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2078 }
2079 else
2080 {
2081 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2082 free (data);
2083 }
2084 }
2085 (void) adt_end_session (adth);
2086 }
2087 #endif /* HAVE_ADT */
2088 }
2089 else
2090 {
2091 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2092 }
2093 if (ucred != NULL)
2094 ucred_free (ucred);
2095
2096 /* ----------------------------------------------------------------
2097 * When adding new mechanisms, please add them above this point
2098 * if they support passing the process ID through, or below if not.
2099 * ---------------------------------------------------------------- */
2100
2101 #elif defined(HAVE_GETPEEREID)
2102 /* getpeereid() originates from D.J. Bernstein and is fairly
2103 * widely-supported. According to a web search, it might be present in
2104 * any/all of:
2105 *
2106 * - AIX?
2107 * - Blackberry?
2108 * - Cygwin
2109 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2110 * - Mac OS X
2111 * - Minix 3.1.8+
2112 * - MirBSD?
2113 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2114 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2115 * - QNX?
2116 */
2117 uid_t euid;
2118 gid_t egid;
2119 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2120 {
2121 uid_read = euid;
2122 }
2123 else
2124 {
2125 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2126 }
2127 #else /* no supported mechanism */
2128
2129 #warning Socket credentials not supported on this Unix OS
2130 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2131
2132 /* Please add other operating systems known to support at least one of
2133 * the mechanisms above to this list, keeping alphabetical order.
2134 * Everything not in this list is best-effort.
2135 */
2136 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2137 defined(__linux__) || \
2138 defined(__OpenBSD__) || \
2139 defined(__NetBSD__)
2140 # error Credentials passing not working on this OS is a regression!
2141 #endif
2142
2143 _dbus_verbose ("Socket credentials not supported on this OS\n");
2144 #endif
2145 }
2146
2147 _dbus_verbose ("Credentials:"
2148 " pid "DBUS_PID_FORMAT
2149 " uid "DBUS_UID_FORMAT
2150 "\n",
2151 pid_read,
2152 uid_read);
2153
2154 if (pid_read != DBUS_PID_UNSET)
2155 {
2156 if (!_dbus_credentials_add_pid (credentials, pid_read))
2157 {
2158 _DBUS_SET_OOM (error);
2159 return FALSE;
2160 }
2161 }
2162
2163 if (uid_read != DBUS_UID_UNSET)
2164 {
2165 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2166 {
2167 _DBUS_SET_OOM (error);
2168 return FALSE;
2169 }
2170 }
2171
2172 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2173 {
2174 _DBUS_SET_OOM (error);
2175 return FALSE;
2176 }
2177
2178 return TRUE;
2179 }
2180
2198 dbus_bool_t
2199 _dbus_send_credentials_socket (DBusSocket server_fd,
2200 DBusError *error)
2201 {
2202 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2203
2204 if (write_credentials_byte (server_fd.fd, error))
2205 return TRUE;
2206 else
2207 return FALSE;
2208 }
2209
2219 DBusSocket
2220 _dbus_accept (DBusSocket listen_fd)
2221 {
2222 DBusSocket client_fd;
2223 struct sockaddr addr;
2224 socklen_t addrlen;
2225 #ifdef HAVE_ACCEPT4
2226 dbus_bool_t cloexec_done;
2227 #endif
2228
2229 addrlen = sizeof (addr);
2230
2231 retry:
2232
2233 #ifdef HAVE_ACCEPT4
2234 /*
2235 * At compile-time, we assume that if accept4() is available in
2236 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2237 * not necessarily true that either is supported by the running kernel.
2238 */
2239 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2240 cloexec_done = client_fd.fd >= 0;
2241
2242 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2243 #endif
2244 {
2245 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2246 }
2247
2248 if (client_fd.fd < 0)
2249 {
2250 if (errno == EINTR)
2251 goto retry;
2252 }
2253
2254 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2255
2256 #ifdef HAVE_ACCEPT4
2257 if (!cloexec_done)
2258 #endif
2259 {
2260 _dbus_fd_set_close_on_exec(client_fd.fd);
2261 }
2262
2263 return client_fd;
2264 }
2265
2274 dbus_bool_t
2275 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2276 {
2277 const char *directory;
2278 struct stat sb;
2279
2280 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2281
2282 directory = _dbus_string_get_const_data (dir);
2283
2284 if (stat (directory, &sb) < 0)
2285 {
2286 dbus_set_error (error, _dbus_error_from_errno (errno),
2287 "%s", _dbus_strerror (errno));
2288
2289 return FALSE;
2290 }
2291
2292 if (sb.st_uid != geteuid ())
2293 {
2294 dbus_set_error (error, DBUS_ERROR_FAILED,
2295 "%s directory is owned by user %lu, not %lu",
2296 directory,
2297 (unsigned long) sb.st_uid,
2298 (unsigned long) geteuid ());
2299 return FALSE;
2300 }
2301
2302 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2303 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2304 {
2305 dbus_set_error (error, DBUS_ERROR_FAILED,
2306 "%s directory is not private to the user", directory);
2307 return FALSE;
2308 }
2309
2310 return TRUE;
2311 }
2312
2313 static dbus_bool_t
2314 fill_user_info_from_passwd (struct passwd *p,
2315 DBusUserInfo *info,
2316 DBusError *error)
2317 {
2318 _dbus_assert (p->pw_name != NULL);
2319 _dbus_assert (p->pw_dir != NULL);
2320
2321 info->uid = p->pw_uid;
2322 info->primary_gid = p->pw_gid;
2323 info->username = _dbus_strdup (p->pw_name);
2324 info->homedir = _dbus_strdup (p->pw_dir);
2325
2326 if (info->username == NULL ||
2327 info->homedir == NULL)
2328 {
2329 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2330 return FALSE;
2331 }
2332
2333 return TRUE;
2334 }
2335
2336 static dbus_bool_t
2337 fill_user_info (DBusUserInfo *info,
2338 dbus_uid_t uid,
2339 const DBusString *username,
2340 DBusError *error)
2341 {
2342 const char *username_c;
2343
2344 /* exactly one of username/uid provided */
2345 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2346 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2347
2348 info->uid = DBUS_UID_UNSET;
2349 info->primary_gid = DBUS_GID_UNSET;
2350 info->group_ids = NULL;
2351 info->n_group_ids = 0;
2352 info->username = NULL;
2353 info->homedir = NULL;
2354
2355 if (username != NULL)
2356 username_c = _dbus_string_get_const_data (username);
2357 else
2358 username_c = NULL;
2359
2360 /* For now assuming that the getpwnam() and getpwuid() flavors
2361 * are always symmetrical, if not we have to add more configure
2362 * checks
2363 */
2364
2365 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2366 {
2367 struct passwd *p;
2368 int result;
2369 size_t buflen;
2370 char *buf;
2371 struct passwd p_str;
2372
2373 /* retrieve maximum needed size for buf */
2374 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2375
2376 /* sysconf actually returns a long, but everything else expects size_t,
2377 * so just recast here.
2378 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2379 */
2380 if ((long) buflen <= 0)
2381 buflen = 1024;
2382
2383 result = -1;
2384 while (1)
2385 {
2386 buf = dbus_malloc (buflen);
2387 if (buf == NULL)
2388 {
2389 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2390 return FALSE;
2391 }
2392
2393 p = NULL;
2394 #ifdef HAVE_POSIX_GETPWNAM_R
2395 if (uid != DBUS_UID_UNSET)
2396 result = getpwuid_r (uid, &p_str, buf, buflen,
2397 &p);
2398 else
2399 result = getpwnam_r (username_c, &p_str, buf, buflen,
2400 &p);
2401 #else
2402 if (uid != DBUS_UID_UNSET)
2403 p = getpwuid_r (uid, &p_str, buf, buflen);
2404 else
2405 p = getpwnam_r (username_c, &p_str, buf, buflen);
2406 result = 0;
2407 #endif /* !HAVE_POSIX_GETPWNAM_R */
2408 //Try a bigger buffer if ERANGE was returned
2409 if (result == ERANGE && buflen < 512 * 1024)
2410 {
2411 dbus_free (buf);
2412 buflen *= 2;
2413 }
2414 else
2415 {
2416 break;
2417 }
2418 }
2419 if (result == 0 && p == &p_str)
2420 {
2421 if (!fill_user_info_from_passwd (p, info, error))
2422 {
2423 dbus_free (buf);
2424 return FALSE;
2425 }
2426 dbus_free (buf);
2427 }
2428 else
2429 {
2430 dbus_set_error (error, _dbus_error_from_errno (errno),
2431 "User \"%s\" unknown or no memory to allocate password entry\n",
2432 username_c ? username_c : "???");
2433 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2434 dbus_free (buf);
2435 return FALSE;
2436 }
2437 }
2438 #else /* ! HAVE_GETPWNAM_R */
2439 {
2440 /* I guess we're screwed on thread safety here */
2441 struct passwd *p;
2442
2443 if (uid != DBUS_UID_UNSET)
2444 p = getpwuid (uid);
2445 else
2446 p = getpwnam (username_c);
2447
2448 if (p != NULL)
2449 {
2450 if (!fill_user_info_from_passwd (p, info, error))
2451 {
2452 return FALSE;
2453 }
2454 }
2455 else
2456 {
2457 dbus_set_error (error, _dbus_error_from_errno (errno),
2458 "User \"%s\" unknown or no memory to allocate password entry\n",
2459 username_c ? username_c : "???");
2460 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2461 return FALSE;
2462 }
2463 }
2464 #endif /* ! HAVE_GETPWNAM_R */
2465
2466 /* Fill this in so we can use it to get groups */
2467 username_c = info->username;
2468
2469 #ifdef HAVE_GETGROUPLIST
2470 {
2471 gid_t *buf;
2472 int buf_count;
2473 int i;
2474 int initial_buf_count;
2475
2476 initial_buf_count = 17;
2477 buf_count = initial_buf_count;
2478 buf = dbus_new (gid_t, buf_count);
2479 if (buf == NULL)
2480 {
2481 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2482 goto failed;
2483 }
2484
2485 if (getgrouplist (username_c,
2486 info->primary_gid,
2487 buf, &buf_count) < 0)
2488 {
2489 gid_t *new;
2490 /* Presumed cause of negative return code: buf has insufficient
2491 entries to hold the entire group list. The Linux behavior in this
2492 case is to pass back the actual number of groups in buf_count, but
2493 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2494 So as a hack, try to help out a bit by guessing a larger
2495 number of groups, within reason.. might still fail, of course,
2496 but we can at least print a more informative message. I looked up
2497 the "right way" to do this by downloading Apple's own source code
2498 for the "id" command, and it turns out that they use an
2499 undocumented library function getgrouplist_2 (!) which is not
2500 declared in any header in /usr/include (!!). That did not seem
2501 like the way to go here.
2502 */
2503 if (buf_count == initial_buf_count)
2504 {
2505 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2506 }
2507 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2508 if (new == NULL)
2509 {
2510 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2511 dbus_free (buf);
2512 goto failed;
2513 }
2514
2515 buf = new;
2516
2517 errno = 0;
2518 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2519 {
2520 if (errno == 0)
2521 {
2522 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2523 username_c, buf_count, buf_count);
2524 }
2525 else
2526 {
2527 dbus_set_error (error,
2528 _dbus_error_from_errno (errno),
2529 "Failed to get groups for username \"%s\" primary GID "
2530 DBUS_GID_FORMAT ": %s\n",
2531 username_c, info->primary_gid,
2532 _dbus_strerror (errno));
2533 dbus_free (buf);
2534 goto failed;
2535 }
2536 }
2537 }
2538
2539 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2540 if (info->group_ids == NULL)
2541 {
2542 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2543 dbus_free (buf);
2544 goto failed;
2545 }
2546
2547 for (i = 0; i < buf_count; ++i)
2548 info->group_ids[i] = buf[i];
2549
2550 info->n_group_ids = buf_count;
2551
2552 dbus_free (buf);
2553 }
2554 #else /* HAVE_GETGROUPLIST */
2555 {
2556 /* We just get the one group ID */
2557 info->group_ids = dbus_new (dbus_gid_t, 1);
2558 if (info->group_ids == NULL)
2559 {
2560 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2561 goto failed;
2562 }
2563
2564 info->n_group_ids = 1;
2565
2566 (info->group_ids)[0] = info->primary_gid;
2567 }
2568 #endif /* HAVE_GETGROUPLIST */
2569
2570 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2571
2572 return TRUE;
2573
2574 failed:
2575 _DBUS_ASSERT_ERROR_IS_SET (error);
2576 return FALSE;
2577 }
2578
2587 dbus_bool_t
2588 _dbus_user_info_fill (DBusUserInfo *info,
2589 const DBusString *username,
2590 DBusError *error)
2591 {
2592 return fill_user_info (info, DBUS_UID_UNSET,
2593 username, error);
2594 }
2595
2604 dbus_bool_t
2605 _dbus_user_info_fill_uid (DBusUserInfo *info,
2606 dbus_uid_t uid,
2607 DBusError *error)
2608 {
2609 return fill_user_info (info, uid,
2610 NULL, error);
2611 }
2612
2620 dbus_bool_t
2621 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2622 {
2623 /* The POSIX spec certainly doesn't promise this, but
2624 * we need these assertions to fail as soon as we're wrong about
2625 * it so we can do the porting fixups
2626 */
2627 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2628 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2629 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2630
2631 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2632 return FALSE;
2633 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2634 return FALSE;
2635
2636 return TRUE;
2637 }
2638
2650 dbus_bool_t
2651 _dbus_append_user_from_current_process (DBusString *str)
2652 {
2653 return _dbus_string_append_uint (str,
2654 _dbus_geteuid ());
2655 }
2656
2661 dbus_pid_t
2662 _dbus_getpid (void)
2663 {
2664 return getpid ();
2665 }
2666
2670 dbus_uid_t
2671 _dbus_getuid (void)
2672 {
2673 return getuid ();
2674 }
2675
2679 dbus_uid_t
2680 _dbus_geteuid (void)
2681 {
2682 return geteuid ();
2683 }
2684
2691 unsigned long
2692 _dbus_pid_for_log (void)
2693 {
2694 return getpid ();
2695 }
2696
2704 dbus_bool_t
2705 _dbus_parse_uid (const DBusString *uid_str,
2706 dbus_uid_t *uid)
2707 {
2708 int end;
2709 long val;
2710
2711 if (_dbus_string_get_length (uid_str) == 0)
2712 {
2713 _dbus_verbose ("UID string was zero length\n");
2714 return FALSE;
2715 }
2716
2717 val = -1;
2718 end = 0;
2719 if (!_dbus_string_parse_int (uid_str, 0, &val,
2720 &end))
2721 {
2722 _dbus_verbose ("could not parse string as a UID\n");
2723 return FALSE;
2724 }
2725
2726 if (end != _dbus_string_get_length (uid_str))
2727 {
2728 _dbus_verbose ("string contained trailing stuff after UID\n");
2729 return FALSE;
2730 }
2731
2732 *uid = val;
2733
2734 return TRUE;
2735 }
2736
2737 #if !DBUS_USE_SYNC
2738 /* To be thread-safe by default on platforms that don't necessarily have
2739 * atomic operations (notably Debian armel, which is armv4t), we must
2740 * use a mutex that can be initialized statically, like this.
2741 * GLib >= 2.32 uses a similar system.
2742 */
2743 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2744 #endif
2745
2752 dbus_int32_t
2753 _dbus_atomic_inc (DBusAtomic *atomic)
2754 {
2755 #if DBUS_USE_SYNC
2756 return __sync_add_and_fetch(&atomic->value, 1)-1;
2757 #else
2758 dbus_int32_t res;
2759
2760 pthread_mutex_lock (&atomic_mutex);
2761 res = atomic->value;
2762 atomic->value += 1;
2763 pthread_mutex_unlock (&atomic_mutex);
2764
2765 return res;
2766 #endif
2767 }
2768
2775 dbus_int32_t
2776 _dbus_atomic_dec (DBusAtomic *atomic)
2777 {
2778 #if DBUS_USE_SYNC
2779 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2780 #else
2781 dbus_int32_t res;
2782
2783 pthread_mutex_lock (&atomic_mutex);
2784 res = atomic->value;
2785 atomic->value -= 1;
2786 pthread_mutex_unlock (&atomic_mutex);
2787
2788 return res;
2789 #endif
2790 }
2791
2799 dbus_int32_t
2800 _dbus_atomic_get (DBusAtomic *atomic)
2801 {
2802 #if DBUS_USE_SYNC
2803 __sync_synchronize ();
2804 return atomic->value;
2805 #else
2806 dbus_int32_t res;
2807
2808 pthread_mutex_lock (&atomic_mutex);
2809 res = atomic->value;
2810 pthread_mutex_unlock (&atomic_mutex);
2811
2812 return res;
2813 #endif
2814 }
2815
2824 int
2825 _dbus_poll (DBusPollFD *fds,
2826 int n_fds,
2827 int timeout_milliseconds)
2828 {
2829 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2830 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2831 if (timeout_milliseconds < -1)
2832 {
2833 timeout_milliseconds = -1;
2834 }
2835
2836 return poll (fds,
2837 n_fds,
2838 timeout_milliseconds);
2839 #else /* ! HAVE_POLL */
2840 /* Emulate poll() in terms of select() */
2841 fd_set read_set, write_set, err_set;
2842 int max_fd = 0;
2843 int i;
2844 struct timeval tv;
2845 int ready;
2846
2847 FD_ZERO (&read_set);
2848 FD_ZERO (&write_set);
2849 FD_ZERO (&err_set);
2850
2851 for (i = 0; i < n_fds; i++)
2852 {
2853 DBusPollFD *fdp = &fds[i];
2854
2855 if (fdp->events & _DBUS_POLLIN)
2856 FD_SET (fdp->fd, &read_set);
2857
2858 if (fdp->events & _DBUS_POLLOUT)
2859 FD_SET (fdp->fd, &write_set);
2860
2861 FD_SET (fdp->fd, &err_set);
2862
2863 max_fd = MAX (max_fd, fdp->fd);
2864 }
2865
2866 tv.tv_sec = timeout_milliseconds / 1000;
2867 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2868
2869 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2870 timeout_milliseconds < 0 ? NULL : &tv);
2871
2872 if (ready > 0)
2873 {
2874 for (i = 0; i < n_fds; i++)
2875 {
2876 DBusPollFD *fdp = &fds[i];
2877
2878 fdp->revents = 0;
2879
2880 if (FD_ISSET (fdp->fd, &read_set))
2881 fdp->revents |= _DBUS_POLLIN;
2882
2883 if (FD_ISSET (fdp->fd, &write_set))
2884 fdp->revents |= _DBUS_POLLOUT;
2885
2886 if (FD_ISSET (fdp->fd, &err_set))
2887 fdp->revents |= _DBUS_POLLERR;
2888 }
2889 }
2890
2891 return ready;
2892 #endif
2893 }
2894
2902 void
2903 _dbus_get_monotonic_time (long *tv_sec,
2904 long *tv_usec)
2905 {
2906 #ifdef HAVE_MONOTONIC_CLOCK
2907 struct timespec ts;
2908 clock_gettime (CLOCK_MONOTONIC, &ts);
2909
2910 if (tv_sec)
2911 *tv_sec = ts.tv_sec;
2912 if (tv_usec)
2913 *tv_usec = ts.tv_nsec / 1000;
2914 #else
2915 struct timeval t;
2916
2917 gettimeofday (&t, NULL);
2918
2919 if (tv_sec)
2920 *tv_sec = t.tv_sec;
2921 if (tv_usec)
2922 *tv_usec = t.tv_usec;
2923 #endif
2924 }
2925
2933 void
2934 _dbus_get_real_time (long *tv_sec,
2935 long *tv_usec)
2936 {
2937 struct timeval t;
2938
2939 gettimeofday (&t, NULL);
2940
2941 if (tv_sec)
2942 *tv_sec = t.tv_sec;
2943 if (tv_usec)
2944 *tv_usec = t.tv_usec;
2945 }
2946
2955 dbus_bool_t
2956 _dbus_ensure_directory (const DBusString *filename,
2957 DBusError *error)
2958 {
2959 const char *filename_c;
2960
2961 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2962
2963 filename_c = _dbus_string_get_const_data (filename);
2964
2965 if (mkdir (filename_c, 0700) < 0)
2966 {
2967 if (errno == EEXIST)
2968 return TRUE;
2969
2970 dbus_set_error (error, DBUS_ERROR_FAILED,
2971 "Failed to create directory %s: %s\n",
2972 filename_c, _dbus_strerror (errno));
2973 return FALSE;
2974 }
2975 else
2976 return TRUE;
2977 }
2978
2987 dbus_bool_t
2988 _dbus_create_directory (const DBusString *filename,
2989 DBusError *error)
2990 {
2991 const char *filename_c;
2992
2993 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2994
2995 filename_c = _dbus_string_get_const_data (filename);
2996
2997 if (mkdir (filename_c, 0700) < 0)
2998 {
2999 dbus_set_error (error, DBUS_ERROR_FAILED,
3000 "Failed to create directory %s: %s\n",
3001 filename_c, _dbus_strerror (errno));
3002 return FALSE;
3003 }
3004 else
3005 return TRUE;
3006 }
3007
3018 dbus_bool_t
3019 _dbus_concat_dir_and_file (DBusString *dir,
3020 const DBusString *next_component)
3021 {
3022 dbus_bool_t dir_ends_in_slash;
3023 dbus_bool_t file_starts_with_slash;
3024
3025 if (_dbus_string_get_length (dir) == 0 ||
3026 _dbus_string_get_length (next_component) == 0)
3027 return TRUE;
3028
3029 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3030 _dbus_string_get_length (dir) - 1);
3031
3032 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3033
3034 if (dir_ends_in_slash && file_starts_with_slash)
3035 {
3036 _dbus_string_shorten (dir, 1);
3037 }
3038 else if (!(dir_ends_in_slash || file_starts_with_slash))
3039 {
3040 if (!_dbus_string_append_byte (dir, '/'))
3041 return FALSE;
3042 }
3043
3044 return _dbus_string_copy (next_component, 0, dir,
3045 _dbus_string_get_length (dir));
3046 }
3047
3049 #define NANOSECONDS_PER_SECOND 1000000000
3050
3051 #define MICROSECONDS_PER_SECOND 1000000
3052
3053 #define MILLISECONDS_PER_SECOND 1000
3054
3055 #define NANOSECONDS_PER_MILLISECOND 1000000
3056
3057 #define MICROSECONDS_PER_MILLISECOND 1000
3058
3063 void
3064 _dbus_sleep_milliseconds (int milliseconds)
3065 {
3066 #ifdef HAVE_NANOSLEEP
3067 struct timespec req;
3068 struct timespec rem;
3069
3070 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3071 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3072 rem.tv_sec = 0;
3073 rem.tv_nsec = 0;
3074
3075 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3076 req = rem;
3077 #elif defined (HAVE_USLEEP)
3078 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3079 #else /* ! HAVE_USLEEP */
3080 sleep (MAX (milliseconds / 1000, 1));
3081 #endif
3082 }
3083
3093 dbus_bool_t
3094 _dbus_generate_random_bytes (DBusString *str,
3095 int n_bytes,
3096 DBusError *error)
3097 {
3098 int old_len;
3099 int fd;
3100 int result;
3101
3102 old_len = _dbus_string_get_length (str);
3103 fd = -1;
3104
3105 /* note, urandom on linux will fall back to pseudorandom */
3106 fd = open ("/dev/urandom", O_RDONLY);
3107
3108 if (fd < 0)
3109 {
3110 dbus_set_error (error, _dbus_error_from_errno (errno),
3111 "Could not open /dev/urandom: %s",
3112 _dbus_strerror (errno));
3113 return FALSE;
3114 }
3115
3116 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3117
3118 result = _dbus_read (fd, str, n_bytes);
3119
3120 if (result != n_bytes)
3121 {
3122 if (result < 0)
3123 dbus_set_error (error, _dbus_error_from_errno (errno),
3124 "Could not read /dev/urandom: %s",
3125 _dbus_strerror (errno));
3126 else
3127 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
3128 "Short read from /dev/urandom");
3129
3130 _dbus_close (fd, NULL);
3131 _dbus_string_set_length (str, old_len);
3132 return FALSE;
3133 }
3134
3135 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3136 n_bytes);
3137
3138 _dbus_close (fd, NULL);
3139
3140 return TRUE;
3141 }
3142
3148 void
3149 _dbus_exit (int code)
3150 {
3151 _exit (code);
3152 }
3153
3162 const char*
3163 _dbus_strerror (int error_number)
3164 {
3165 const char *msg;
3166
3167 msg = strerror (error_number);
3168 if (msg == NULL)
3169 msg = "unknown";
3170
3171 return msg;
3172 }
3173
3177 void
3178 _dbus_disable_sigpipe (void)
3179 {
3180 signal (SIGPIPE, SIG_IGN);
3181 }
3182
3190 void
3191 _dbus_fd_set_close_on_exec (int fd)
3192 {
3193 int val;
3194
3195 val = fcntl (fd, F_GETFD, 0);
3196
3197 if (val < 0)
3198 return;
3199
3200 val |= FD_CLOEXEC;
3201
3202 fcntl (fd, F_SETFD, val);
3203 }
3204
3212 dbus_bool_t
3213 _dbus_close (int fd,
3214 DBusError *error)
3215 {
3216 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3217
3218 again:
3219 if (close (fd) < 0)
3220 {
3221 if (errno == EINTR)
3222 goto again;
3223
3224 dbus_set_error (error, _dbus_error_from_errno (errno),
3225 "Could not close fd %d", fd);
3226 return FALSE;
3227 }
3228
3229 return TRUE;
3230 }
3231
3240 int
3241 _dbus_dup(int fd,
3242 DBusError *error)
3243 {
3244 int new_fd;
3245
3246 #ifdef F_DUPFD_CLOEXEC
3247 dbus_bool_t cloexec_done;
3248
3249 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3250 cloexec_done = new_fd >= 0;
3251
3252 if (new_fd < 0 && errno == EINVAL)
3253 #endif
3254 {
3255 new_fd = fcntl(fd, F_DUPFD, 3);
3256 }
3257
3258 if (new_fd < 0) {
3259
3260 dbus_set_error (error, _dbus_error_from_errno (errno),
3261 "Could not duplicate fd %d", fd);
3262 return -1;
3263 }
3264
3265 #ifdef F_DUPFD_CLOEXEC
3266 if (!cloexec_done)
3267 #endif
3268 {
3269 _dbus_fd_set_close_on_exec(new_fd);
3270 }
3271
3272 return new_fd;
3273 }
3274
3282 dbus_bool_t
3283 _dbus_set_socket_nonblocking (DBusSocket fd,
3284 DBusError *error)
3285 {
3286 return _dbus_set_fd_nonblocking (fd.fd, error);
3287 }
3288
3289 static dbus_bool_t
3290 _dbus_set_fd_nonblocking (int fd,
3291 DBusError *error)
3292 {
3293 int val;
3294
3295 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3296
3297 val = fcntl (fd, F_GETFL, 0);
3298 if (val < 0)
3299 {
3300 dbus_set_error (error, _dbus_error_from_errno (errno),
3301 "Failed to get flags from file descriptor %d: %s",
3302 fd, _dbus_strerror (errno));
3303 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3304 _dbus_strerror (errno));
3305 return FALSE;
3306 }
3307
3308 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3309 {
3310 dbus_set_error (error, _dbus_error_from_errno (errno),
3311 "Failed to set nonblocking flag of file descriptor %d: %s",
3312 fd, _dbus_strerror (errno));
3313 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3314 fd, _dbus_strerror (errno));
3315
3316 return FALSE;
3317 }
3318
3319 return TRUE;
3320 }
3321
3327 void
3328 _dbus_print_backtrace (void)
3329 {
3330 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3331 void *bt[500];
3332 int bt_size;
3333 int i;
3334 char **syms;
3335
3336 bt_size = backtrace (bt, 500);
3337
3338 syms = backtrace_symbols (bt, bt_size);
3339
3340 i = 0;
3341 while (i < bt_size)
3342 {
3343 /* don't use dbus_warn since it can _dbus_abort() */
3344 fprintf (stderr, " %s\n", syms[i]);
3345 ++i;
3346 }
3347 fflush (stderr);
3348
3349 free (syms);
3350 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3351 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3352 #else
3353 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3354 #endif
3355 }
3356
3369 dbus_bool_t
3370 _dbus_socketpair (DBusSocket *fd1,
3371 DBusSocket *fd2,
3372 dbus_bool_t blocking,
3373 DBusError *error)
3374 {
3375 #ifdef HAVE_SOCKETPAIR
3376 int fds[2];
3377 int retval;
3378
3379 #ifdef SOCK_CLOEXEC
3380 dbus_bool_t cloexec_done;
3381
3382 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3383 cloexec_done = retval >= 0;
3384
3385 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3386 #endif
3387 {
3388 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3389 }
3390
3391 if (retval < 0)
3392 {
3393 dbus_set_error (error, _dbus_error_from_errno (errno),
3394 "Could not create full-duplex pipe");
3395 return FALSE;
3396 }
3397
3398 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3399
3400 #ifdef SOCK_CLOEXEC
3401 if (!cloexec_done)
3402 #endif
3403 {
3404 _dbus_fd_set_close_on_exec (fds[0]);
3405 _dbus_fd_set_close_on_exec (fds[1]);
3406 }
3407
3408 if (!blocking &&
3409 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3410 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3411 {
3412 dbus_set_error (error, _dbus_error_from_errno (errno),
3413 "Could not set full-duplex pipe nonblocking");
3414
3415 _dbus_close (fds[0], NULL);
3416 _dbus_close (fds[1], NULL);
3417
3418 return FALSE;
3419 }
3420
3421 fd1->fd = fds[0];
3422 fd2->fd = fds[1];
3423
3424 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3425 fd1->fd, fd2->fd);
3426
3427 return TRUE;
3428 #else
3429 _dbus_warn ("_dbus_socketpair() not implemented on this OS\n");
3430 dbus_set_error (error, DBUS_ERROR_FAILED,
3431 "_dbus_socketpair() not implemented on this OS");
3432 return FALSE;
3433 #endif
3434 }
3435
3444 int
3445 _dbus_printf_string_upper_bound (const char *format,
3446 va_list args)
3447 {
3448 char static_buf[1024];
3449 int bufsize = sizeof (static_buf);
3450 int len;
3451 va_list args_copy;
3452
3453 DBUS_VA_COPY (args_copy, args);
3454 len = vsnprintf (static_buf, bufsize, format, args_copy);
3455 va_end (args_copy);
3456
3457 /* If vsnprintf() returned non-negative, then either the string fits in
3458 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3459 * returns the number of characters that were needed, or this OS returns the
3460 * truncated length.
3461 *
3462 * We ignore the possibility that snprintf might just ignore the length and
3463 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3464 * If your libc is really that bad, come back when you have a better one. */
3465 if (len == bufsize)
3466 {
3467 /* This could be the truncated length (Tru64 and IRIX have this bug),
3468 * or the real length could be coincidentally the same. Which is it?
3469 * If vsnprintf returns the truncated length, we'll go to the slow
3470 * path. */
3471 DBUS_VA_COPY (args_copy, args);
3472
3473 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3474 len = -1;
3475
3476 va_end (args_copy);
3477 }
3478
3479 /* If vsnprintf() returned negative, we have to do more work.
3480 * HP-UX returns negative. */
3481 while (len < 0)
3482 {
3483 char *buf;
3484
3485 bufsize *= 2;
3486
3487 buf = dbus_malloc (bufsize);
3488
3489 if (buf == NULL)
3490 return -1;
3491
3492 DBUS_VA_COPY (args_copy, args);
3493 len = vsnprintf (buf, bufsize, format, args_copy);
3494 va_end (args_copy);
3495
3496 dbus_free (buf);
3497
3498 /* If the reported length is exactly the buffer size, round up to the
3499 * next size, in case vsnprintf has been returning the truncated
3500 * length */
3501 if (len == bufsize)
3502 len = -1;
3503 }
3504
3505 return len;
3506 }
3507
3514 const char*
3515 _dbus_get_tmpdir(void)
3516 {
3517 /* Protected by _DBUS_LOCK_sysdeps */
3518 static const char* tmpdir = NULL;
3519
3520 if (!_DBUS_LOCK (sysdeps))
3521 return NULL;
3522
3523 if (tmpdir == NULL)
3524 {
3525 /* TMPDIR is what glibc uses, then
3526 * glibc falls back to the P_tmpdir macro which
3527 * just expands to "/tmp"
3528 */
3529 if (tmpdir == NULL)
3530 tmpdir = getenv("TMPDIR");
3531
3532 /* These two env variables are probably
3533 * broken, but maybe some OS uses them?
3534 */
3535 if (tmpdir == NULL)
3536 tmpdir = getenv("TMP");
3537 if (tmpdir == NULL)
3538 tmpdir = getenv("TEMP");
3539
3540 /* And this is the sane fallback. */
3541 if (tmpdir == NULL)
3542 tmpdir = "/tmp";
3543 }
3544
3545 _DBUS_UNLOCK (sysdeps);
3546
3547 _dbus_assert(tmpdir != NULL);
3548
3549 return tmpdir;
3550 }
3551
3552 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3553
3572 static dbus_bool_t
3573 _read_subprocess_line_argv (const char *progpath,
3574 dbus_bool_t path_fallback,
3575 char * const *argv,
3576 DBusString *result,
3577 DBusError *error)
3578 {
3579 int result_pipe[2] = { -1, -1 };
3580 int errors_pipe[2] = { -1, -1 };
3581 pid_t pid;
3582 int ret;
3583 int status;
3584 int orig_len;
3585
3586 dbus_bool_t retval;
3587 sigset_t new_set, old_set;
3588
3589 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3590 retval = FALSE;
3591
3592 /* We need to block any existing handlers for SIGCHLD temporarily; they
3593 * will cause waitpid() below to fail.
3594 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3595 */
3596 sigemptyset (&new_set);
3597 sigaddset (&new_set, SIGCHLD);
3598 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3599
3600 orig_len = _dbus_string_get_length (result);
3601
3602 #define READ_END 0
3603 #define WRITE_END 1
3604 if (pipe (result_pipe) < 0)
3605 {
3606 dbus_set_error (error, _dbus_error_from_errno (errno),
3607 "Failed to create a pipe to call %s: %s",
3608 progpath, _dbus_strerror (errno));
3609 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3610 progpath, _dbus_strerror (errno));
3611 goto out;
3612 }
3613 if (pipe (errors_pipe) < 0)
3614 {
3615 dbus_set_error (error, _dbus_error_from_errno (errno),
3616 "Failed to create a pipe to call %s: %s",
3617 progpath, _dbus_strerror (errno));
3618 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3619 progpath, _dbus_strerror (errno));
3620 goto out;
3621 }
3622
3623 pid = fork ();
3624 if (pid < 0)
3625 {
3626 dbus_set_error (error, _dbus_error_from_errno (errno),
3627 "Failed to fork() to call %s: %s",
3628 progpath, _dbus_strerror (errno));
3629 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3630 progpath, _dbus_strerror (errno));
3631 goto out;
3632 }
3633
3634 if (pid == 0)
3635 {
3636 /* child process */
3637 int fd;
3638
3639 fd = open ("/dev/null", O_RDWR);
3640 if (fd == -1)
3641 /* huh?! can't open /dev/null? */
3642 _exit (1);
3643
3644 _dbus_verbose ("/dev/null fd %d opened\n", fd);
3645
3646 /* set-up stdXXX */
3647 close (result_pipe[READ_END]);
3648 close (errors_pipe[READ_END]);
3649
3650 if (dup2 (fd, 0) == -1) /* setup stdin */
3651 _exit (1);
3652 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3653 _exit (1);
3654 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3655 _exit (1);
3656
3657 _dbus_close_all ();
3658
3659 sigprocmask (SIG_SETMASK, &old_set, NULL);
3660
3661 /* If it looks fully-qualified, try execv first */
3662 if (progpath[0] == '/')
3663 {
3664 execv (progpath, argv);
3665 /* Ok, that failed. Now if path_fallback is given, let's
3666 * try unqualified. This is mostly a hack to work
3667 * around systems which ship dbus-launch in /usr/bin
3668 * but everything else in /bin (because dbus-launch
3669 * depends on X11).
3670 */
3671 if (path_fallback)
3672 /* We must have a slash, because we checked above */
3673 execvp (strrchr (progpath, '/')+1, argv);
3674 }
3675 else
3676 execvp (progpath, argv);
3677
3678 /* still nothing, we failed */
3679 _exit (1);
3680 }
3681
3682 /* parent process */
3683 close (result_pipe[WRITE_END]);
3684 close (errors_pipe[WRITE_END]);
3685 result_pipe[WRITE_END] = -1;
3686 errors_pipe[WRITE_END] = -1;
3687
3688 ret = 0;
3689 do
3690 {
3691 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3692 }
3693 while (ret > 0);
3694
3695 /* reap the child process to avoid it lingering as zombie */
3696 do
3697 {
3698 ret = waitpid (pid, &status, 0);
3699 }
3700 while (ret == -1 && errno == EINTR);
3701
3702 /* We succeeded if the process exited with status 0 and
3703 anything was read */
3704 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3705 {
3706 /* The process ended with error */
3707 DBusString error_message;
3708 if (!_dbus_string_init (&error_message))
3709 {
3710 _DBUS_SET_OOM (error);
3711 goto out;
3712 }
3713
3714 ret = 0;
3715 do
3716 {
3717 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3718 }
3719 while (ret > 0);
3720
3721 _dbus_string_set_length (result, orig_len);
3722 if (_dbus_string_get_length (&error_message) > 0)
3723 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3724 "%s terminated abnormally with the following error: %s",
3725 progpath, _dbus_string_get_data (&error_message));
3726 else
3727 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3728 "%s terminated abnormally without any error message",
3729 progpath);
3730 goto out;
3731 }
3732
3733 retval = TRUE;
3734
3735 out:
3736 sigprocmask (SIG_SETMASK, &old_set, NULL);
3737
3738 if (retval)
3739 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3740 else
3741 _DBUS_ASSERT_ERROR_IS_SET (error);
3742
3743 if (result_pipe[0] != -1)
3744 close (result_pipe[0]);
3745 if (result_pipe[1] != -1)
3746 close (result_pipe[1]);
3747 if (errors_pipe[0] != -1)
3748 close (errors_pipe[0]);
3749 if (errors_pipe[1] != -1)
3750 close (errors_pipe[1]);
3751
3752 return retval;
3753 }
3754 #endif
3755
3768 dbus_bool_t
3769 _dbus_get_autolaunch_address (const char *scope,
3770 DBusString *address,
3771 DBusError *error)
3772 {
3773 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3774 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3775 * but that's done elsewhere, and if it worked, this function wouldn't
3776 * be called.) */
3777 const char *display;
3778 char *progpath;
3779 char *argv[6];
3780 int i;
3781 DBusString uuid;
3782 dbus_bool_t retval;
3783
3784 if (_dbus_check_setuid ())
3785 {
3786 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3787 "Unable to autolaunch when setuid");
3788 return FALSE;
3789 }
3790
3791 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3792 retval = FALSE;
3793
3794 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3795 * dbus-launch-x11 is just going to fail. Rather than trying to
3796 * run it, we might as well bail out early with a nice error.
3797 *
3798 * This is not strictly true in a world where the user bus exists,
3799 * because dbus-launch --autolaunch knows how to connect to that -
3800 * but if we were going to connect to the user bus, we'd have done
3801 * so before trying autolaunch: in any case. */
3802 display = _dbus_getenv ("DISPLAY");
3803
3804 if (display == NULL || display[0] == '\0')
3805 {
3806 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3807 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3808 return FALSE;
3809 }
3810
3811 if (!_dbus_string_init (&uuid))
3812 {
3813 _DBUS_SET_OOM (error);
3814 return FALSE;
3815 }
3816
3817 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3818 {
3819 goto out;
3820 }
3821
3822 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3823 if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL)
3824 progpath = TEST_BUS_LAUNCH_BINARY;
3825 else
3826 #endif
3827 progpath = DBUS_BINDIR "/dbus-launch";
3828 /*
3829 * argv[0] is always dbus-launch, that's the name what we'll
3830 * get from /proc, or ps(1), regardless what the progpath is,
3831 * see fd.o#69716
3832 */
3833 i = 0;
3834 argv[i] = "dbus-launch";
3835 ++i;
3836 argv[i] = "--autolaunch";
3837 ++i;
3838 argv[i] = _dbus_string_get_data (&uuid);
3839 ++i;
3840 argv[i] = "--binary-syntax";
3841 ++i;
3842 argv[i] = "--close-stderr";
3843 ++i;
3844 argv[i] = NULL;
3845 ++i;
3846
3847 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3848
3849 retval = _read_subprocess_line_argv (progpath,
3850 TRUE,
3851 argv, address, error);
3852
3853 out:
3854 _dbus_string_free (&uuid);
3855 return retval;
3856 #else
3857 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3858 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3859 "set your DBUS_SESSION_BUS_ADDRESS instead");
3860 return FALSE;
3861 #endif
3862 }
3863
3882 dbus_bool_t
3883 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3884 dbus_bool_t create_if_not_found,
3885 DBusError *error)
3886 {
3887 DBusString filename;
3888 dbus_bool_t b;
3889
3890 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3891
3892 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3893 if (b)
3894 return TRUE;
3895
3896 dbus_error_free (error);
3897
3898 /* Fallback to the system machine ID */
3899 _dbus_string_init_const (&filename, "/etc/machine-id");
3900 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3901
3902 if (b)
3903 {
3904 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3905 * complain if that isn't possible for whatever reason */
3906 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3907 _dbus_write_uuid_file (&filename, machine_id, NULL);
3908
3909 return TRUE;
3910 }
3911
3912 if (!create_if_not_found)
3913 return FALSE;
3914
3915 /* if none found, try to make a new one */
3916 dbus_error_free (error);
3917 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3918
3919 if (!_dbus_generate_uuid (machine_id, error))
3920 return FALSE;
3921
3922 return _dbus_write_uuid_file (&filename, machine_id, error);
3923 }
3924
3932 dbus_bool_t
3933 _dbus_lookup_launchd_socket (DBusString *socket_path,
3934 const char *launchd_env_var,
3935 DBusError *error)
3936 {
3937 #ifdef DBUS_ENABLE_LAUNCHD
3938 char *argv[4];
3939 int i;
3940
3941 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3942
3943 if (_dbus_check_setuid ())
3944 {
3945 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3946 "Unable to find launchd socket when setuid");
3947 return FALSE;
3948 }
3949
3950 i = 0;
3951 argv[i] = "launchctl";
3952 ++i;
3953 argv[i] = "getenv";
3954 ++i;
3955 argv[i] = (char*)launchd_env_var;
3956 ++i;
3957 argv[i] = NULL;
3958 ++i;
3959
3960 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3961
3962 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
3963 {
3964 return FALSE;
3965 }
3966
3967 /* no error, but no result either */
3968 if (_dbus_string_get_length(socket_path) == 0)
3969 {
3970 return FALSE;
3971 }
3972
3973 /* strip the carriage-return */
3974 _dbus_string_shorten(socket_path, 1);
3975 return TRUE;
3976 #else /* DBUS_ENABLE_LAUNCHD */
3977 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
3978 "can't lookup socket from launchd; launchd support not compiled in");
3979 return FALSE;
3980 #endif
3981 }
3982
3983 #ifdef DBUS_ENABLE_LAUNCHD
3984 static dbus_bool_t
3985 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
3986 {
3987 dbus_bool_t valid_socket;
3988 DBusString socket_path;
3989
3990 if (_dbus_check_setuid ())
3991 {
3992 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3993 "Unable to find launchd socket when setuid");
3994 return FALSE;
3995 }
3996
3997 if (!_dbus_string_init (&socket_path))
3998 {
3999 _DBUS_SET_OOM (error);
4000 return FALSE;
4001 }
4002
4003 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4004
4005 if (dbus_error_is_set(error))
4006 {
4007 _dbus_string_free(&socket_path);
4008 return FALSE;
4009 }
4010
4011 if (!valid_socket)
4012 {
4013 dbus_set_error(error, "no socket path",
4014 "launchd did not provide a socket path, "
4015 "verify that org.freedesktop.dbus-session.plist is loaded!");
4016 _dbus_string_free(&socket_path);
4017 return FALSE;
4018 }
4019 if (!_dbus_string_append (address, "unix:path="))
4020 {
4021 _DBUS_SET_OOM (error);
4022 _dbus_string_free(&socket_path);
4023 return FALSE;
4024 }
4025 if (!_dbus_string_copy (&socket_path, 0, address,
4026 _dbus_string_get_length (address)))
4027 {
4028 _DBUS_SET_OOM (error);
4029 _dbus_string_free(&socket_path);
4030 return FALSE;
4031 }
4032
4033 _dbus_string_free(&socket_path);
4034 return TRUE;
4035 }
4036 #endif
4037
4038 dbus_bool_t
4039 _dbus_lookup_user_bus (dbus_bool_t *supported,
4040 DBusString *address,
4041 DBusError *error)
4042 {
4043 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4044 dbus_bool_t ret = FALSE;
4045 struct stat stbuf;
4046 DBusString user_bus_path;
4047
4048 if (runtime_dir == NULL)
4049 {
4050 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4051 *supported = FALSE;
4052 return TRUE; /* Cannot use it, but not an error */
4053 }
4054
4055 if (!_dbus_string_init (&user_bus_path))
4056 {
4057 _DBUS_SET_OOM (error);
4058 return FALSE;
4059 }
4060
4061 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4062 {
4063 _DBUS_SET_OOM (error);
4064 goto out;
4065 }
4066
4067 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4068 {
4069 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4070 _dbus_strerror (errno));
4071 *supported = FALSE;
4072 ret = TRUE; /* Cannot use it, but not an error */
4073 goto out;
4074 }
4075
4076 if (stbuf.st_uid != getuid ())
4077 {
4078 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4079 (long) stbuf.st_uid, (long) getuid ());
4080 *supported = FALSE;
4081 ret = TRUE; /* Cannot use it, but not an error */
4082 goto out;
4083 }
4084
4085 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4086 {
4087 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4088 (long) stbuf.st_mode);
4089 *supported = FALSE;
4090 ret = TRUE; /* Cannot use it, but not an error */
4091 goto out;
4092 }
4093
4094 if (!_dbus_string_append (address, "unix:path=") ||
4095 !_dbus_address_append_escaped (address, &user_bus_path))
4096 {
4097 _DBUS_SET_OOM (error);
4098 goto out;
4099 }
4100
4101 *supported = TRUE;
4102 ret = TRUE;
4103
4104 out:
4105 _dbus_string_free (&user_bus_path);
4106 return ret;
4107 }
4108
4128 dbus_bool_t
4129 _dbus_lookup_session_address (dbus_bool_t *supported,
4130 DBusString *address,
4131 DBusError *error)
4132 {
4133 #ifdef DBUS_ENABLE_LAUNCHD
4134 *supported = TRUE;
4135 return _dbus_lookup_session_address_launchd (address, error);
4136 #else
4137 *supported = FALSE;
4138
4139 if (!_dbus_lookup_user_bus (supported, address, error))
4140 return FALSE;
4141 else if (*supported)
4142 return TRUE;
4143
4144 /* On non-Mac Unix platforms, if the session address isn't already
4145 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4146 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4147 * autolaunch: global default; see init_session_address in
4148 * dbus/dbus-bus.c. */
4149 return TRUE;
4150 #endif
4151 }
4152
4160 void
4161 _dbus_flush_caches (void)
4162 {
4163 _dbus_user_database_flush_system ();
4164 }
4165
4179 dbus_bool_t
4180 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
4181 DBusCredentials *credentials)
4182 {
4183 DBusString homedir;
4184 DBusString dotdir;
4185 dbus_uid_t uid;
4186
4187 _dbus_assert (credentials != NULL);
4188 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
4189
4190 if (!_dbus_string_init (&homedir))
4191 return FALSE;
4192
4193 uid = _dbus_credentials_get_unix_uid (credentials);
4194 _dbus_assert (uid != DBUS_UID_UNSET);
4195
4196 if (!_dbus_homedir_from_uid (uid, &homedir))
4197 goto failed;
4198
4199 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4200 {
4201 const char *override;
4202
4203 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4204 if (override != NULL && *override != '\0')
4205 {
4206 _dbus_string_set_length (&homedir, 0);
4207 if (!_dbus_string_append (&homedir, override))
4208 goto failed;
4209
4210 _dbus_verbose ("Using fake homedir for testing: %s\n",
4211 _dbus_string_get_const_data (&homedir));
4212 }
4213 else
4214 {
4215 /* Not strictly thread-safe, but if we fail at thread-safety here,
4216 * the worst that will happen is some extra warnings. */
4217 static dbus_bool_t already_warned = FALSE;
4218 if (!already_warned)
4219 {
4220 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
4221 already_warned = TRUE;
4222 }
4223 }
4224 }
4225 #endif
4226
4227 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4228 if (!_dbus_concat_dir_and_file (&homedir,
4229 &dotdir))
4230 goto failed;
4231
4232 if (!_dbus_string_copy (&homedir, 0,
4233 directory, _dbus_string_get_length (directory))) {
4234 goto failed;
4235 }
4236
4237 _dbus_string_free (&homedir);
4238 return TRUE;
4239
4240 failed:
4241 _dbus_string_free (&homedir);
4242 return FALSE;
4243 }
4244
4245 //PENDING(kdab) docs
4246 dbus_bool_t
4247 _dbus_daemon_publish_session_bus_address (const char* addr,
4248 const char *scope)
4249 {
4250 return TRUE;
4251 }
4252
4253 //PENDING(kdab) docs
4254 void
4255 _dbus_daemon_unpublish_session_bus_address (void)
4256 {
4257
4258 }
4259
4266 dbus_bool_t
4267 _dbus_get_is_errno_eagain_or_ewouldblock (int e)
4268 {
4269 return e == EAGAIN || e == EWOULDBLOCK;
4270 }
4271
4279 dbus_bool_t
4280 _dbus_delete_directory (const DBusString *filename,
4281 DBusError *error)
4282 {
4283 const char *filename_c;
4284
4285 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4286
4287 filename_c = _dbus_string_get_const_data (filename);
4288
4289 if (rmdir (filename_c) != 0)
4290 {
4291 dbus_set_error (error, DBUS_ERROR_FAILED,
4292 "Failed to remove directory %s: %s\n",
4293 filename_c, _dbus_strerror (errno));
4294 return FALSE;
4295 }
4296
4297 return TRUE;
4298 }
4299
4307 dbus_bool_t
4308 _dbus_socket_can_pass_unix_fd (DBusSocket fd)
4309 {
4310 #ifdef SCM_RIGHTS
4311 union {
4312 struct sockaddr sa;
4313 struct sockaddr_storage storage;
4314 struct sockaddr_un un;
4315 } sa_buf;
4316
4317 socklen_t sa_len = sizeof(sa_buf);
4318
4319 _DBUS_ZERO(sa_buf);
4320
4321 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4322 return FALSE;
4323
4324 return sa_buf.sa.sa_family == AF_UNIX;
4325
4326 #else
4327 return FALSE;
4328
4329 #endif
4330 }
4331
4336 void
4337 _dbus_close_all (void)
4338 {
4339 int maxfds, i;
4340
4341 #ifdef __linux__
4342 DIR *d;
4343
4344 /* On Linux we can optimize this a bit if /proc is available. If it
4345 isn't available, fall back to the brute force way. */
4346
4347 d = opendir ("/proc/self/fd");
4348 if (d)
4349 {
4350 for (;;)
4351 {
4352 struct dirent buf, *de;
4353 int k, fd;
4354 long l;
4355 char *e = NULL;
4356
4357 k = readdir_r (d, &buf, &de);
4358 if (k != 0 || !de)
4359 break;
4360
4361 if (de->d_name[0] == '.')
4362 continue;
4363
4364 errno = 0;
4365 l = strtol (de->d_name, &e, 10);
4366 if (errno != 0 || e == NULL || *e != '\0')
4367 continue;
4368
4369 fd = (int) l;
4370 if (fd < 3)
4371 continue;
4372
4373 if (fd == dirfd (d))
4374 continue;
4375
4376 close (fd);
4377 }
4378
4379 closedir (d);
4380 return;
4381 }
4382 #endif
4383
4384 maxfds = sysconf (_SC_OPEN_MAX);
4385
4386 /* Pick something reasonable if for some reason sysconf says
4387 * unlimited.
4388 */
4389 if (maxfds < 0)
4390 maxfds = 1024;
4391
4392 /* close all inherited fds */
4393 for (i = 3; i < maxfds; i++)
4394 close (i);
4395 }
4396
4406 dbus_bool_t
4407 _dbus_check_setuid (void)
4408 {
4409 /* TODO: get __libc_enable_secure exported from glibc.
4410 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4411 */
4412 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4413 {
4414 /* See glibc/include/unistd.h */
4415 extern int __libc_enable_secure;
4416 return __libc_enable_secure;
4417 }
4418 #elif defined(HAVE_ISSETUGID)
4419 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4420 return issetugid ();
4421 #else
4422 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4423 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4424
4425 /* We call into this function from _dbus_threads_init_platform_specific()
4426 * to make sure these are initialized before we start threading. */
4427 static dbus_bool_t check_setuid_initialised;
4428 static dbus_bool_t is_setuid;
4429
4430 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4431 {
4432 #ifdef HAVE_GETRESUID
4433 if (getresuid (&ruid, &euid, &suid) != 0 ||
4434 getresgid (&rgid, &egid, &sgid) != 0)
4435 #endif /* HAVE_GETRESUID */
4436 {
4437 suid = ruid = getuid ();
4438 sgid = rgid = getgid ();
4439 euid = geteuid ();
4440 egid = getegid ();
4441 }
4442
4443 check_setuid_initialised = TRUE;
4444 is_setuid = (ruid != euid || ruid != suid ||
4445 rgid != egid || rgid != sgid);
4446
4447 }
4448 return is_setuid;
4449 #endif
4450 }
4451
4459 dbus_bool_t
4460 _dbus_append_address_from_socket (DBusSocket fd,
4461 DBusString *address,
4462 DBusError *error)
4463 {
4464 union {
4465 struct sockaddr sa;
4466 struct sockaddr_storage storage;
4467 struct sockaddr_un un;
4468 struct sockaddr_in ipv4;
4469 struct sockaddr_in6 ipv6;
4470 } socket;
4471 char hostip[INET6_ADDRSTRLEN];
4472 int size = sizeof (socket);
4473 DBusString path_str;
4474
4475 if (getsockname (fd.fd, &socket.sa, &size))
4476 goto err;
4477
4478 switch (socket.sa.sa_family)
4479 {
4480 case AF_UNIX:
4481 if (socket.un.sun_path[0]=='\0')
4482 {
4483 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4484 if (_dbus_string_append (address, "unix:abstract=") &&
4485 _dbus_address_append_escaped (address, &path_str))
4486 return TRUE;
4487 }
4488 else
4489 {
4490 _dbus_string_init_const (&path_str, socket.un.sun_path);
4491 if (_dbus_string_append (address, "unix:path=") &&
4492 _dbus_address_append_escaped (address, &path_str))
4493 return TRUE;
4494 }
4495 break;
4496 case AF_INET:
4497 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4498 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4499 hostip, ntohs (socket.ipv4.sin_port)))
4500 return TRUE;
4501 break;
4502 #ifdef AF_INET6
4503 case AF_INET6:
4504 _dbus_string_init_const (&path_str, hostip);
4505 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4506 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4507 ntohs (socket.ipv6.sin6_port)) &&
4508 _dbus_address_append_escaped (address, &path_str))
4509 return TRUE;
4510 break;
4511 #endif
4512 default:
4513 dbus_set_error (error,
4514 _dbus_error_from_errno (EINVAL),
4515 "Failed to read address from socket: Unknown socket type.");
4516 return FALSE;
4517 }
4518 err:
4519 dbus_set_error (error,
4520 _dbus_error_from_errno (errno),
4521 "Failed to open socket: %s",
4522 _dbus_strerror (errno));
4523 return FALSE;
4524 }
4525
4526 int
4527 _dbus_save_socket_errno (void)
4528 {
4529 return errno;
4530 }
4531
4532 void
4533 _dbus_restore_socket_errno (int saved_errno)
4534 {
4535 errno = saved_errno;
4536 }
4537
4538 /* 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:435
DBusAtomic
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:279
_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:392
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:284
_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:2275
_dbus_close_all
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:4337
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:601
_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:2956
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
_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:3370
_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:761
_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:152
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:123
DBUS_PID_FORMAT
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:119
_dbus_generate_uuid
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
Definition: dbus-internals.c:653
_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:884
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition: dbus-internals.h:148
_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:4460
_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:4407
_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:380
DBusGUID
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
Definition: dbus-internals.h:390
_dbus_getpid
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
Definition: dbus-sysdeps-unix.c:2662
_DBUS_POLLIN
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:388
_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:3019
_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:299
_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:3241
_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:383
_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:112
_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:2199
_dbus_close_socket
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
Definition: dbus-sysdeps-unix.c:283
_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:114
_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:2705
_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:3769
_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:590
_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:2588
_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:105
_dbus_read_socket_with_unix_fds
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
Definition: dbus-sysdeps-unix.c:355
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:148
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:3933
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:461
_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:2651
_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:4267
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:1235
_DBUS_POLLOUT
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:392
_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:628
_dbus_accept
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
Definition: dbus-sysdeps-unix.c:2220
_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:2753
DBusUserInfo::uid
dbus_uid_t uid
UID.
Definition: dbus-sysdeps-unix.h:108
_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:701
_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:4180
_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:2988
_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:4280
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:2903
_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:1460
_dbus_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition: dbus-sysdeps-unix.c:3178
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:189
_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:4161
_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:1002
_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:3515
_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:369
_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:116
_dbus_geteuid
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
Definition: dbus-sysdeps-unix.c:2680
_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:2621
TRUE
#define TRUE
Expands to "1".
DBusPollFD::fd
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:382
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition: dbus-internals.h:159
_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
READ_END
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:873
DBUS_UID_FORMAT
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:121
_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:832
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:3149
_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:2692
_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:3191
_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:1335
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:2776
_dbus_getuid
dbus_uid_t _dbus_getuid(void)
Gets our UID.
Definition: dbus-sysdeps-unix.c:2671
_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:3094
_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:2605
_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:3283
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:4129
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3213
FALSE
#define FALSE
Expands to "0".
_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:3883
_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:783
_dbus_print_backtrace
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
Definition: dbus-sysdeps-unix.c:3328
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:368
_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:317
_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:807
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition: dbus-sysdeps-unix.c:2800
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition: dbus-sysdeps-unix.c:3064
_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:1360
WRITE_END
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:875
dbus_gid_t
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:109
_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:3445
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:537
_DBUS_ZERO
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
Definition: dbus-internals.h:194
_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:4308
_dbus_getenv
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
dbus_uid_t
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:107
_dbus_poll
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
Definition: dbus-sysdeps-unix.c:2825
DBusPollFD::revents
short revents
Events that occurred.
Definition: dbus-sysdeps.h:384
_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:906
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:1108
_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:2934
DBusUserInfo
Information about a UNIX user.
Definition: dbus-sysdeps-unix.h:106
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:394