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

D-Bus 1.8.16

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List

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-transport.h"
33 #include "dbus-string.h"
34 #include "dbus-userdb.h"
35 #include "dbus-list.h"
36 #include "dbus-credentials.h"
37 #include "dbus-nonce.h"
38
39 #include <sys/types.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <signal.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <fcntl.h>
46 #include <sys/socket.h>
47 #include <dirent.h>
48 #include <sys/un.h>
49 #include <pwd.h>
50 #include <time.h>
51 #include <locale.h>
52 #include <sys/time.h>
53 #include <sys/stat.h>
54 #include <sys/wait.h>
55 #include <netinet/in.h>
56 #include <netdb.h>
57 #include <grp.h>
58 #include <arpa/inet.h>
59
60 #ifdef HAVE_ERRNO_H
61 #include <errno.h>
62 #endif
63 #ifdef HAVE_WRITEV
64 #include <sys/uio.h>
65 #endif
66 #ifdef HAVE_POLL
67 #include <sys/poll.h>
68 #endif
69 #ifdef HAVE_BACKTRACE
70 #include <execinfo.h>
71 #endif
72 #ifdef HAVE_GETPEERUCRED
73 #include <ucred.h>
74 #endif
75 #ifdef HAVE_ALLOCA_H
76 #include <alloca.h>
77 #endif
78
79 #ifdef HAVE_ADT
80 #include <bsm/adt.h>
81 #endif
82
83 #include "sd-daemon.h"
84
85 #if !DBUS_USE_SYNC
86 #include <pthread.h>
87 #endif
88
89 #ifndef O_BINARY
90 #define O_BINARY 0
91 #endif
92
93 #ifndef AI_ADDRCONFIG
94 #define AI_ADDRCONFIG 0
95 #endif
96
97 #ifndef HAVE_SOCKLEN_T
98 #define socklen_t int
99 #endif
100
101 #if defined (__sun) || defined (__sun__)
102 /*
103 * CMS_SPACE etc. definitions for Solaris < 10, based on
104 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
105 * via
106 * http://wiki.opencsw.org/porting-faq#toc10
107 *
108 * These are only redefined for Solaris, for now: if your OS needs these too,
109 * please file a bug. (Or preferably, improve your OS so they're not needed.)
110 */
111
112 # ifndef CMSG_ALIGN
113 # ifdef __sun__
114 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
115 # else
116 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
117 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
118 ~(sizeof (long) - 1))
119 # endif
120 # endif
121
122 # ifndef CMSG_SPACE
123 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
124 CMSG_ALIGN (len))
125 # endif
126
127 # ifndef CMSG_LEN
128 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
129 # endif
130
131 #endif /* Solaris */
132
133 static dbus_bool_t
134 _dbus_open_socket (int *fd_p,
135 int domain,
136 int type,
137 int protocol,
138 DBusError *error)
139 {
140 #ifdef SOCK_CLOEXEC
141 dbus_bool_t cloexec_done;
142
143 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
144 cloexec_done = *fd_p >= 0;
145
146 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
147 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
148 #endif
149 {
150 *fd_p = socket (domain, type, protocol);
151 }
152
153 if (*fd_p >= 0)
154 {
155 #ifdef SOCK_CLOEXEC
156 if (!cloexec_done)
157 #endif
158 {
159 _dbus_fd_set_close_on_exec(*fd_p);
160 }
161
162 _dbus_verbose ("socket fd %d opened\n", *fd_p);
163 return TRUE;
164 }
165 else
166 {
167 dbus_set_error(error,
168 _dbus_error_from_errno (errno),
169 "Failed to open socket: %s",
170 _dbus_strerror (errno));
171 return FALSE;
172 }
173 }
174
185 static dbus_bool_t
186 _dbus_open_unix_socket (int *fd,
187 DBusError *error)
188 {
189 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
190 }
191
200 dbus_bool_t
201 _dbus_close_socket (int fd,
202 DBusError *error)
203 {
204 return _dbus_close (fd, error);
205 }
206
216 int
217 _dbus_read_socket (int fd,
218 DBusString *buffer,
219 int count)
220 {
221 return _dbus_read (fd, buffer, count);
222 }
223
234 int
235 _dbus_write_socket (int fd,
236 const DBusString *buffer,
237 int start,
238 int len)
239 {
240 #if HAVE_DECL_MSG_NOSIGNAL
241 const char *data;
242 int bytes_written;
243
244 data = _dbus_string_get_const_data_len (buffer, start, len);
245
246 again:
247
248 bytes_written = send (fd, data, len, MSG_NOSIGNAL);
249
250 if (bytes_written < 0 && errno == EINTR)
251 goto again;
252
253 return bytes_written;
254
255 #else
256 return _dbus_write (fd, buffer, start, len);
257 #endif
258 }
259
272 int
273 _dbus_read_socket_with_unix_fds (int fd,
274 DBusString *buffer,
275 int count,
276 int *fds,
277 int *n_fds) {
278 #ifndef HAVE_UNIX_FD_PASSING
279 int r;
280
281 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
282 return r;
283
284 *n_fds = 0;
285 return r;
286
287 #else
288 int bytes_read;
289 int start;
290 struct msghdr m;
291 struct iovec iov;
292
293 _dbus_assert (count >= 0);
294 _dbus_assert (*n_fds >= 0);
295
296 start = _dbus_string_get_length (buffer);
297
298 if (!_dbus_string_lengthen (buffer, count))
299 {
300 errno = ENOMEM;
301 return -1;
302 }
303
304 _DBUS_ZERO(iov);
305 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
306 iov.iov_len = count;
307
308 _DBUS_ZERO(m);
309 m.msg_iov = &iov;
310 m.msg_iovlen = 1;
311
312 /* Hmm, we have no clue how long the control data will actually be
313 that is queued for us. The least we can do is assume that the
314 caller knows. Hence let's make space for the number of fds that
315 we shall read at max plus the cmsg header. */
316 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
317
318 /* It's probably safe to assume that systems with SCM_RIGHTS also
319 know alloca() */
320 m.msg_control = alloca(m.msg_controllen);
321 memset(m.msg_control, 0, m.msg_controllen);
322
323 /* Do not include the padding at the end when we tell the kernel
324 * how much we're willing to receive. This avoids getting
325 * the padding filled with additional fds that we weren't expecting,
326 * if a (potentially malicious) sender included them. (fd.o #83622) */
327 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
328
329 again:
330
331 bytes_read = recvmsg(fd, &m, 0
332 #ifdef MSG_CMSG_CLOEXEC
333 |MSG_CMSG_CLOEXEC
334 #endif
335 );
336
337 if (bytes_read < 0)
338 {
339 if (errno == EINTR)
340 goto again;
341 else
342 {
343 /* put length back (note that this doesn't actually realloc anything) */
344 _dbus_string_set_length (buffer, start);
345 return -1;
346 }
347 }
348 else
349 {
350 struct cmsghdr *cm;
351 dbus_bool_t found = FALSE;
352
353 if (m.msg_flags & MSG_CTRUNC)
354 {
355 /* Hmm, apparently the control data was truncated. The bad
356 thing is that we might have completely lost a couple of fds
357 without chance to recover them. Hence let's treat this as a
358 serious error. */
359
360 errno = ENOSPC;
361 _dbus_string_set_length (buffer, start);
362 return -1;
363 }
364
365 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
366 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
367 {
368 size_t i;
369 int *payload = (int *) CMSG_DATA (cm);
370 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
371 size_t payload_len_fds = payload_len_bytes / sizeof (int);
372 size_t fds_to_use;
373
374 /* Every non-negative int fits in a size_t without truncation,
375 * and we already know that *n_fds is non-negative, so
376 * casting (size_t) *n_fds is OK */
377 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
378
379 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
380 {
381 /* The fds in the payload will fit in our buffer */
382 fds_to_use = payload_len_fds;
383 }
384 else
385 {
386 /* Too many fds in the payload. This shouldn't happen
387 * any more because we're setting m.msg_controllen to
388 * the exact number we can accept, but be safe and
389 * truncate. */
390 fds_to_use = (size_t) *n_fds;
391
392 /* Close the excess fds to avoid DoS: if they stayed open,
393 * someone could send us an extra fd per message
394 * and we'd eventually run out. */
395 for (i = fds_to_use; i < payload_len_fds; i++)
396 {
397 close (payload[i]);
398 }
399 }
400
401 memcpy (fds, payload, fds_to_use * sizeof (int));
402 found = TRUE;
403 /* This cannot overflow because we have chosen fds_to_use
404 * to be <= *n_fds */
405 *n_fds = (int) fds_to_use;
406
407 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
408 worked, hence we need to go through this list and set
409 CLOEXEC everywhere in any case */
410 for (i = 0; i < fds_to_use; i++)
411 _dbus_fd_set_close_on_exec(fds[i]);
412
413 break;
414 }
415
416 if (!found)
417 *n_fds = 0;
418
419 /* put length back (doesn't actually realloc) */
420 _dbus_string_set_length (buffer, start + bytes_read);
421
422 #if 0
423 if (bytes_read > 0)
424 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
425 #endif
426
427 return bytes_read;
428 }
429 #endif
430 }
431
432 int
433 _dbus_write_socket_with_unix_fds(int fd,
434 const DBusString *buffer,
435 int start,
436 int len,
437 const int *fds,
438 int n_fds) {
439
440 #ifndef HAVE_UNIX_FD_PASSING
441
442 if (n_fds > 0) {
443 errno = ENOTSUP;
444 return -1;
445 }
446
447 return _dbus_write_socket(fd, buffer, start, len);
448 #else
449 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
450 #endif
451 }
452
453 int
454 _dbus_write_socket_with_unix_fds_two(int fd,
455 const DBusString *buffer1,
456 int start1,
457 int len1,
458 const DBusString *buffer2,
459 int start2,
460 int len2,
461 const int *fds,
462 int n_fds) {
463
464 #ifndef HAVE_UNIX_FD_PASSING
465
466 if (n_fds > 0) {
467 errno = ENOTSUP;
468 return -1;
469 }
470
471 return _dbus_write_socket_two(fd,
472 buffer1, start1, len1,
473 buffer2, start2, len2);
474 #else
475
476 struct msghdr m;
477 struct cmsghdr *cm;
478 struct iovec iov[2];
479 int bytes_written;
480
481 _dbus_assert (len1 >= 0);
482 _dbus_assert (len2 >= 0);
483 _dbus_assert (n_fds >= 0);
484
485 _DBUS_ZERO(iov);
486 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
487 iov[0].iov_len = len1;
488
489 if (buffer2)
490 {
491 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
492 iov[1].iov_len = len2;
493 }
494
495 _DBUS_ZERO(m);
496 m.msg_iov = iov;
497 m.msg_iovlen = buffer2 ? 2 : 1;
498
499 if (n_fds > 0)
500 {
501 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
502 m.msg_control = alloca(m.msg_controllen);
503 memset(m.msg_control, 0, m.msg_controllen);
504
505 cm = CMSG_FIRSTHDR(&m);
506 cm->cmsg_level = SOL_SOCKET;
507 cm->cmsg_type = SCM_RIGHTS;
508 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
509 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
510 }
511
512 again:
513
514 bytes_written = sendmsg (fd, &m, 0
515 #if HAVE_DECL_MSG_NOSIGNAL
516 |MSG_NOSIGNAL
517 #endif
518 );
519
520 if (bytes_written < 0 && errno == EINTR)
521 goto again;
522
523 #if 0
524 if (bytes_written > 0)
525 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
526 #endif
527
528 return bytes_written;
529 #endif
530 }
531
545 int
546 _dbus_write_socket_two (int fd,
547 const DBusString *buffer1,
548 int start1,
549 int len1,
550 const DBusString *buffer2,
551 int start2,
552 int len2)
553 {
554 #if HAVE_DECL_MSG_NOSIGNAL
555 struct iovec vectors[2];
556 const char *data1;
557 const char *data2;
558 int bytes_written;
559 struct msghdr m;
560
561 _dbus_assert (buffer1 != NULL);
562 _dbus_assert (start1 >= 0);
563 _dbus_assert (start2 >= 0);
564 _dbus_assert (len1 >= 0);
565 _dbus_assert (len2 >= 0);
566
567 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
568
569 if (buffer2 != NULL)
570 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
571 else
572 {
573 data2 = NULL;
574 start2 = 0;
575 len2 = 0;
576 }
577
578 vectors[0].iov_base = (char*) data1;
579 vectors[0].iov_len = len1;
580 vectors[1].iov_base = (char*) data2;
581 vectors[1].iov_len = len2;
582
583 _DBUS_ZERO(m);
584 m.msg_iov = vectors;
585 m.msg_iovlen = data2 ? 2 : 1;
586
587 again:
588
589 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
590
591 if (bytes_written < 0 && errno == EINTR)
592 goto again;
593
594 return bytes_written;
595
596 #else
597 return _dbus_write_two (fd, buffer1, start1, len1,
598 buffer2, start2, len2);
599 #endif
600 }
601
602 dbus_bool_t
603 _dbus_socket_is_invalid (int fd)
604 {
605 return fd < 0 ? TRUE : FALSE;
606 }
607
624 int
625 _dbus_read (int fd,
626 DBusString *buffer,
627 int count)
628 {
629 int bytes_read;
630 int start;
631 char *data;
632
633 _dbus_assert (count >= 0);
634
635 start = _dbus_string_get_length (buffer);
636
637 if (!_dbus_string_lengthen (buffer, count))
638 {
639 errno = ENOMEM;
640 return -1;
641 }
642
643 data = _dbus_string_get_data_len (buffer, start, count);
644
645 again:
646
647 bytes_read = read (fd, data, count);
648
649 if (bytes_read < 0)
650 {
651 if (errno == EINTR)
652 goto again;
653 else
654 {
655 /* put length back (note that this doesn't actually realloc anything) */
656 _dbus_string_set_length (buffer, start);
657 return -1;
658 }
659 }
660 else
661 {
662 /* put length back (doesn't actually realloc) */
663 _dbus_string_set_length (buffer, start + bytes_read);
664
665 #if 0
666 if (bytes_read > 0)
667 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
668 #endif
669
670 return bytes_read;
671 }
672 }
673
684 int
685 _dbus_write (int fd,
686 const DBusString *buffer,
687 int start,
688 int len)
689 {
690 const char *data;
691 int bytes_written;
692
693 data = _dbus_string_get_const_data_len (buffer, start, len);
694
695 again:
696
697 bytes_written = write (fd, data, len);
698
699 if (bytes_written < 0 && errno == EINTR)
700 goto again;
701
702 #if 0
703 if (bytes_written > 0)
704 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
705 #endif
706
707 return bytes_written;
708 }
709
730 int
731 _dbus_write_two (int fd,
732 const DBusString *buffer1,
733 int start1,
734 int len1,
735 const DBusString *buffer2,
736 int start2,
737 int len2)
738 {
739 _dbus_assert (buffer1 != NULL);
740 _dbus_assert (start1 >= 0);
741 _dbus_assert (start2 >= 0);
742 _dbus_assert (len1 >= 0);
743 _dbus_assert (len2 >= 0);
744
745 #ifdef HAVE_WRITEV
746 {
747 struct iovec vectors[2];
748 const char *data1;
749 const char *data2;
750 int bytes_written;
751
752 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
753
754 if (buffer2 != NULL)
755 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
756 else
757 {
758 data2 = NULL;
759 start2 = 0;
760 len2 = 0;
761 }
762
763 vectors[0].iov_base = (char*) data1;
764 vectors[0].iov_len = len1;
765 vectors[1].iov_base = (char*) data2;
766 vectors[1].iov_len = len2;
767
768 again:
769
770 bytes_written = writev (fd,
771 vectors,
772 data2 ? 2 : 1);
773
774 if (bytes_written < 0 && errno == EINTR)
775 goto again;
776
777 return bytes_written;
778 }
779 #else /* HAVE_WRITEV */
780 {
781 int ret1, ret2;
782
783 ret1 = _dbus_write (fd, buffer1, start1, len1);
784 if (ret1 == len1 && buffer2 != NULL)
785 {
786 ret2 = _dbus_write (fd, buffer2, start2, len2);
787 if (ret2 < 0)
788 ret2 = 0; /* we can't report an error as the first write was OK */
789
790 return ret1 + ret2;
791 }
792 else
793 return ret1;
794 }
795 #endif /* !HAVE_WRITEV */
796 }
797
798 #define _DBUS_MAX_SUN_PATH_LENGTH 99
799
829 int
830 _dbus_connect_unix_socket (const char *path,
831 dbus_bool_t abstract,
832 DBusError *error)
833 {
834 int fd;
835 size_t path_len;
836 struct sockaddr_un addr;
837
838 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
839
840 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
841 path, abstract);
842
843
844 if (!_dbus_open_unix_socket (&fd, error))
845 {
846 _DBUS_ASSERT_ERROR_IS_SET(error);
847 return -1;
848 }
849 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
850
851 _DBUS_ZERO (addr);
852 addr.sun_family = AF_UNIX;
853 path_len = strlen (path);
854
855 if (abstract)
856 {
857 #ifdef HAVE_ABSTRACT_SOCKETS
858 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
859 path_len++; /* Account for the extra nul byte added to the start of sun_path */
860
861 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
862 {
863 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
864 "Abstract socket name too long\n");
865 _dbus_close (fd, NULL);
866 return -1;
867 }
868
869 strncpy (&addr.sun_path[1], path, path_len);
870 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
871 #else /* HAVE_ABSTRACT_SOCKETS */
872 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
873 "Operating system does not support abstract socket namespace\n");
874 _dbus_close (fd, NULL);
875 return -1;
876 #endif /* ! HAVE_ABSTRACT_SOCKETS */
877 }
878 else
879 {
880 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
881 {
882 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
883 "Socket name too long\n");
884 _dbus_close (fd, NULL);
885 return -1;
886 }
887
888 strncpy (addr.sun_path, path, path_len);
889 }
890
891 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
892 {
893 dbus_set_error (error,
894 _dbus_error_from_errno (errno),
895 "Failed to connect to socket %s: %s",
896 path, _dbus_strerror (errno));
897
898 _dbus_close (fd, NULL);
899 return -1;
900 }
901
902 if (!_dbus_set_fd_nonblocking (fd, error))
903 {
904 _DBUS_ASSERT_ERROR_IS_SET (error);
905
906 _dbus_close (fd, NULL);
907 return -1;
908 }
909
910 return fd;
911 }
912
925 int
926 _dbus_connect_exec (const char *path,
927 char *const argv[],
928 DBusError *error)
929 {
930 int fds[2];
931 pid_t pid;
932 int retval;
933 dbus_bool_t cloexec_done = 0;
934
935 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
936
937 _dbus_verbose ("connecting to process %s\n", path);
938
939 #ifdef SOCK_CLOEXEC
940 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
941 cloexec_done = (retval >= 0);
942
943 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
944 #endif
945 {
946 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
947 }
948
949 if (retval < 0)
950 {
951 dbus_set_error (error,
952 _dbus_error_from_errno (errno),
953 "Failed to create socket pair: %s",
954 _dbus_strerror (errno));
955 return -1;
956 }
957
958 if (!cloexec_done)
959 {
960 _dbus_fd_set_close_on_exec (fds[0]);
961 _dbus_fd_set_close_on_exec (fds[1]);
962 }
963
964 pid = fork ();
965 if (pid < 0)
966 {
967 dbus_set_error (error,
968 _dbus_error_from_errno (errno),
969 "Failed to fork() to call %s: %s",
970 path, _dbus_strerror (errno));
971 close (fds[0]);
972 close (fds[1]);
973 return -1;
974 }
975
976 if (pid == 0)
977 {
978 /* child */
979 close (fds[0]);
980
981 dup2 (fds[1], STDIN_FILENO);
982 dup2 (fds[1], STDOUT_FILENO);
983
984 if (fds[1] != STDIN_FILENO &&
985 fds[1] != STDOUT_FILENO)
986 close (fds[1]);
987
988 /* Inherit STDERR and the controlling terminal from the
989 parent */
990
991 _dbus_close_all ();
992
993 execvp (path, argv);
994
995 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
996
997 _exit(1);
998 }
999
1000 /* parent */
1001 close (fds[1]);
1002
1003 if (!_dbus_set_fd_nonblocking (fds[0], error))
1004 {
1005 _DBUS_ASSERT_ERROR_IS_SET (error);
1006
1007 close (fds[0]);
1008 return -1;
1009 }
1010
1011 return fds[0];
1012 }
1013
1031 int
1032 _dbus_listen_unix_socket (const char *path,
1033 dbus_bool_t abstract,
1034 DBusError *error)
1035 {
1036 int listen_fd;
1037 struct sockaddr_un addr;
1038 size_t path_len;
1039
1040 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1041
1042 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1043 path, abstract);
1044
1045 if (!_dbus_open_unix_socket (&listen_fd, error))
1046 {
1047 _DBUS_ASSERT_ERROR_IS_SET(error);
1048 return -1;
1049 }
1050 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1051
1052 _DBUS_ZERO (addr);
1053 addr.sun_family = AF_UNIX;
1054 path_len = strlen (path);
1055
1056 if (abstract)
1057 {
1058 #ifdef HAVE_ABSTRACT_SOCKETS
1059 /* remember that abstract names aren't nul-terminated so we rely
1060 * on sun_path being filled in with zeroes above.
1061 */
1062 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1063 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1064
1065 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1066 {
1067 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1068 "Abstract socket name too long\n");
1069 _dbus_close (listen_fd, NULL);
1070 return -1;
1071 }
1072
1073 strncpy (&addr.sun_path[1], path, path_len);
1074 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1075 #else /* HAVE_ABSTRACT_SOCKETS */
1076 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1077 "Operating system does not support abstract socket namespace\n");
1078 _dbus_close (listen_fd, NULL);
1079 return -1;
1080 #endif /* ! HAVE_ABSTRACT_SOCKETS */
1081 }
1082 else
1083 {
1084 /* Discussed security implications of this with Nalin,
1085 * and we couldn't think of where it would kick our ass, but
1086 * it still seems a bit sucky. It also has non-security suckage;
1087 * really we'd prefer to exit if the socket is already in use.
1088 * But there doesn't seem to be a good way to do this.
1089 *
1090 * Just to be extra careful, I threw in the stat() - clearly
1091 * the stat() can't *fix* any security issue, but it at least
1092 * avoids inadvertent/accidental data loss.
1093 */
1094 {
1095 struct stat sb;
1096
1097 if (stat (path, &sb) == 0 &&
1098 S_ISSOCK (sb.st_mode))
1099 unlink (path);
1100 }
1101
1102 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1103 {
1104 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1105 "Abstract socket name too long\n");
1106 _dbus_close (listen_fd, NULL);
1107 return -1;
1108 }
1109
1110 strncpy (addr.sun_path, path, path_len);
1111 }
1112
1113 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1114 {
1115 dbus_set_error (error, _dbus_error_from_errno (errno),
1116 "Failed to bind socket \"%s\": %s",
1117 path, _dbus_strerror (errno));
1118 _dbus_close (listen_fd, NULL);
1119 return -1;
1120 }
1121
1122 if (listen (listen_fd, 30 /* backlog */) < 0)
1123 {
1124 dbus_set_error (error, _dbus_error_from_errno (errno),
1125 "Failed to listen on socket \"%s\": %s",
1126 path, _dbus_strerror (errno));
1127 _dbus_close (listen_fd, NULL);
1128 return -1;
1129 }
1130
1131 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1132 {
1133 _DBUS_ASSERT_ERROR_IS_SET (error);
1134 _dbus_close (listen_fd, NULL);
1135 return -1;
1136 }
1137
1138 /* Try opening up the permissions, but if we can't, just go ahead
1139 * and continue, maybe it will be good enough.
1140 */
1141 if (!abstract && chmod (path, 0777) < 0)
1142 _dbus_warn ("Could not set mode 0777 on socket %s\n",
1143 path);
1144
1145 return listen_fd;
1146 }
1147
1158 int
1159 _dbus_listen_systemd_sockets (int **fds,
1160 DBusError *error)
1161 {
1162 int r, n;
1163 unsigned fd;
1164 int *new_fds;
1165
1166 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1167
1168 n = sd_listen_fds (TRUE);
1169 if (n < 0)
1170 {
1171 dbus_set_error (error, _dbus_error_from_errno (-n),
1172 "Failed to acquire systemd socket: %s",
1173 _dbus_strerror (-n));
1174 return -1;
1175 }
1176
1177 if (n <= 0)
1178 {
1179 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1180 "No socket received.");
1181 return -1;
1182 }
1183
1184 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1185 {
1186 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1187 if (r < 0)
1188 {
1189 dbus_set_error (error, _dbus_error_from_errno (-r),
1190 "Failed to verify systemd socket type: %s",
1191 _dbus_strerror (-r));
1192 return -1;
1193 }
1194
1195 if (!r)
1196 {
1197 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1198 "Passed socket has wrong type.");
1199 return -1;
1200 }
1201 }
1202
1203 /* OK, the file descriptors are all good, so let's take posession of
1204 them then. */
1205
1206 new_fds = dbus_new (int, n);
1207 if (!new_fds)
1208 {
1209 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1210 "Failed to allocate file handle array.");
1211 goto fail;
1212 }
1213
1214 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1215 {
1216 if (!_dbus_set_fd_nonblocking (fd, error))
1217 {
1218 _DBUS_ASSERT_ERROR_IS_SET (error);
1219 goto fail;
1220 }
1221
1222 new_fds[fd - SD_LISTEN_FDS_START] = fd;
1223 }
1224
1225 *fds = new_fds;
1226 return n;
1227
1228 fail:
1229
1230 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1231 {
1232 _dbus_close (fd, NULL);
1233 }
1234
1235 dbus_free (new_fds);
1236 return -1;
1237 }
1238
1252 int
1253 _dbus_connect_tcp_socket (const char *host,
1254 const char *port,
1255 const char *family,
1256 DBusError *error)
1257 {
1258 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1259 }
1260
1261 int
1262 _dbus_connect_tcp_socket_with_nonce (const char *host,
1263 const char *port,
1264 const char *family,
1265 const char *noncefile,
1266 DBusError *error)
1267 {
1268 int saved_errno = 0;
1269 int fd = -1, res;
1270 struct addrinfo hints;
1271 struct addrinfo *ai, *tmp;
1272
1273 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1274
1275 _DBUS_ZERO (hints);
1276
1277 if (!family)
1278 hints.ai_family = AF_UNSPEC;
1279 else if (!strcmp(family, "ipv4"))
1280 hints.ai_family = AF_INET;
1281 else if (!strcmp(family, "ipv6"))
1282 hints.ai_family = AF_INET6;
1283 else
1284 {
1285 dbus_set_error (error,
1286 DBUS_ERROR_BAD_ADDRESS,
1287 "Unknown address family %s", family);
1288 return -1;
1289 }
1290 hints.ai_protocol = IPPROTO_TCP;
1291 hints.ai_socktype = SOCK_STREAM;
1292 hints.ai_flags = AI_ADDRCONFIG;
1293
1294 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1295 {
1296 dbus_set_error (error,
1297 _dbus_error_from_errno (errno),
1298 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1299 host, port, gai_strerror(res), res);
1300 return -1;
1301 }
1302
1303 tmp = ai;
1304 while (tmp)
1305 {
1306 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1307 {
1308 freeaddrinfo(ai);
1309 _DBUS_ASSERT_ERROR_IS_SET(error);
1310 return -1;
1311 }
1312 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1313
1314 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1315 {
1316 saved_errno = errno;
1317 _dbus_close(fd, NULL);
1318 fd = -1;
1319 tmp = tmp->ai_next;
1320 continue;
1321 }
1322
1323 break;
1324 }
1325 freeaddrinfo(ai);
1326
1327 if (fd == -1)
1328 {
1329 dbus_set_error (error,
1330 _dbus_error_from_errno (saved_errno),
1331 "Failed to connect to socket \"%s:%s\" %s",
1332 host, port, _dbus_strerror(saved_errno));
1333 return -1;
1334 }
1335
1336 if (noncefile != NULL)
1337 {
1338 DBusString noncefileStr;
1339 dbus_bool_t ret;
1340 _dbus_string_init_const (&noncefileStr, noncefile);
1341 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1342 _dbus_string_free (&noncefileStr);
1343
1344 if (!ret)
1345 {
1346 _dbus_close (fd, NULL);
1347 return -1;
1348 }
1349 }
1350
1351 if (!_dbus_set_fd_nonblocking (fd, error))
1352 {
1353 _dbus_close (fd, NULL);
1354 return -1;
1355 }
1356
1357 return fd;
1358 }
1359
1376 int
1377 _dbus_listen_tcp_socket (const char *host,
1378 const char *port,
1379 const char *family,
1380 DBusString *retport,
1381 int **fds_p,
1382 DBusError *error)
1383 {
1384 int saved_errno;
1385 int nlisten_fd = 0, *listen_fd = NULL, res, i;
1386 struct addrinfo hints;
1387 struct addrinfo *ai, *tmp;
1388 unsigned int reuseaddr;
1389
1390 *fds_p = NULL;
1391 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1392
1393 _DBUS_ZERO (hints);
1394
1395 if (!family)
1396 hints.ai_family = AF_UNSPEC;
1397 else if (!strcmp(family, "ipv4"))
1398 hints.ai_family = AF_INET;
1399 else if (!strcmp(family, "ipv6"))
1400 hints.ai_family = AF_INET6;
1401 else
1402 {
1403 dbus_set_error (error,
1404 DBUS_ERROR_BAD_ADDRESS,
1405 "Unknown address family %s", family);
1406 return -1;
1407 }
1408
1409 hints.ai_protocol = IPPROTO_TCP;
1410 hints.ai_socktype = SOCK_STREAM;
1411 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1412
1413 redo_lookup_with_port:
1414 ai = NULL;
1415 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1416 {
1417 dbus_set_error (error,
1418 _dbus_error_from_errno (errno),
1419 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1420 host ? host : "*", port, gai_strerror(res), res);
1421 goto failed;
1422 }
1423
1424 tmp = ai;
1425 while (tmp)
1426 {
1427 int fd = -1, *newlisten_fd;
1428 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1429 {
1430 _DBUS_ASSERT_ERROR_IS_SET(error);
1431 goto failed;
1432 }
1433 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1434
1435 reuseaddr = 1;
1436 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1437 {
1438 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1439 host ? host : "*", port, _dbus_strerror (errno));
1440 }
1441
1442 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1443 {
1444 saved_errno = errno;
1445 _dbus_close(fd, NULL);
1446 if (saved_errno == EADDRINUSE)
1447 {
1448 /* Depending on kernel policy, it may or may not
1449 be neccessary to bind to both IPv4 & 6 addresses
1450 so ignore EADDRINUSE here */
1451 tmp = tmp->ai_next;
1452 continue;
1453 }
1454 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1455 "Failed to bind socket \"%s:%s\": %s",
1456 host ? host : "*", port, _dbus_strerror (saved_errno));
1457 goto failed;
1458 }
1459
1460 if (listen (fd, 30 /* backlog */) < 0)
1461 {
1462 saved_errno = errno;
1463 _dbus_close (fd, NULL);
1464 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1465 "Failed to listen on socket \"%s:%s\": %s",
1466 host ? host : "*", port, _dbus_strerror (saved_errno));
1467 goto failed;
1468 }
1469
1470 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
1471 if (!newlisten_fd)
1472 {
1473 saved_errno = errno;
1474 _dbus_close (fd, NULL);
1475 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1476 "Failed to allocate file handle array: %s",
1477 _dbus_strerror (saved_errno));
1478 goto failed;
1479 }
1480 listen_fd = newlisten_fd;
1481 listen_fd[nlisten_fd] = fd;
1482 nlisten_fd++;
1483
1484 if (!_dbus_string_get_length(retport))
1485 {
1486 /* If the user didn't specify a port, or used 0, then
1487 the kernel chooses a port. After the first address
1488 is bound to, we need to force all remaining addresses
1489 to use the same port */
1490 if (!port || !strcmp(port, "0"))
1491 {
1492 int result;
1493 struct sockaddr_storage addr;
1494 socklen_t addrlen;
1495 char portbuf[50];
1496
1497 addrlen = sizeof(addr);
1498 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1499
1500 if (result == -1 ||
1501 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1502 portbuf, sizeof(portbuf),
1503 NI_NUMERICHOST)) != 0)
1504 {
1505 dbus_set_error (error, _dbus_error_from_errno (errno),
1506 "Failed to resolve port \"%s:%s\": %s (%s)",
1507 host ? host : "*", port, gai_strerror(res), res);
1508 goto failed;
1509 }
1510 if (!_dbus_string_append(retport, portbuf))
1511 {
1512 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1513 goto failed;
1514 }
1515
1516 /* Release current address list & redo lookup */
1517 port = _dbus_string_get_const_data(retport);
1518 freeaddrinfo(ai);
1519 goto redo_lookup_with_port;
1520 }
1521 else
1522 {
1523 if (!_dbus_string_append(retport, port))
1524 {
1525 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1526 goto failed;
1527 }
1528 }
1529 }
1530
1531 tmp = tmp->ai_next;
1532 }
1533 freeaddrinfo(ai);
1534 ai = NULL;
1535
1536 if (!nlisten_fd)
1537 {
1538 errno = EADDRINUSE;
1539 dbus_set_error (error, _dbus_error_from_errno (errno),
1540 "Failed to bind socket \"%s:%s\": %s",
1541 host ? host : "*", port, _dbus_strerror (errno));
1542 goto failed;
1543 }
1544
1545 for (i = 0 ; i < nlisten_fd ; i++)
1546 {
1547 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
1548 {
1549 goto failed;
1550 }
1551 }
1552
1553 *fds_p = listen_fd;
1554
1555 return nlisten_fd;
1556
1557 failed:
1558 if (ai)
1559 freeaddrinfo(ai);
1560 for (i = 0 ; i < nlisten_fd ; i++)
1561 _dbus_close(listen_fd[i], NULL);
1562 dbus_free(listen_fd);
1563 return -1;
1564 }
1565
1566 static dbus_bool_t
1567 write_credentials_byte (int server_fd,
1568 DBusError *error)
1569 {
1570 int bytes_written;
1571 char buf[1] = { '\0' };
1572 #if defined(HAVE_CMSGCRED)
1573 union {
1574 struct cmsghdr hdr;
1575 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1576 } cmsg;
1577 struct iovec iov;
1578 struct msghdr msg;
1579 iov.iov_base = buf;
1580 iov.iov_len = 1;
1581
1582 _DBUS_ZERO(msg);
1583 msg.msg_iov = &iov;
1584 msg.msg_iovlen = 1;
1585
1586 msg.msg_control = (caddr_t) &cmsg;
1587 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1588 _DBUS_ZERO(cmsg);
1589 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1590 cmsg.hdr.cmsg_level = SOL_SOCKET;
1591 cmsg.hdr.cmsg_type = SCM_CREDS;
1592 #endif
1593
1594 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1595
1596 again:
1597
1598 #if defined(HAVE_CMSGCRED)
1599 bytes_written = sendmsg (server_fd, &msg, 0
1600 #if HAVE_DECL_MSG_NOSIGNAL
1601 |MSG_NOSIGNAL
1602 #endif
1603 );
1604
1605 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1606 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1607 * only allows that on AF_UNIX. Try just doing a send() instead. */
1608 if (bytes_written < 0 && errno == EINVAL)
1609 #endif
1610 {
1611 bytes_written = send (server_fd, buf, 1, 0
1612 #if HAVE_DECL_MSG_NOSIGNAL
1613 |MSG_NOSIGNAL
1614 #endif
1615 );
1616 }
1617
1618 if (bytes_written < 0 && errno == EINTR)
1619 goto again;
1620
1621 if (bytes_written < 0)
1622 {
1623 dbus_set_error (error, _dbus_error_from_errno (errno),
1624 "Failed to write credentials byte: %s",
1625 _dbus_strerror (errno));
1626 return FALSE;
1627 }
1628 else if (bytes_written == 0)
1629 {
1630 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1631 "wrote zero bytes writing credentials byte");
1632 return FALSE;
1633 }
1634 else
1635 {
1636 _dbus_assert (bytes_written == 1);
1637 _dbus_verbose ("wrote credentials byte\n");
1638 return TRUE;
1639 }
1640 }
1641
1663 dbus_bool_t
1664 _dbus_read_credentials_socket (int client_fd,
1665 DBusCredentials *credentials,
1666 DBusError *error)
1667 {
1668 struct msghdr msg;
1669 struct iovec iov;
1670 char buf;
1671 dbus_uid_t uid_read;
1672 dbus_pid_t pid_read;
1673 int bytes_read;
1674
1675 #ifdef HAVE_CMSGCRED
1676 union {
1677 struct cmsghdr hdr;
1678 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1679 } cmsg;
1680 #endif
1681
1682 uid_read = DBUS_UID_UNSET;
1683 pid_read = DBUS_PID_UNSET;
1684
1685 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1686
1687 /* The POSIX spec certainly doesn't promise this, but
1688 * we need these assertions to fail as soon as we're wrong about
1689 * it so we can do the porting fixups
1690 */
1691 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
1692 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
1693 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
1694
1695 _dbus_credentials_clear (credentials);
1696
1697 iov.iov_base = &buf;
1698 iov.iov_len = 1;
1699
1700 _DBUS_ZERO(msg);
1701 msg.msg_iov = &iov;
1702 msg.msg_iovlen = 1;
1703
1704 #if defined(HAVE_CMSGCRED)
1705 _DBUS_ZERO(cmsg);
1706 msg.msg_control = (caddr_t) &cmsg;
1707 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1708 #endif
1709
1710 again:
1711 bytes_read = recvmsg (client_fd, &msg, 0);
1712
1713 if (bytes_read < 0)
1714 {
1715 if (errno == EINTR)
1716 goto again;
1717
1718 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1719 * normally only call read_credentials if the socket was ready
1720 * for reading
1721 */
1722
1723 dbus_set_error (error, _dbus_error_from_errno (errno),
1724 "Failed to read credentials byte: %s",
1725 _dbus_strerror (errno));
1726 return FALSE;
1727 }
1728 else if (bytes_read == 0)
1729 {
1730 /* this should not happen unless we are using recvmsg wrong,
1731 * so is essentially here for paranoia
1732 */
1733 dbus_set_error (error, DBUS_ERROR_FAILED,
1734 "Failed to read credentials byte (zero-length read)");
1735 return FALSE;
1736 }
1737 else if (buf != '\0')
1738 {
1739 dbus_set_error (error, DBUS_ERROR_FAILED,
1740 "Credentials byte was not nul");
1741 return FALSE;
1742 }
1743
1744 _dbus_verbose ("read credentials byte\n");
1745
1746 {
1747 #ifdef SO_PEERCRED
1748 /* Supported by at least Linux and OpenBSD, with minor differences.
1749 *
1750 * This mechanism passes the process ID through and does not require
1751 * the peer's cooperation, so we prefer it over all others. Notably,
1752 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
1753 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
1754 * because this is much less fragile.
1755 */
1756 #ifdef __OpenBSD__
1757 struct sockpeercred cr;
1758 #else
1759 struct ucred cr;
1760 #endif
1761 int cr_len = sizeof (cr);
1762
1763 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
1764 cr_len == sizeof (cr))
1765 {
1766 pid_read = cr.pid;
1767 uid_read = cr.uid;
1768 }
1769 else
1770 {
1771 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
1772 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
1773 }
1774 #elif defined(HAVE_CMSGCRED)
1775 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
1776 * presence of that struct implies SCM_CREDS. Supported by at least
1777 * FreeBSD and DragonflyBSD.
1778 *
1779 * This mechanism requires the peer to help us (it has to send us a
1780 * SCM_CREDS message) but it does pass the process ID through,
1781 * which makes it better than getpeereid().
1782 */
1783 struct cmsgcred *cred;
1784 struct cmsghdr *cmsgp;
1785
1786 for (cmsgp = CMSG_FIRSTHDR (&msg);
1787 cmsgp != NULL;
1788 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
1789 {
1790 if (cmsgp->cmsg_type == SCM_CREDS &&
1791 cmsgp->cmsg_level == SOL_SOCKET &&
1792 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
1793 {
1794 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
1795 pid_read = cred->cmcred_pid;
1796 uid_read = cred->cmcred_euid;
1797 break;
1798 }
1799 }
1800
1801 #elif defined(HAVE_GETPEERUCRED)
1802 /* Supported in at least Solaris >= 10. It should probably be higher
1803 * up this list, because it carries the pid and we use this code path
1804 * for audit data. */
1805 ucred_t * ucred = NULL;
1806 if (getpeerucred (client_fd, &ucred) == 0)
1807 {
1808 pid_read = ucred_getpid (ucred);
1809 uid_read = ucred_geteuid (ucred);
1810 #ifdef HAVE_ADT
1811 /* generate audit session data based on socket ucred */
1812 adt_session_data_t *adth = NULL;
1813 adt_export_data_t *data = NULL;
1814 size_t size = 0;
1815 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
1816 {
1817 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
1818 }
1819 else
1820 {
1821 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
1822 {
1823 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
1824 }
1825 else
1826 {
1827 size = adt_export_session_data (adth, &data);
1828 if (size <= 0)
1829 {
1830 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
1831 }
1832 else
1833 {
1834 _dbus_credentials_add_adt_audit_data (credentials, data, size);
1835 free (data);
1836 }
1837 }
1838 (void) adt_end_session (adth);
1839 }
1840 #endif /* HAVE_ADT */
1841 }
1842 else
1843 {
1844 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
1845 }
1846 if (ucred != NULL)
1847 ucred_free (ucred);
1848
1849 /* ----------------------------------------------------------------
1850 * When adding new mechanisms, please add them above this point
1851 * if they support passing the process ID through, or below if not.
1852 * ---------------------------------------------------------------- */
1853
1854 #elif defined(HAVE_GETPEEREID)
1855 /* getpeereid() originates from D.J. Bernstein and is fairly
1856 * widely-supported. According to a web search, it might be present in
1857 * any/all of:
1858 *
1859 * - AIX?
1860 * - Blackberry?
1861 * - Cygwin
1862 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
1863 * - Mac OS X
1864 * - Minix 3.1.8+
1865 * - MirBSD?
1866 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
1867 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
1868 * - QNX?
1869 */
1870 uid_t euid;
1871 gid_t egid;
1872 if (getpeereid (client_fd, &euid, &egid) == 0)
1873 {
1874 uid_read = euid;
1875 }
1876 else
1877 {
1878 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
1879 }
1880 #else /* no supported mechanism */
1881
1882 #warning Socket credentials not supported on this Unix OS
1883 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
1884
1885 /* Please add other operating systems known to support at least one of
1886 * the mechanisms above to this list, keeping alphabetical order.
1887 * Everything not in this list is best-effort.
1888 */
1889 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
1890 defined(__linux__) || \
1891 defined(__OpenBSD__) || \
1892 defined(__NetBSD__)
1893 # error Credentials passing not working on this OS is a regression!
1894 #endif
1895
1896 _dbus_verbose ("Socket credentials not supported on this OS\n");
1897 #endif
1898 }
1899
1900 _dbus_verbose ("Credentials:"
1901 " pid "DBUS_PID_FORMAT
1902 " uid "DBUS_UID_FORMAT
1903 "\n",
1904 pid_read,
1905 uid_read);
1906
1907 if (pid_read != DBUS_PID_UNSET)
1908 {
1909 if (!_dbus_credentials_add_pid (credentials, pid_read))
1910 {
1911 _DBUS_SET_OOM (error);
1912 return FALSE;
1913 }
1914 }
1915
1916 if (uid_read != DBUS_UID_UNSET)
1917 {
1918 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
1919 {
1920 _DBUS_SET_OOM (error);
1921 return FALSE;
1922 }
1923 }
1924
1925 return TRUE;
1926 }
1927
1945 dbus_bool_t
1946 _dbus_send_credentials_socket (int server_fd,
1947 DBusError *error)
1948 {
1949 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1950
1951 if (write_credentials_byte (server_fd, error))
1952 return TRUE;
1953 else
1954 return FALSE;
1955 }
1956
1966 int
1967 _dbus_accept (int listen_fd)
1968 {
1969 int client_fd;
1970 struct sockaddr addr;
1971 socklen_t addrlen;
1972 #ifdef HAVE_ACCEPT4
1973 dbus_bool_t cloexec_done;
1974 #endif
1975
1976 addrlen = sizeof (addr);
1977
1978 retry:
1979
1980 #ifdef HAVE_ACCEPT4
1981 /*
1982 * At compile-time, we assume that if accept4() is available in
1983 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
1984 * not necessarily true that either is supported by the running kernel.
1985 */
1986 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
1987 cloexec_done = client_fd >= 0;
1988
1989 if (client_fd < 0 && (errno == ENOSYS || errno == EINVAL))
1990 #endif
1991 {
1992 client_fd = accept (listen_fd, &addr, &addrlen);
1993 }
1994
1995 if (client_fd < 0)
1996 {
1997 if (errno == EINTR)
1998 goto retry;
1999 }
2000
2001 _dbus_verbose ("client fd %d accepted\n", client_fd);
2002
2003 #ifdef HAVE_ACCEPT4
2004 if (!cloexec_done)
2005 #endif
2006 {
2007 _dbus_fd_set_close_on_exec(client_fd);
2008 }
2009
2010 return client_fd;
2011 }
2012
2021 dbus_bool_t
2022 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2023 {
2024 const char *directory;
2025 struct stat sb;
2026
2027 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2028
2029 directory = _dbus_string_get_const_data (dir);
2030
2031 if (stat (directory, &sb) < 0)
2032 {
2033 dbus_set_error (error, _dbus_error_from_errno (errno),
2034 "%s", _dbus_strerror (errno));
2035
2036 return FALSE;
2037 }
2038
2039 if (sb.st_uid != geteuid ())
2040 {
2041 dbus_set_error (error, DBUS_ERROR_FAILED,
2042 "%s directory is owned by user %lu, not %lu",
2043 directory,
2044 (unsigned long) sb.st_uid,
2045 (unsigned long) geteuid ());
2046 return FALSE;
2047 }
2048
2049 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2050 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2051 {
2052 dbus_set_error (error, DBUS_ERROR_FAILED,
2053 "%s directory is not private to the user", directory);
2054 return FALSE;
2055 }
2056
2057 return TRUE;
2058 }
2059
2060 static dbus_bool_t
2061 fill_user_info_from_passwd (struct passwd *p,
2062 DBusUserInfo *info,
2063 DBusError *error)
2064 {
2065 _dbus_assert (p->pw_name != NULL);
2066 _dbus_assert (p->pw_dir != NULL);
2067
2068 info->uid = p->pw_uid;
2069 info->primary_gid = p->pw_gid;
2070 info->username = _dbus_strdup (p->pw_name);
2071 info->homedir = _dbus_strdup (p->pw_dir);
2072
2073 if (info->username == NULL ||
2074 info->homedir == NULL)
2075 {
2076 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2077 return FALSE;
2078 }
2079
2080 return TRUE;
2081 }
2082
2083 static dbus_bool_t
2084 fill_user_info (DBusUserInfo *info,
2085 dbus_uid_t uid,
2086 const DBusString *username,
2087 DBusError *error)
2088 {
2089 const char *username_c;
2090
2091 /* exactly one of username/uid provided */
2092 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2093 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2094
2095 info->uid = DBUS_UID_UNSET;
2096 info->primary_gid = DBUS_GID_UNSET;
2097 info->group_ids = NULL;
2098 info->n_group_ids = 0;
2099 info->username = NULL;
2100 info->homedir = NULL;
2101
2102 if (username != NULL)
2103 username_c = _dbus_string_get_const_data (username);
2104 else
2105 username_c = NULL;
2106
2107 /* For now assuming that the getpwnam() and getpwuid() flavors
2108 * are always symmetrical, if not we have to add more configure
2109 * checks
2110 */
2111
2112 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2113 {
2114 struct passwd *p;
2115 int result;
2116 size_t buflen;
2117 char *buf;
2118 struct passwd p_str;
2119
2120 /* retrieve maximum needed size for buf */
2121 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2122
2123 /* sysconf actually returns a long, but everything else expects size_t,
2124 * so just recast here.
2125 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2126 */
2127 if ((long) buflen <= 0)
2128 buflen = 1024;
2129
2130 result = -1;
2131 while (1)
2132 {
2133 buf = dbus_malloc (buflen);
2134 if (buf == NULL)
2135 {
2136 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2137 return FALSE;
2138 }
2139
2140 p = NULL;
2141 #ifdef HAVE_POSIX_GETPWNAM_R
2142 if (uid != DBUS_UID_UNSET)
2143 result = getpwuid_r (uid, &p_str, buf, buflen,
2144 &p);
2145 else
2146 result = getpwnam_r (username_c, &p_str, buf, buflen,
2147 &p);
2148 #else
2149 if (uid != DBUS_UID_UNSET)
2150 p = getpwuid_r (uid, &p_str, buf, buflen);
2151 else
2152 p = getpwnam_r (username_c, &p_str, buf, buflen);
2153 result = 0;
2154 #endif /* !HAVE_POSIX_GETPWNAM_R */
2155 //Try a bigger buffer if ERANGE was returned
2156 if (result == ERANGE && buflen < 512 * 1024)
2157 {
2158 dbus_free (buf);
2159 buflen *= 2;
2160 }
2161 else
2162 {
2163 break;
2164 }
2165 }
2166 if (result == 0 && p == &p_str)
2167 {
2168 if (!fill_user_info_from_passwd (p, info, error))
2169 {
2170 dbus_free (buf);
2171 return FALSE;
2172 }
2173 dbus_free (buf);
2174 }
2175 else
2176 {
2177 dbus_set_error (error, _dbus_error_from_errno (errno),
2178 "User \"%s\" unknown or no memory to allocate password entry\n",
2179 username_c ? username_c : "???");
2180 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2181 dbus_free (buf);
2182 return FALSE;
2183 }
2184 }
2185 #else /* ! HAVE_GETPWNAM_R */
2186 {
2187 /* I guess we're screwed on thread safety here */
2188 struct passwd *p;
2189
2190 if (uid != DBUS_UID_UNSET)
2191 p = getpwuid (uid);
2192 else
2193 p = getpwnam (username_c);
2194
2195 if (p != NULL)
2196 {
2197 if (!fill_user_info_from_passwd (p, info, error))
2198 {
2199 return FALSE;
2200 }
2201 }
2202 else
2203 {
2204 dbus_set_error (error, _dbus_error_from_errno (errno),
2205 "User \"%s\" unknown or no memory to allocate password entry\n",
2206 username_c ? username_c : "???");
2207 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2208 return FALSE;
2209 }
2210 }
2211 #endif /* ! HAVE_GETPWNAM_R */
2212
2213 /* Fill this in so we can use it to get groups */
2214 username_c = info->username;
2215
2216 #ifdef HAVE_GETGROUPLIST
2217 {
2218 gid_t *buf;
2219 int buf_count;
2220 int i;
2221 int initial_buf_count;
2222
2223 initial_buf_count = 17;
2224 buf_count = initial_buf_count;
2225 buf = dbus_new (gid_t, buf_count);
2226 if (buf == NULL)
2227 {
2228 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2229 goto failed;
2230 }
2231
2232 if (getgrouplist (username_c,
2233 info->primary_gid,
2234 buf, &buf_count) < 0)
2235 {
2236 gid_t *new;
2237 /* Presumed cause of negative return code: buf has insufficient
2238 entries to hold the entire group list. The Linux behavior in this
2239 case is to pass back the actual number of groups in buf_count, but
2240 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2241 So as a hack, try to help out a bit by guessing a larger
2242 number of groups, within reason.. might still fail, of course,
2243 but we can at least print a more informative message. I looked up
2244 the "right way" to do this by downloading Apple's own source code
2245 for the "id" command, and it turns out that they use an
2246 undocumented library function getgrouplist_2 (!) which is not
2247 declared in any header in /usr/include (!!). That did not seem
2248 like the way to go here.
2249 */
2250 if (buf_count == initial_buf_count)
2251 {
2252 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2253 }
2254 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2255 if (new == NULL)
2256 {
2257 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2258 dbus_free (buf);
2259 goto failed;
2260 }
2261
2262 buf = new;
2263
2264 errno = 0;
2265 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2266 {
2267 if (errno == 0)
2268 {
2269 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2270 username_c, buf_count, buf_count);
2271 }
2272 else
2273 {
2274 dbus_set_error (error,
2275 _dbus_error_from_errno (errno),
2276 "Failed to get groups for username \"%s\" primary GID "
2277 DBUS_GID_FORMAT ": %s\n",
2278 username_c, info->primary_gid,
2279 _dbus_strerror (errno));
2280 dbus_free (buf);
2281 goto failed;
2282 }
2283 }
2284 }
2285
2286 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2287 if (info->group_ids == NULL)
2288 {
2289 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2290 dbus_free (buf);
2291 goto failed;
2292 }
2293
2294 for (i = 0; i < buf_count; ++i)
2295 info->group_ids[i] = buf[i];
2296
2297 info->n_group_ids = buf_count;
2298
2299 dbus_free (buf);
2300 }
2301 #else /* HAVE_GETGROUPLIST */
2302 {
2303 /* We just get the one group ID */
2304 info->group_ids = dbus_new (dbus_gid_t, 1);
2305 if (info->group_ids == NULL)
2306 {
2307 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2308 goto failed;
2309 }
2310
2311 info->n_group_ids = 1;
2312
2313 (info->group_ids)[0] = info->primary_gid;
2314 }
2315 #endif /* HAVE_GETGROUPLIST */
2316
2317 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2318
2319 return TRUE;
2320
2321 failed:
2322 _DBUS_ASSERT_ERROR_IS_SET (error);
2323 return FALSE;
2324 }
2325
2334 dbus_bool_t
2335 _dbus_user_info_fill (DBusUserInfo *info,
2336 const DBusString *username,
2337 DBusError *error)
2338 {
2339 return fill_user_info (info, DBUS_UID_UNSET,
2340 username, error);
2341 }
2342
2351 dbus_bool_t
2352 _dbus_user_info_fill_uid (DBusUserInfo *info,
2353 dbus_uid_t uid,
2354 DBusError *error)
2355 {
2356 return fill_user_info (info, uid,
2357 NULL, error);
2358 }
2359
2367 dbus_bool_t
2368 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2369 {
2370 /* The POSIX spec certainly doesn't promise this, but
2371 * we need these assertions to fail as soon as we're wrong about
2372 * it so we can do the porting fixups
2373 */
2374 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
2375 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
2376 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
2377
2378 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2379 return FALSE;
2380 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2381 return FALSE;
2382
2383 return TRUE;
2384 }
2385
2397 dbus_bool_t
2398 _dbus_append_user_from_current_process (DBusString *str)
2399 {
2400 return _dbus_string_append_uint (str,
2401 _dbus_geteuid ());
2402 }
2403
2408 dbus_pid_t
2409 _dbus_getpid (void)
2410 {
2411 return getpid ();
2412 }
2413
2417 dbus_uid_t
2418 _dbus_getuid (void)
2419 {
2420 return getuid ();
2421 }
2422
2426 dbus_uid_t
2427 _dbus_geteuid (void)
2428 {
2429 return geteuid ();
2430 }
2431
2438 unsigned long
2439 _dbus_pid_for_log (void)
2440 {
2441 return getpid ();
2442 }
2443
2451 dbus_bool_t
2452 _dbus_parse_uid (const DBusString *uid_str,
2453 dbus_uid_t *uid)
2454 {
2455 int end;
2456 long val;
2457
2458 if (_dbus_string_get_length (uid_str) == 0)
2459 {
2460 _dbus_verbose ("UID string was zero length\n");
2461 return FALSE;
2462 }
2463
2464 val = -1;
2465 end = 0;
2466 if (!_dbus_string_parse_int (uid_str, 0, &val,
2467 &end))
2468 {
2469 _dbus_verbose ("could not parse string as a UID\n");
2470 return FALSE;
2471 }
2472
2473 if (end != _dbus_string_get_length (uid_str))
2474 {
2475 _dbus_verbose ("string contained trailing stuff after UID\n");
2476 return FALSE;
2477 }
2478
2479 *uid = val;
2480
2481 return TRUE;
2482 }
2483
2484 #if !DBUS_USE_SYNC
2485 /* To be thread-safe by default on platforms that don't necessarily have
2486 * atomic operations (notably Debian armel, which is armv4t), we must
2487 * use a mutex that can be initialized statically, like this.
2488 * GLib >= 2.32 uses a similar system.
2489 */
2490 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2491 #endif
2492
2499 dbus_int32_t
2500 _dbus_atomic_inc (DBusAtomic *atomic)
2501 {
2502 #if DBUS_USE_SYNC
2503 return __sync_add_and_fetch(&atomic->value, 1)-1;
2504 #else
2505 dbus_int32_t res;
2506
2507 pthread_mutex_lock (&atomic_mutex);
2508 res = atomic->value;
2509 atomic->value += 1;
2510 pthread_mutex_unlock (&atomic_mutex);
2511
2512 return res;
2513 #endif
2514 }
2515
2522 dbus_int32_t
2523 _dbus_atomic_dec (DBusAtomic *atomic)
2524 {
2525 #if DBUS_USE_SYNC
2526 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2527 #else
2528 dbus_int32_t res;
2529
2530 pthread_mutex_lock (&atomic_mutex);
2531 res = atomic->value;
2532 atomic->value -= 1;
2533 pthread_mutex_unlock (&atomic_mutex);
2534
2535 return res;
2536 #endif
2537 }
2538
2546 dbus_int32_t
2547 _dbus_atomic_get (DBusAtomic *atomic)
2548 {
2549 #if DBUS_USE_SYNC
2550 __sync_synchronize ();
2551 return atomic->value;
2552 #else
2553 dbus_int32_t res;
2554
2555 pthread_mutex_lock (&atomic_mutex);
2556 res = atomic->value;
2557 pthread_mutex_unlock (&atomic_mutex);
2558
2559 return res;
2560 #endif
2561 }
2562
2571 int
2572 _dbus_poll (DBusPollFD *fds,
2573 int n_fds,
2574 int timeout_milliseconds)
2575 {
2576 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2577 /* This big thing is a constant expression and should get optimized
2578 * out of existence. So it's more robust than a configure check at
2579 * no cost.
2580 */
2581 if (_DBUS_POLLIN == POLLIN &&
2582 _DBUS_POLLPRI == POLLPRI &&
2583 _DBUS_POLLOUT == POLLOUT &&
2584 _DBUS_POLLERR == POLLERR &&
2585 _DBUS_POLLHUP == POLLHUP &&
2586 _DBUS_POLLNVAL == POLLNVAL &&
2587 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
2588 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
2589 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
2590 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
2591 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
2592 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
2593 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
2594 {
2595 return poll ((struct pollfd*) fds,
2596 n_fds,
2597 timeout_milliseconds);
2598 }
2599 else
2600 {
2601 /* We have to convert the DBusPollFD to an array of
2602 * struct pollfd, poll, and convert back.
2603 */
2604 _dbus_warn ("didn't implement poll() properly for this system yet\n");
2605 return -1;
2606 }
2607 #else /* ! HAVE_POLL */
2608
2609 fd_set read_set, write_set, err_set;
2610 int max_fd = 0;
2611 int i;
2612 struct timeval tv;
2613 int ready;
2614
2615 FD_ZERO (&read_set);
2616 FD_ZERO (&write_set);
2617 FD_ZERO (&err_set);
2618
2619 for (i = 0; i < n_fds; i++)
2620 {
2621 DBusPollFD *fdp = &fds[i];
2622
2623 if (fdp->events & _DBUS_POLLIN)
2624 FD_SET (fdp->fd, &read_set);
2625
2626 if (fdp->events & _DBUS_POLLOUT)
2627 FD_SET (fdp->fd, &write_set);
2628
2629 FD_SET (fdp->fd, &err_set);
2630
2631 max_fd = MAX (max_fd, fdp->fd);
2632 }
2633
2634 tv.tv_sec = timeout_milliseconds / 1000;
2635 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2636
2637 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2638 timeout_milliseconds < 0 ? NULL : &tv);
2639
2640 if (ready > 0)
2641 {
2642 for (i = 0; i < n_fds; i++)
2643 {
2644 DBusPollFD *fdp = &fds[i];
2645
2646 fdp->revents = 0;
2647
2648 if (FD_ISSET (fdp->fd, &read_set))
2649 fdp->revents |= _DBUS_POLLIN;
2650
2651 if (FD_ISSET (fdp->fd, &write_set))
2652 fdp->revents |= _DBUS_POLLOUT;
2653
2654 if (FD_ISSET (fdp->fd, &err_set))
2655 fdp->revents |= _DBUS_POLLERR;
2656 }
2657 }
2658
2659 return ready;
2660 #endif
2661 }
2662
2670 void
2671 _dbus_get_monotonic_time (long *tv_sec,
2672 long *tv_usec)
2673 {
2674 #ifdef HAVE_MONOTONIC_CLOCK
2675 struct timespec ts;
2676 clock_gettime (CLOCK_MONOTONIC, &ts);
2677
2678 if (tv_sec)
2679 *tv_sec = ts.tv_sec;
2680 if (tv_usec)
2681 *tv_usec = ts.tv_nsec / 1000;
2682 #else
2683 struct timeval t;
2684
2685 gettimeofday (&t, NULL);
2686
2687 if (tv_sec)
2688 *tv_sec = t.tv_sec;
2689 if (tv_usec)
2690 *tv_usec = t.tv_usec;
2691 #endif
2692 }
2693
2701 void
2702 _dbus_get_real_time (long *tv_sec,
2703 long *tv_usec)
2704 {
2705 struct timeval t;
2706
2707 gettimeofday (&t, NULL);
2708
2709 if (tv_sec)
2710 *tv_sec = t.tv_sec;
2711 if (tv_usec)
2712 *tv_usec = t.tv_usec;
2713 }
2714
2723 dbus_bool_t
2724 _dbus_create_directory (const DBusString *filename,
2725 DBusError *error)
2726 {
2727 const char *filename_c;
2728
2729 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2730
2731 filename_c = _dbus_string_get_const_data (filename);
2732
2733 if (mkdir (filename_c, 0700) < 0)
2734 {
2735 if (errno == EEXIST)
2736 return TRUE;
2737
2738 dbus_set_error (error, DBUS_ERROR_FAILED,
2739 "Failed to create directory %s: %s\n",
2740 filename_c, _dbus_strerror (errno));
2741 return FALSE;
2742 }
2743 else
2744 return TRUE;
2745 }
2746
2757 dbus_bool_t
2758 _dbus_concat_dir_and_file (DBusString *dir,
2759 const DBusString *next_component)
2760 {
2761 dbus_bool_t dir_ends_in_slash;
2762 dbus_bool_t file_starts_with_slash;
2763
2764 if (_dbus_string_get_length (dir) == 0 ||
2765 _dbus_string_get_length (next_component) == 0)
2766 return TRUE;
2767
2768 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
2769 _dbus_string_get_length (dir) - 1);
2770
2771 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
2772
2773 if (dir_ends_in_slash && file_starts_with_slash)
2774 {
2775 _dbus_string_shorten (dir, 1);
2776 }
2777 else if (!(dir_ends_in_slash || file_starts_with_slash))
2778 {
2779 if (!_dbus_string_append_byte (dir, '/'))
2780 return FALSE;
2781 }
2782
2783 return _dbus_string_copy (next_component, 0, dir,
2784 _dbus_string_get_length (dir));
2785 }
2786
2788 #define NANOSECONDS_PER_SECOND 1000000000
2789
2790 #define MICROSECONDS_PER_SECOND 1000000
2791
2792 #define MILLISECONDS_PER_SECOND 1000
2793
2794 #define NANOSECONDS_PER_MILLISECOND 1000000
2795
2796 #define MICROSECONDS_PER_MILLISECOND 1000
2797
2802 void
2803 _dbus_sleep_milliseconds (int milliseconds)
2804 {
2805 #ifdef HAVE_NANOSLEEP
2806 struct timespec req;
2807 struct timespec rem;
2808
2809 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
2810 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
2811 rem.tv_sec = 0;
2812 rem.tv_nsec = 0;
2813
2814 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
2815 req = rem;
2816 #elif defined (HAVE_USLEEP)
2817 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
2818 #else /* ! HAVE_USLEEP */
2819 sleep (MAX (milliseconds / 1000, 1));
2820 #endif
2821 }
2822
2823 static dbus_bool_t
2824 _dbus_generate_pseudorandom_bytes (DBusString *str,
2825 int n_bytes)
2826 {
2827 int old_len;
2828 char *p;
2829
2830 old_len = _dbus_string_get_length (str);
2831
2832 if (!_dbus_string_lengthen (str, n_bytes))
2833 return FALSE;
2834
2835 p = _dbus_string_get_data_len (str, old_len, n_bytes);
2836
2837 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
2838
2839 return TRUE;
2840 }
2841
2850 dbus_bool_t
2851 _dbus_generate_random_bytes (DBusString *str,
2852 int n_bytes)
2853 {
2854 int old_len;
2855 int fd;
2856
2857 /* FALSE return means "no memory", if it could
2858 * mean something else then we'd need to return
2859 * a DBusError. So we always fall back to pseudorandom
2860 * if the I/O fails.
2861 */
2862
2863 old_len = _dbus_string_get_length (str);
2864 fd = -1;
2865
2866 /* note, urandom on linux will fall back to pseudorandom */
2867 fd = open ("/dev/urandom", O_RDONLY);
2868 if (fd < 0)
2869 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2870
2871 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
2872
2873 if (_dbus_read (fd, str, n_bytes) != n_bytes)
2874 {
2875 _dbus_close (fd, NULL);
2876 _dbus_string_set_length (str, old_len);
2877 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2878 }
2879
2880 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2881 n_bytes);
2882
2883 _dbus_close (fd, NULL);
2884
2885 return TRUE;
2886 }
2887
2893 void
2894 _dbus_exit (int code)
2895 {
2896 _exit (code);
2897 }
2898
2907 const char*
2908 _dbus_strerror (int error_number)
2909 {
2910 const char *msg;
2911
2912 msg = strerror (error_number);
2913 if (msg == NULL)
2914 msg = "unknown";
2915
2916 return msg;
2917 }
2918
2922 void
2923 _dbus_disable_sigpipe (void)
2924 {
2925 signal (SIGPIPE, SIG_IGN);
2926 }
2927
2935 void
2936 _dbus_fd_set_close_on_exec (intptr_t fd)
2937 {
2938 int val;
2939
2940 val = fcntl (fd, F_GETFD, 0);
2941
2942 if (val < 0)
2943 return;
2944
2945 val |= FD_CLOEXEC;
2946
2947 fcntl (fd, F_SETFD, val);
2948 }
2949
2957 dbus_bool_t
2958 _dbus_close (int fd,
2959 DBusError *error)
2960 {
2961 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2962
2963 again:
2964 if (close (fd) < 0)
2965 {
2966 if (errno == EINTR)
2967 goto again;
2968
2969 dbus_set_error (error, _dbus_error_from_errno (errno),
2970 "Could not close fd %d", fd);
2971 return FALSE;
2972 }
2973
2974 return TRUE;
2975 }
2976
2985 int
2986 _dbus_dup(int fd,
2987 DBusError *error)
2988 {
2989 int new_fd;
2990
2991 #ifdef F_DUPFD_CLOEXEC
2992 dbus_bool_t cloexec_done;
2993
2994 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2995 cloexec_done = new_fd >= 0;
2996
2997 if (new_fd < 0 && errno == EINVAL)
2998 #endif
2999 {
3000 new_fd = fcntl(fd, F_DUPFD, 3);
3001 }
3002
3003 if (new_fd < 0) {
3004
3005 dbus_set_error (error, _dbus_error_from_errno (errno),
3006 "Could not duplicate fd %d", fd);
3007 return -1;
3008 }
3009
3010 #ifdef F_DUPFD_CLOEXEC
3011 if (!cloexec_done)
3012 #endif
3013 {
3014 _dbus_fd_set_close_on_exec(new_fd);
3015 }
3016
3017 return new_fd;
3018 }
3019
3027 dbus_bool_t
3028 _dbus_set_fd_nonblocking (int fd,
3029 DBusError *error)
3030 {
3031 int val;
3032
3033 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3034
3035 val = fcntl (fd, F_GETFL, 0);
3036 if (val < 0)
3037 {
3038 dbus_set_error (error, _dbus_error_from_errno (errno),
3039 "Failed to get flags from file descriptor %d: %s",
3040 fd, _dbus_strerror (errno));
3041 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3042 _dbus_strerror (errno));
3043 return FALSE;
3044 }
3045
3046 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3047 {
3048 dbus_set_error (error, _dbus_error_from_errno (errno),
3049 "Failed to set nonblocking flag of file descriptor %d: %s",
3050 fd, _dbus_strerror (errno));
3051 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3052 fd, _dbus_strerror (errno));
3053
3054 return FALSE;
3055 }
3056
3057 return TRUE;
3058 }
3059
3065 void
3066 _dbus_print_backtrace (void)
3067 {
3068 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3069 void *bt[500];
3070 int bt_size;
3071 int i;
3072 char **syms;
3073
3074 bt_size = backtrace (bt, 500);
3075
3076 syms = backtrace_symbols (bt, bt_size);
3077
3078 i = 0;
3079 while (i < bt_size)
3080 {
3081 /* don't use dbus_warn since it can _dbus_abort() */
3082 fprintf (stderr, " %s\n", syms[i]);
3083 ++i;
3084 }
3085 fflush (stderr);
3086
3087 free (syms);
3088 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3089 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3090 #else
3091 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3092 #endif
3093 }
3094
3107 dbus_bool_t
3108 _dbus_full_duplex_pipe (int *fd1,
3109 int *fd2,
3110 dbus_bool_t blocking,
3111 DBusError *error)
3112 {
3113 #ifdef HAVE_SOCKETPAIR
3114 int fds[2];
3115 int retval;
3116
3117 #ifdef SOCK_CLOEXEC
3118 dbus_bool_t cloexec_done;
3119
3120 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3121 cloexec_done = retval >= 0;
3122
3123 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3124 #endif
3125 {
3126 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3127 }
3128
3129 if (retval < 0)
3130 {
3131 dbus_set_error (error, _dbus_error_from_errno (errno),
3132 "Could not create full-duplex pipe");
3133 return FALSE;
3134 }
3135
3136 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3137
3138 #ifdef SOCK_CLOEXEC
3139 if (!cloexec_done)
3140 #endif
3141 {
3142 _dbus_fd_set_close_on_exec (fds[0]);
3143 _dbus_fd_set_close_on_exec (fds[1]);
3144 }
3145
3146 if (!blocking &&
3147 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3148 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3149 {
3150 dbus_set_error (error, _dbus_error_from_errno (errno),
3151 "Could not set full-duplex pipe nonblocking");
3152
3153 _dbus_close (fds[0], NULL);
3154 _dbus_close (fds[1], NULL);
3155
3156 return FALSE;
3157 }
3158
3159 *fd1 = fds[0];
3160 *fd2 = fds[1];
3161
3162 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3163 *fd1, *fd2);
3164
3165 return TRUE;
3166 #else
3167 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
3168 dbus_set_error (error, DBUS_ERROR_FAILED,
3169 "_dbus_full_duplex_pipe() not implemented on this OS");
3170 return FALSE;
3171 #endif
3172 }
3173
3182 int
3183 _dbus_printf_string_upper_bound (const char *format,
3184 va_list args)
3185 {
3186 char static_buf[1024];
3187 int bufsize = sizeof (static_buf);
3188 int len;
3189 va_list args_copy;
3190
3191 DBUS_VA_COPY (args_copy, args);
3192 len = vsnprintf (static_buf, bufsize, format, args_copy);
3193 va_end (args_copy);
3194
3195 /* If vsnprintf() returned non-negative, then either the string fits in
3196 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3197 * returns the number of characters that were needed, or this OS returns the
3198 * truncated length.
3199 *
3200 * We ignore the possibility that snprintf might just ignore the length and
3201 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3202 * If your libc is really that bad, come back when you have a better one. */
3203 if (len == bufsize)
3204 {
3205 /* This could be the truncated length (Tru64 and IRIX have this bug),
3206 * or the real length could be coincidentally the same. Which is it?
3207 * If vsnprintf returns the truncated length, we'll go to the slow
3208 * path. */
3209 DBUS_VA_COPY (args_copy, args);
3210
3211 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3212 len = -1;
3213
3214 va_end (args_copy);
3215 }
3216
3217 /* If vsnprintf() returned negative, we have to do more work.
3218 * HP-UX returns negative. */
3219 while (len < 0)
3220 {
3221 char *buf;
3222
3223 bufsize *= 2;
3224
3225 buf = dbus_malloc (bufsize);
3226
3227 if (buf == NULL)
3228 return -1;
3229
3230 DBUS_VA_COPY (args_copy, args);
3231 len = vsnprintf (buf, bufsize, format, args_copy);
3232 va_end (args_copy);
3233
3234 dbus_free (buf);
3235
3236 /* If the reported length is exactly the buffer size, round up to the
3237 * next size, in case vsnprintf has been returning the truncated
3238 * length */
3239 if (len == bufsize)
3240 len = -1;
3241 }
3242
3243 return len;
3244 }
3245
3252 const char*
3253 _dbus_get_tmpdir(void)
3254 {
3255 /* Protected by _DBUS_LOCK_sysdeps */
3256 static const char* tmpdir = NULL;
3257
3258 if (!_DBUS_LOCK (sysdeps))
3259 return NULL;
3260
3261 if (tmpdir == NULL)
3262 {
3263 /* TMPDIR is what glibc uses, then
3264 * glibc falls back to the P_tmpdir macro which
3265 * just expands to "/tmp"
3266 */
3267 if (tmpdir == NULL)
3268 tmpdir = getenv("TMPDIR");
3269
3270 /* These two env variables are probably
3271 * broken, but maybe some OS uses them?
3272 */
3273 if (tmpdir == NULL)
3274 tmpdir = getenv("TMP");
3275 if (tmpdir == NULL)
3276 tmpdir = getenv("TEMP");
3277
3278 /* And this is the sane fallback. */
3279 if (tmpdir == NULL)
3280 tmpdir = "/tmp";
3281 }
3282
3283 _DBUS_UNLOCK (sysdeps);
3284
3285 _dbus_assert(tmpdir != NULL);
3286
3287 return tmpdir;
3288 }
3289
3290 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3291
3310 static dbus_bool_t
3311 _read_subprocess_line_argv (const char *progpath,
3312 dbus_bool_t path_fallback,
3313 char * const *argv,
3314 DBusString *result,
3315 DBusError *error)
3316 {
3317 int result_pipe[2] = { -1, -1 };
3318 int errors_pipe[2] = { -1, -1 };
3319 pid_t pid;
3320 int ret;
3321 int status;
3322 int orig_len;
3323
3324 dbus_bool_t retval;
3325 sigset_t new_set, old_set;
3326
3327 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3328 retval = FALSE;
3329
3330 /* We need to block any existing handlers for SIGCHLD temporarily; they
3331 * will cause waitpid() below to fail.
3332 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3333 */
3334 sigemptyset (&new_set);
3335 sigaddset (&new_set, SIGCHLD);
3336 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3337
3338 orig_len = _dbus_string_get_length (result);
3339
3340 #define READ_END 0
3341 #define WRITE_END 1
3342 if (pipe (result_pipe) < 0)
3343 {
3344 dbus_set_error (error, _dbus_error_from_errno (errno),
3345 "Failed to create a pipe to call %s: %s",
3346 progpath, _dbus_strerror (errno));
3347 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3348 progpath, _dbus_strerror (errno));
3349 goto out;
3350 }
3351 if (pipe (errors_pipe) < 0)
3352 {
3353 dbus_set_error (error, _dbus_error_from_errno (errno),
3354 "Failed to create a pipe to call %s: %s",
3355 progpath, _dbus_strerror (errno));
3356 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3357 progpath, _dbus_strerror (errno));
3358 goto out;
3359 }
3360
3361 pid = fork ();
3362 if (pid < 0)
3363 {
3364 dbus_set_error (error, _dbus_error_from_errno (errno),
3365 "Failed to fork() to call %s: %s",
3366 progpath, _dbus_strerror (errno));
3367 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3368 progpath, _dbus_strerror (errno));
3369 goto out;
3370 }
3371
3372 if (pid == 0)
3373 {
3374 /* child process */
3375 int fd;
3376
3377 fd = open ("/dev/null", O_RDWR);
3378 if (fd == -1)
3379 /* huh?! can't open /dev/null? */
3380 _exit (1);
3381
3382 _dbus_verbose ("/dev/null fd %d opened\n", fd);
3383
3384 /* set-up stdXXX */
3385 close (result_pipe[READ_END]);
3386 close (errors_pipe[READ_END]);
3387
3388 if (dup2 (fd, 0) == -1) /* setup stdin */
3389 _exit (1);
3390 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3391 _exit (1);
3392 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3393 _exit (1);
3394
3395 _dbus_close_all ();
3396
3397 sigprocmask (SIG_SETMASK, &old_set, NULL);
3398
3399 /* If it looks fully-qualified, try execv first */
3400 if (progpath[0] == '/')
3401 {
3402 execv (progpath, argv);
3403 /* Ok, that failed. Now if path_fallback is given, let's
3404 * try unqualified. This is mostly a hack to work
3405 * around systems which ship dbus-launch in /usr/bin
3406 * but everything else in /bin (because dbus-launch
3407 * depends on X11).
3408 */
3409 if (path_fallback)
3410 /* We must have a slash, because we checked above */
3411 execvp (strrchr (progpath, '/')+1, argv);
3412 }
3413 else
3414 execvp (progpath, argv);
3415
3416 /* still nothing, we failed */
3417 _exit (1);
3418 }
3419
3420 /* parent process */
3421 close (result_pipe[WRITE_END]);
3422 close (errors_pipe[WRITE_END]);
3423 result_pipe[WRITE_END] = -1;
3424 errors_pipe[WRITE_END] = -1;
3425
3426 ret = 0;
3427 do
3428 {
3429 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3430 }
3431 while (ret > 0);
3432
3433 /* reap the child process to avoid it lingering as zombie */
3434 do
3435 {
3436 ret = waitpid (pid, &status, 0);
3437 }
3438 while (ret == -1 && errno == EINTR);
3439
3440 /* We succeeded if the process exited with status 0 and
3441 anything was read */
3442 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3443 {
3444 /* The process ended with error */
3445 DBusString error_message;
3446 if (!_dbus_string_init (&error_message))
3447 {
3448 _DBUS_SET_OOM (error);
3449 goto out;
3450 }
3451
3452 ret = 0;
3453 do
3454 {
3455 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3456 }
3457 while (ret > 0);
3458
3459 _dbus_string_set_length (result, orig_len);
3460 if (_dbus_string_get_length (&error_message) > 0)
3461 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3462 "%s terminated abnormally with the following error: %s",
3463 progpath, _dbus_string_get_data (&error_message));
3464 else
3465 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3466 "%s terminated abnormally without any error message",
3467 progpath);
3468 goto out;
3469 }
3470
3471 retval = TRUE;
3472
3473 out:
3474 sigprocmask (SIG_SETMASK, &old_set, NULL);
3475
3476 if (retval)
3477 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3478 else
3479 _DBUS_ASSERT_ERROR_IS_SET (error);
3480
3481 if (result_pipe[0] != -1)
3482 close (result_pipe[0]);
3483 if (result_pipe[1] != -1)
3484 close (result_pipe[1]);
3485 if (errors_pipe[0] != -1)
3486 close (errors_pipe[0]);
3487 if (errors_pipe[1] != -1)
3488 close (errors_pipe[1]);
3489
3490 return retval;
3491 }
3492 #endif
3493
3506 dbus_bool_t
3507 _dbus_get_autolaunch_address (const char *scope,
3508 DBusString *address,
3509 DBusError *error)
3510 {
3511 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3512 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3513 * but that's done elsewhere, and if it worked, this function wouldn't
3514 * be called.) */
3515 const char *display;
3516 char *argv[6];
3517 int i;
3518 DBusString uuid;
3519 dbus_bool_t retval;
3520
3521 if (_dbus_check_setuid ())
3522 {
3523 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3524 "Unable to autolaunch when setuid");
3525 return FALSE;
3526 }
3527
3528 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3529 retval = FALSE;
3530
3531 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3532 * dbus-launch-x11 is just going to fail. Rather than trying to
3533 * run it, we might as well bail out early with a nice error. */
3534 display = _dbus_getenv ("DISPLAY");
3535
3536 if (display == NULL || display[0] == '\0')
3537 {
3538 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3539 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3540 return FALSE;
3541 }
3542
3543 if (!_dbus_string_init (&uuid))
3544 {
3545 _DBUS_SET_OOM (error);
3546 return FALSE;
3547 }
3548
3549 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
3550 {
3551 _DBUS_SET_OOM (error);
3552 goto out;
3553 }
3554
3555 i = 0;
3556 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3557 if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL)
3558 argv[i] = TEST_BUS_LAUNCH_BINARY;
3559 else
3560 #endif
3561 argv[i] = DBUS_BINDIR "/dbus-launch";
3562 ++i;
3563 argv[i] = "--autolaunch";
3564 ++i;
3565 argv[i] = _dbus_string_get_data (&uuid);
3566 ++i;
3567 argv[i] = "--binary-syntax";
3568 ++i;
3569 argv[i] = "--close-stderr";
3570 ++i;
3571 argv[i] = NULL;
3572 ++i;
3573
3574 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3575
3576 retval = _read_subprocess_line_argv (argv[0],
3577 TRUE,
3578 argv, address, error);
3579
3580 out:
3581 _dbus_string_free (&uuid);
3582 return retval;
3583 #else
3584 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3585 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3586 "set your DBUS_SESSION_BUS_ADDRESS instead");
3587 return FALSE;
3588 #endif
3589 }
3590
3609 dbus_bool_t
3610 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3611 dbus_bool_t create_if_not_found,
3612 DBusError *error)
3613 {
3614 DBusString filename;
3615 dbus_bool_t b;
3616
3617 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3618
3619 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3620 if (b)
3621 return TRUE;
3622
3623 dbus_error_free (error);
3624
3625 /* Fallback to the system machine ID */
3626 _dbus_string_init_const (&filename, "/etc/machine-id");
3627 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3628
3629 if (b)
3630 {
3631 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3632 * complain if that isn't possible for whatever reason */
3633 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3634 _dbus_write_uuid_file (&filename, machine_id, NULL);
3635
3636 return TRUE;
3637 }
3638
3639 if (!create_if_not_found)
3640 return FALSE;
3641
3642 /* if none found, try to make a new one */
3643 dbus_error_free (error);
3644 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3645 _dbus_generate_uuid (machine_id);
3646 return _dbus_write_uuid_file (&filename, machine_id, error);
3647 }
3648
3656 dbus_bool_t
3657 _dbus_lookup_launchd_socket (DBusString *socket_path,
3658 const char *launchd_env_var,
3659 DBusError *error)
3660 {
3661 #ifdef DBUS_ENABLE_LAUNCHD
3662 char *argv[4];
3663 int i;
3664
3665 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3666
3667 if (_dbus_check_setuid ())
3668 {
3669 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3670 "Unable to find launchd socket when setuid");
3671 return FALSE;
3672 }
3673
3674 i = 0;
3675 argv[i] = "launchctl";
3676 ++i;
3677 argv[i] = "getenv";
3678 ++i;
3679 argv[i] = (char*)launchd_env_var;
3680 ++i;
3681 argv[i] = NULL;
3682 ++i;
3683
3684 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3685
3686 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
3687 {
3688 return FALSE;
3689 }
3690
3691 /* no error, but no result either */
3692 if (_dbus_string_get_length(socket_path) == 0)
3693 {
3694 return FALSE;
3695 }
3696
3697 /* strip the carriage-return */
3698 _dbus_string_shorten(socket_path, 1);
3699 return TRUE;
3700 #else /* DBUS_ENABLE_LAUNCHD */
3701 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
3702 "can't lookup socket from launchd; launchd support not compiled in");
3703 return FALSE;
3704 #endif
3705 }
3706
3707 #ifdef DBUS_ENABLE_LAUNCHD
3708 static dbus_bool_t
3709 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
3710 {
3711 dbus_bool_t valid_socket;
3712 DBusString socket_path;
3713
3714 if (_dbus_check_setuid ())
3715 {
3716 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3717 "Unable to find launchd socket when setuid");
3718 return FALSE;
3719 }
3720
3721 if (!_dbus_string_init (&socket_path))
3722 {
3723 _DBUS_SET_OOM (error);
3724 return FALSE;
3725 }
3726
3727 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
3728
3729 if (dbus_error_is_set(error))
3730 {
3731 _dbus_string_free(&socket_path);
3732 return FALSE;
3733 }
3734
3735 if (!valid_socket)
3736 {
3737 dbus_set_error(error, "no socket path",
3738 "launchd did not provide a socket path, "
3739 "verify that org.freedesktop.dbus-session.plist is loaded!");
3740 _dbus_string_free(&socket_path);
3741 return FALSE;
3742 }
3743 if (!_dbus_string_append (address, "unix:path="))
3744 {
3745 _DBUS_SET_OOM (error);
3746 _dbus_string_free(&socket_path);
3747 return FALSE;
3748 }
3749 if (!_dbus_string_copy (&socket_path, 0, address,
3750 _dbus_string_get_length (address)))
3751 {
3752 _DBUS_SET_OOM (error);
3753 _dbus_string_free(&socket_path);
3754 return FALSE;
3755 }
3756
3757 _dbus_string_free(&socket_path);
3758 return TRUE;
3759 }
3760 #endif
3761
3781 dbus_bool_t
3782 _dbus_lookup_session_address (dbus_bool_t *supported,
3783 DBusString *address,
3784 DBusError *error)
3785 {
3786 #ifdef DBUS_ENABLE_LAUNCHD
3787 *supported = TRUE;
3788 return _dbus_lookup_session_address_launchd (address, error);
3789 #else
3790 /* On non-Mac Unix platforms, if the session address isn't already
3791 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
3792 * fall back to the autolaunch: global default; see
3793 * init_session_address in dbus/dbus-bus.c. */
3794 *supported = FALSE;
3795 return TRUE;
3796 #endif
3797 }
3798
3806 void
3807 _dbus_flush_caches (void)
3808 {
3809 _dbus_user_database_flush_system ();
3810 }
3811
3825 dbus_bool_t
3826 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
3827 DBusCredentials *credentials)
3828 {
3829 DBusString homedir;
3830 DBusString dotdir;
3831 dbus_uid_t uid;
3832
3833 _dbus_assert (credentials != NULL);
3834 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
3835
3836 if (!_dbus_string_init (&homedir))
3837 return FALSE;
3838
3839 uid = _dbus_credentials_get_unix_uid (credentials);
3840 _dbus_assert (uid != DBUS_UID_UNSET);
3841
3842 if (!_dbus_homedir_from_uid (uid, &homedir))
3843 goto failed;
3844
3845 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3846 {
3847 const char *override;
3848
3849 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
3850 if (override != NULL && *override != '\0')
3851 {
3852 _dbus_string_set_length (&homedir, 0);
3853 if (!_dbus_string_append (&homedir, override))
3854 goto failed;
3855
3856 _dbus_verbose ("Using fake homedir for testing: %s\n",
3857 _dbus_string_get_const_data (&homedir));
3858 }
3859 else
3860 {
3861 /* Not strictly thread-safe, but if we fail at thread-safety here,
3862 * the worst that will happen is some extra warnings. */
3863 static dbus_bool_t already_warned = FALSE;
3864 if (!already_warned)
3865 {
3866 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3867 already_warned = TRUE;
3868 }
3869 }
3870 }
3871 #endif
3872
3873 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
3874 if (!_dbus_concat_dir_and_file (&homedir,
3875 &dotdir))
3876 goto failed;
3877
3878 if (!_dbus_string_copy (&homedir, 0,
3879 directory, _dbus_string_get_length (directory))) {
3880 goto failed;
3881 }
3882
3883 _dbus_string_free (&homedir);
3884 return TRUE;
3885
3886 failed:
3887 _dbus_string_free (&homedir);
3888 return FALSE;
3889 }
3890
3891 //PENDING(kdab) docs
3892 dbus_bool_t
3893 _dbus_daemon_publish_session_bus_address (const char* addr,
3894 const char *scope)
3895 {
3896 return TRUE;
3897 }
3898
3899 //PENDING(kdab) docs
3900 void
3901 _dbus_daemon_unpublish_session_bus_address (void)
3902 {
3903
3904 }
3905
3912 dbus_bool_t
3913 _dbus_get_is_errno_eagain_or_ewouldblock (void)
3914 {
3915 return errno == EAGAIN || errno == EWOULDBLOCK;
3916 }
3917
3925 dbus_bool_t
3926 _dbus_delete_directory (const DBusString *filename,
3927 DBusError *error)
3928 {
3929 const char *filename_c;
3930
3931 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3932
3933 filename_c = _dbus_string_get_const_data (filename);
3934
3935 if (rmdir (filename_c) != 0)
3936 {
3937 dbus_set_error (error, DBUS_ERROR_FAILED,
3938 "Failed to remove directory %s: %s\n",
3939 filename_c, _dbus_strerror (errno));
3940 return FALSE;
3941 }
3942
3943 return TRUE;
3944 }
3945
3953 dbus_bool_t
3954 _dbus_socket_can_pass_unix_fd(int fd) {
3955
3956 #ifdef SCM_RIGHTS
3957 union {
3958 struct sockaddr sa;
3959 struct sockaddr_storage storage;
3960 struct sockaddr_un un;
3961 } sa_buf;
3962
3963 socklen_t sa_len = sizeof(sa_buf);
3964
3965 _DBUS_ZERO(sa_buf);
3966
3967 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
3968 return FALSE;
3969
3970 return sa_buf.sa.sa_family == AF_UNIX;
3971
3972 #else
3973 return FALSE;
3974
3975 #endif
3976 }
3977
3982 void
3983 _dbus_close_all (void)
3984 {
3985 int maxfds, i;
3986
3987 #ifdef __linux__
3988 DIR *d;
3989
3990 /* On Linux we can optimize this a bit if /proc is available. If it
3991 isn't available, fall back to the brute force way. */
3992
3993 d = opendir ("/proc/self/fd");
3994 if (d)
3995 {
3996 for (;;)
3997 {
3998 struct dirent buf, *de;
3999 int k, fd;
4000 long l;
4001 char *e = NULL;
4002
4003 k = readdir_r (d, &buf, &de);
4004 if (k != 0 || !de)
4005 break;
4006
4007 if (de->d_name[0] == '.')
4008 continue;
4009
4010 errno = 0;
4011 l = strtol (de->d_name, &e, 10);
4012 if (errno != 0 || e == NULL || *e != '\0')
4013 continue;
4014
4015 fd = (int) l;
4016 if (fd < 3)
4017 continue;
4018
4019 if (fd == dirfd (d))
4020 continue;
4021
4022 close (fd);
4023 }
4024
4025 closedir (d);
4026 return;
4027 }
4028 #endif
4029
4030 maxfds = sysconf (_SC_OPEN_MAX);
4031
4032 /* Pick something reasonable if for some reason sysconf says
4033 * unlimited.
4034 */
4035 if (maxfds < 0)
4036 maxfds = 1024;
4037
4038 /* close all inherited fds */
4039 for (i = 3; i < maxfds; i++)
4040 close (i);
4041 }
4042
4052 dbus_bool_t
4053 _dbus_check_setuid (void)
4054 {
4055 /* TODO: get __libc_enable_secure exported from glibc.
4056 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4057 */
4058 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4059 {
4060 /* See glibc/include/unistd.h */
4061 extern int __libc_enable_secure;
4062 return __libc_enable_secure;
4063 }
4064 #elif defined(HAVE_ISSETUGID)
4065 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4066 return issetugid ();
4067 #else
4068 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4069 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4070
4071 /* We call into this function from _dbus_threads_init_platform_specific()
4072 * to make sure these are initialized before we start threading. */
4073 static dbus_bool_t check_setuid_initialised;
4074 static dbus_bool_t is_setuid;
4075
4076 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4077 {
4078 #ifdef HAVE_GETRESUID
4079 if (getresuid (&ruid, &euid, &suid) != 0 ||
4080 getresgid (&rgid, &egid, &sgid) != 0)
4081 #endif /* HAVE_GETRESUID */
4082 {
4083 suid = ruid = getuid ();
4084 sgid = rgid = getgid ();
4085 euid = geteuid ();
4086 egid = getegid ();
4087 }
4088
4089 check_setuid_initialised = TRUE;
4090 is_setuid = (ruid != euid || ruid != suid ||
4091 rgid != egid || rgid != sgid);
4092
4093 }
4094 return is_setuid;
4095 #endif
4096 }
4097
4105 dbus_bool_t
4106 _dbus_append_address_from_socket (int fd,
4107 DBusString *address,
4108 DBusError *error)
4109 {
4110 union {
4111 struct sockaddr sa;
4112 struct sockaddr_storage storage;
4113 struct sockaddr_un un;
4114 struct sockaddr_in ipv4;
4115 struct sockaddr_in6 ipv6;
4116 } socket;
4117 char hostip[INET6_ADDRSTRLEN];
4118 int size = sizeof (socket);
4119 DBusString path_str;
4120
4121 if (getsockname (fd, &socket.sa, &size))
4122 goto err;
4123
4124 switch (socket.sa.sa_family)
4125 {
4126 case AF_UNIX:
4127 if (socket.un.sun_path[0]=='\0')
4128 {
4129 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4130 if (_dbus_string_append (address, "unix:abstract=") &&
4131 _dbus_address_append_escaped (address, &path_str))
4132 return TRUE;
4133 }
4134 else
4135 {
4136 _dbus_string_init_const (&path_str, socket.un.sun_path);
4137 if (_dbus_string_append (address, "unix:path=") &&
4138 _dbus_address_append_escaped (address, &path_str))
4139 return TRUE;
4140 }
4141 break;
4142 case AF_INET:
4143 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4144 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4145 hostip, ntohs (socket.ipv4.sin_port)))
4146 return TRUE;
4147 break;
4148 #ifdef AF_INET6
4149 case AF_INET6:
4150 _dbus_string_init_const (&path_str, hostip);
4151 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4152 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4153 ntohs (socket.ipv6.sin6_port)) &&
4154 _dbus_address_append_escaped (address, &path_str))
4155 return TRUE;
4156 break;
4157 #endif
4158 default:
4159 dbus_set_error (error,
4160 _dbus_error_from_errno (EINVAL),
4161 "Failed to read address from socket: Unknown socket type.");
4162 return FALSE;
4163 }
4164 err:
4165 dbus_set_error (error,
4166 _dbus_error_from_errno (errno),
4167 "Failed to open socket: %s",
4168 _dbus_strerror (errno));
4169 return FALSE;
4170 }
4171
4172 /* 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:918
_dbus_string_parse_int
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:227
_dbus_credentials_get_unix_uid
dbus_uid_t _dbus_credentials_get_unix_uid(DBusCredentials *credentials)
Gets the UNIX user ID in the credentials, or DBUS_UID_UNSET if the credentials object doesn't contain...
Definition: dbus-credentials.c:268
_dbus_string_append_uint
dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:392
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition: dbus-sysdeps-unix.c:2547
DBusUserInfo::username
char * username
Username.
Definition: dbus-sysdeps-unix.h:104
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:411
DBusAtomic::value
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:232
_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:2022
_DBUS_POLLHUP
#define _DBUS_POLLHUP
Hung up.
Definition: dbus-sysdeps.h:302
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:743
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_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:3926
_dbus_socket_can_pass_unix_fd
dbus_bool_t _dbus_socket_can_pass_unix_fd(int fd)
Checks whether file descriptors may be passed via the socket.
Definition: dbus-sysdeps-unix.c:3954
_DBUS_POLLNVAL
#define _DBUS_POLLNVAL
Invalid request: fd not open.
Definition: dbus-sysdeps.h:304
_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:685
DBUS_ERROR_NOT_SUPPORTED
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
Definition: dbus-protocol.h:364
_dbus_append_address_from_socket
dbus_bool_t _dbus_append_address_from_socket(int fd, DBusString *address, DBusError *error)
Read the address from the socket and append it to the string.
Definition: dbus-sysdeps-unix.c:4106
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:114
DBUS_PID_FORMAT
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:110
_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:3807
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition: dbus-internals.h:135
_dbus_full_duplex_pipe
dbus_bool_t _dbus_full_duplex_pipe(int *fd1, int *fd2, dbus_bool_t blocking, DBusError *error)
Creates a full-duplex pipe (as in socketpair()).
Definition: dbus-sysdeps-unix.c:3108
_dbus_write_socket_two
int _dbus_write_socket_two(int 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:546
_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:4053
_dbus_user_database_flush_system
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
Definition: dbus-userdb.c:349
dbus_error_free
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
DBusUserInfo::primary_gid
dbus_gid_t primary_gid
GID.
Definition: dbus-sysdeps-unix.h:101
_DBUS_POLLPRI
#define _DBUS_POLLPRI
There is urgent data to read.
Definition: dbus-sysdeps.h:296
_dbus_read_socket_with_unix_fds
int _dbus_read_socket_with_unix_fds(int 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:273
DBusPollFD
A portable struct pollfd wrapper.
Definition: dbus-sysdeps.h:310
DBusGUID
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
Definition: dbus-internals.h:350
_dbus_accept
int _dbus_accept(int listen_fd)
Accepts a connection on a listening socket.
Definition: dbus-sysdeps-unix.c:1967
_dbus_dup
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
Definition: dbus-sysdeps-unix.c:2986
_DBUS_POLLIN
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:294
_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:473
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
_dbus_getpid
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
Definition: dbus-sysdeps-unix.c:2409
_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:2398
DBUS_ERROR_IO_ERROR
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
Definition: dbus-protocol.h:360
_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:763
DBusPollFD::events
short events
Events to poll for.
Definition: dbus-sysdeps.h:313
_dbus_string_copy
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1265
_dbus_read_credentials_socket
dbus_bool_t _dbus_read_credentials_socket(int 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:1664
DBUS_PID_UNSET
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
Definition: dbus-sysdeps.h:103
_dbus_credentials_clear
void _dbus_credentials_clear(DBusCredentials *credentials)
Clear all credentials in the object.
Definition: dbus-credentials.c:446
dirent
Definition: dbus-sysdeps-util-win.c:489
DBUS_UID_UNSET
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:105
_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:2452
_dbus_getenv
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
_dbus_get_local_machine_uuid_encoded
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str)
Gets the hex-encoded UUID of the machine this function is executed on.
Definition: dbus-internals.c:854
_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:3507
_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:614
_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:2335
_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_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:2671
dbus_pid_t
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:96
DBusUserInfo::group_ids
dbus_gid_t * group_ids
Groups IDs, including above primary group.
Definition: dbus-sysdeps-unix.h:102
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:2523
_dbus_fd_set_close_on_exec
void _dbus_fd_set_close_on_exec(intptr_t fd)
Sets the file descriptor to be close on exec.
Definition: dbus-sysdeps-unix.c:2936
_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:3657
_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:2702
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:461
_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:2758
_dbus_close_all
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:3983
_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:361
DBusString
Definition: dbus-string.h:42
DIR
Definition: dbus-sysdeps-util-win.c:498
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:103
_dbus_poll
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
Definition: dbus-sysdeps-unix.c:2572
_DBUS_POLLOUT
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:298
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition: dbus-internals.c:230
DBusUserInfo::uid
dbus_uid_t uid
UID.
Definition: dbus-sysdeps-unix.h:100
_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:1096
_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:3826
_dbus_read_socket
int _dbus_read_socket(int fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
Definition: dbus-sysdeps-unix.c:217
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_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition: dbus-sysdeps-unix.c:2923
_dbus_send_credentials_socket
dbus_bool_t _dbus_send_credentials_socket(int server_fd, DBusError *error)
Sends a single nul byte with our UNIX credentials as ancillary data.
Definition: dbus-sysdeps-unix.c:1946
DBUS_ERROR_BAD_ADDRESS
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
Definition: dbus-protocol.h:362
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:204
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition: dbus-sysdeps-unix.c:2500
_DBUS_N_ELEMENTS
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
Definition: dbus-internals.h:174
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:2958
DBusPollFD::fd
int fd
File descriptor.
Definition: dbus-sysdeps.h:312
_dbus_create_directory
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
Definition: dbus-sysdeps-unix.c:2724
_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:926
_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:1139
_DBUS_UNLOCK
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
Definition: dbus-internals.h:330
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
DBUS_GID_UNSET
#define DBUS_GID_UNSET
an invalid GID used to represent an uninitialized dbus_gid_t field
Definition: dbus-sysdeps.h:107
_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:2368
TRUE
#define TRUE
Expands to "1".
_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:149
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition: dbus-protocol.h:350
READ_END
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:857
DBUS_UID_FORMAT
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:112
_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:806
DBusUserInfo::homedir
char * homedir
Home directory.
Definition: dbus-sysdeps-unix.h:105
_dbus_getuid
dbus_uid_t _dbus_getuid(void)
Gets our UID.
Definition: dbus-sysdeps-unix.c:2418
_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:3253
_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:2439
_dbus_generate_pseudorandom_bytes_buffer
void _dbus_generate_pseudorandom_bytes_buffer(char *buffer, int n_bytes)
Random numbers.
Definition: dbus-sysdeps.c:508
_dbus_write_socket
int _dbus_write_socket(int 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:235
_dbus_exit
void _dbus_exit(int code)
Exit the process, returning the given value.
Definition: dbus-sysdeps-unix.c:2894
_dbus_get_is_errno_eagain_or_ewouldblock
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(void)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted) ...
Definition: dbus-sysdeps-unix.c:3913
_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:2352
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition: dbus-protocol.h:352
_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:3782
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're running on from the dbus configuration.
Definition: dbus-sysdeps-unix.c:3610
_dbus_generate_uuid
void _dbus_generate_uuid(DBusGUID *uuid)
Generates a new UUID.
Definition: dbus-internals.c:641
_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:757
_dbus_print_backtrace
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
Definition: dbus-sysdeps-unix.c:3066
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:785
_DBUS_LOCK
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
Definition: dbus-internals.h:329
_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:731
_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:3183
_dbus_verbose_bytes_of_string
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
_dbus_geteuid
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
Definition: dbus-sysdeps-unix.c:2427
WRITE_END
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:859
dbus_gid_t
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:100
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition: dbus-internals.c:527
_dbus_close_socket
dbus_bool_t _dbus_close_socket(int fd, DBusError *error)
Closes a socket.
Definition: dbus-sysdeps-unix.c:201
_DBUS_ZERO
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
Definition: dbus-internals.h:179
_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:164
dbus_uid_t
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:98
DBusPollFD::revents
short revents
Events that occurred.
Definition: dbus-sysdeps.h:314
_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:830
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition: dbus-sysdeps-unix.c:2803
_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:625
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:1032
_dbus_connect_tcp_socket
int _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:1253
_dbus_listen_systemd_sockets
int _dbus_listen_systemd_sockets(int **fds, DBusError *error)
Acquires one or more sockets passed in from systemd.
Definition: dbus-sysdeps-unix.c:1159
_dbus_listen_tcp_socket
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, int **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
Definition: dbus-sysdeps-unix.c:1377
_dbus_generate_random_bytes
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes)
Generates the given number of random bytes, using the best mechanism we can come up with...
Definition: dbus-sysdeps-unix.c:2851
DBusUserInfo
Information about a UNIX user.
Definition: dbus-sysdeps-unix.h:98
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:300