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

D-Bus 1.13.18

dbus-sysdeps-unix.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #include <config.h>
26
27 #include "dbus-internals.h"
28 #include "dbus-sysdeps.h"
29 #include "dbus-sysdeps-unix.h"
30 #include "dbus-threads.h"
31 #include "dbus-protocol.h"
32 #include "dbus-file.h"
33 #include "dbus-transport.h"
34 #include "dbus-string.h"
35 #include "dbus-userdb.h"
36 #include "dbus-list.h"
37 #include "dbus-credentials.h"
38 #include "dbus-nonce.h"
39
40 #include <sys/types.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <fcntl.h>
47 #include <sys/socket.h>
48 #include <dirent.h>
49 #include <sys/un.h>
50 #include <pwd.h>
51 #include <time.h>
52 #include <locale.h>
53 #include <sys/time.h>
54 #include <sys/stat.h>
55 #include <sys/wait.h>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <netdb.h>
59 #include <grp.h>
60 #include <arpa/inet.h>
61
62 #ifdef HAVE_ERRNO_H
63 #include <errno.h>
64 #endif
65 #ifdef HAVE_SYSLOG_H
66 #include <syslog.h>
67 #endif
68 #ifdef HAVE_WRITEV
69 #include <sys/uio.h>
70 #endif
71 #ifdef HAVE_BACKTRACE
72 #include <execinfo.h>
73 #endif
74 #ifdef HAVE_GETPEERUCRED
75 #include <ucred.h>
76 #endif
77 #ifdef HAVE_ALLOCA_H
78 #include <alloca.h>
79 #endif
80 #ifdef HAVE_SYS_RANDOM_H
81 #include <sys/random.h>
82 #endif
83
84 #ifdef HAVE_ADT
85 #include <bsm/adt.h>
86 #endif
87
88 #ifdef HAVE_SYSTEMD
89 #include <systemd/sd-daemon.h>
90 #endif
91
92 #if !DBUS_USE_SYNC
93 #include <pthread.h>
94 #endif
95
96 #ifndef O_BINARY
97 #define O_BINARY 0
98 #endif
99
100 #ifndef AI_ADDRCONFIG
101 #define AI_ADDRCONFIG 0
102 #endif
103
104 #ifndef HAVE_SOCKLEN_T
105 #define socklen_t int
106 #endif
107
108 #if defined (__sun) || defined (__sun__)
109 /*
110 * CMS_SPACE etc. definitions for Solaris < 10, based on
111 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
112 * via
113 * http://wiki.opencsw.org/porting-faq#toc10
114 *
115 * These are only redefined for Solaris, for now: if your OS needs these too,
116 * please file a bug. (Or preferably, improve your OS so they're not needed.)
117 */
118
119 # ifndef CMSG_ALIGN
120 # ifdef __sun__
121 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
122 # else
123 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
124 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
125 ~(sizeof (long) - 1))
126 # endif
127 # endif
128
129 # ifndef CMSG_SPACE
130 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
131 CMSG_ALIGN (len))
132 # endif
133
134 # ifndef CMSG_LEN
135 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
136 # endif
137
138 #endif /* Solaris */
139
154 dbus_bool_t
155 _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
156 const char **error_str_p)
157 {
158 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
159 DBUS_FORCE_STDOUT_NULL,
160 DBUS_FORCE_STDERR_NULL };
161 /* Should always get replaced with the real error before use */
162 const char *error_str = "Failed mysteriously";
163 int devnull = -1;
164 int saved_errno;
165 /* This function relies on the standard fds having their POSIX values. */
166 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
167 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
168 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
169 int i;
170
171 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
172 {
173 /* Because we rely on being single-threaded, and we want the
174 * standard fds to not be close-on-exec, we don't set it
175 * close-on-exec. */
176 if (devnull < i)
177 devnull = open ("/dev/null", O_RDWR);
178
179 if (devnull < 0)
180 {
181 error_str = "Failed to open /dev/null";
182 goto out;
183 }
184
185 /* We already opened all fds < i, so the only way this assertion
186 * could fail is if another thread closed one, and we document
187 * this function as not safe for multi-threading. */
188 _dbus_assert (devnull >= i);
189
190 if (devnull != i && (flags & relevant_flag[i]) != 0)
191 {
192 if (dup2 (devnull, i) < 0)
193 {
194 error_str = "Failed to dup2 /dev/null onto a standard fd";
195 goto out;
196 }
197 }
198 }
199
200 error_str = NULL;
201
202 out:
203 saved_errno = errno;
204
205 if (devnull > STDERR_FILENO)
206 close (devnull);
207
208 if (error_str_p != NULL)
209 *error_str_p = error_str;
210
211 errno = saved_errno;
212 return (error_str == NULL);
213 }
214
215 static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
216 DBusError *error);
217
218 static dbus_bool_t
219 _dbus_open_socket (int *fd_p,
220 int domain,
221 int type,
222 int protocol,
223 DBusError *error)
224 {
225 #ifdef SOCK_CLOEXEC
226 dbus_bool_t cloexec_done;
227
228 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
229 cloexec_done = *fd_p >= 0;
230
231 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
232 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
233 #endif
234 {
235 *fd_p = socket (domain, type, protocol);
236 }
237
238 if (*fd_p >= 0)
239 {
240 #ifdef SOCK_CLOEXEC
241 if (!cloexec_done)
242 #endif
243 {
244 _dbus_fd_set_close_on_exec(*fd_p);
245 }
246
247 _dbus_verbose ("socket fd %d opened\n", *fd_p);
248 return TRUE;
249 }
250 else
251 {
252 dbus_set_error(error,
253 _dbus_error_from_errno (errno),
254 "Failed to open socket: %s",
255 _dbus_strerror (errno));
256 return FALSE;
257 }
258 }
259
270 static dbus_bool_t
271 _dbus_open_unix_socket (int *fd,
272 DBusError *error)
273 {
274 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
275 }
276
285 dbus_bool_t
286 _dbus_close_socket (DBusSocket fd,
287 DBusError *error)
288 {
289 return _dbus_close (fd.fd, error);
290 }
291
301 int
302 _dbus_read_socket (DBusSocket fd,
303 DBusString *buffer,
304 int count)
305 {
306 return _dbus_read (fd.fd, buffer, count);
307 }
308
319 int
320 _dbus_write_socket (DBusSocket fd,
321 const DBusString *buffer,
322 int start,
323 int len)
324 {
325 #if HAVE_DECL_MSG_NOSIGNAL
326 const char *data;
327 int bytes_written;
328
329 data = _dbus_string_get_const_data_len (buffer, start, len);
330
331 again:
332
333 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
334
335 if (bytes_written < 0 && errno == EINTR)
336 goto again;
337
338 return bytes_written;
339
340 #else
341 return _dbus_write (fd.fd, buffer, start, len);
342 #endif
343 }
344
357 int
358 _dbus_read_socket_with_unix_fds (DBusSocket fd,
359 DBusString *buffer,
360 int count,
361 int *fds,
362 unsigned int *n_fds) {
363 #ifndef HAVE_UNIX_FD_PASSING
364 int r;
365
366 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
367 return r;
368
369 *n_fds = 0;
370 return r;
371
372 #else
373 int bytes_read;
374 int start;
375 struct msghdr m;
376 struct iovec iov;
377
378 _dbus_assert (count >= 0);
379 _dbus_assert (*n_fds <= DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
380
381 start = _dbus_string_get_length (buffer);
382
383 if (!_dbus_string_lengthen (buffer, count))
384 {
385 errno = ENOMEM;
386 return -1;
387 }
388
389 _DBUS_ZERO(iov);
390 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
391 iov.iov_len = count;
392
393 _DBUS_ZERO(m);
394 m.msg_iov = &iov;
395 m.msg_iovlen = 1;
396
397 /* Hmm, we have no clue how long the control data will actually be
398 that is queued for us. The least we can do is assume that the
399 caller knows. Hence let's make space for the number of fds that
400 we shall read at max plus the cmsg header. */
401 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
402
403 /* It's probably safe to assume that systems with SCM_RIGHTS also
404 know alloca() */
405 m.msg_control = alloca(m.msg_controllen);
406 memset(m.msg_control, 0, m.msg_controllen);
407
408 /* Do not include the padding at the end when we tell the kernel
409 * how much we're willing to receive. This avoids getting
410 * the padding filled with additional fds that we weren't expecting,
411 * if a (potentially malicious) sender included them. (fd.o #83622) */
412 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
413
414 again:
415
416 bytes_read = recvmsg (fd.fd, &m, 0
417 #ifdef MSG_CMSG_CLOEXEC
418 |MSG_CMSG_CLOEXEC
419 #endif
420 );
421
422 if (bytes_read < 0)
423 {
424 if (errno == EINTR)
425 goto again;
426 else
427 {
428 /* put length back (note that this doesn't actually realloc anything) */
429 _dbus_string_set_length (buffer, start);
430 return -1;
431 }
432 }
433 else
434 {
435 struct cmsghdr *cm;
436 dbus_bool_t found = FALSE;
437
438 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
439 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
440 {
441 size_t i;
442 int *payload = (int *) CMSG_DATA (cm);
443 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
444 size_t payload_len_fds;
445 size_t fds_to_use;
446
447 /* Every unsigned int fits in a size_t without truncation, so
448 * casting (size_t) *n_fds is OK */
449 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
450
451 if ((m.msg_flags & MSG_CTRUNC) && CMSG_NXTHDR(&m, cm) == NULL &&
452 (char *) payload + payload_len_bytes >
453 (char *) m.msg_control + m.msg_controllen)
454 {
455 /* This is the last cmsg in a truncated message and using
456 * cmsg_len would apparently overrun the allocated buffer.
457 * Some operating systems (illumos and Solaris are known) do
458 * not adjust cmsg_len in the last cmsg when truncation occurs.
459 * Adjust the payload length here. The calculation for
460 * payload_len_fds below will discard any trailing bytes that
461 * belong to an incomplete file descriptor - the kernel will
462 * have already closed that (at least for illumos and Solaris)
463 */
464 payload_len_bytes = m.msg_controllen -
465 ((char *) payload - (char *) m.msg_control);
466 }
467
468 payload_len_fds = payload_len_bytes / sizeof (int);
469
470 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
471 {
472 /* The fds in the payload will fit in our buffer */
473 fds_to_use = payload_len_fds;
474 }
475 else
476 {
477 /* Too many fds in the payload. This shouldn't happen
478 * any more because we're setting m.msg_controllen to
479 * the exact number we can accept, but be safe and
480 * truncate. */
481 fds_to_use = (size_t) *n_fds;
482
483 /* Close the excess fds to avoid DoS: if they stayed open,
484 * someone could send us an extra fd per message
485 * and we'd eventually run out. */
486 for (i = fds_to_use; i < payload_len_fds; i++)
487 {
488 close (payload[i]);
489 }
490 }
491
492 memcpy (fds, payload, fds_to_use * sizeof (int));
493 found = TRUE;
494 /* This narrowing cast from size_t to unsigned int cannot
495 * overflow because we have chosen fds_to_use
496 * to be <= *n_fds */
497 *n_fds = (unsigned int) fds_to_use;
498
499 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
500 worked, hence we need to go through this list and set
501 CLOEXEC everywhere in any case */
502 for (i = 0; i < fds_to_use; i++)
503 _dbus_fd_set_close_on_exec(fds[i]);
504
505 break;
506 }
507
508 if (!found)
509 *n_fds = 0;
510
511 if (m.msg_flags & MSG_CTRUNC)
512 {
513 unsigned int i;
514
515 /* Hmm, apparently the control data was truncated. The bad
516 thing is that we might have completely lost a couple of fds
517 without chance to recover them. Hence let's treat this as a
518 serious error. */
519
520 /* We still need to close whatever fds we *did* receive,
521 * otherwise they'll never get closed. (CVE-2020-12049) */
522 for (i = 0; i < *n_fds; i++)
523 close (fds[i]);
524
525 *n_fds = 0;
526 errno = ENOSPC;
527 _dbus_string_set_length (buffer, start);
528 return -1;
529 }
530
531 /* put length back (doesn't actually realloc) */
532 _dbus_string_set_length (buffer, start + bytes_read);
533
534 #if 0
535 if (bytes_read > 0)
536 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
537 #endif
538
539 return bytes_read;
540 }
541 #endif
542 }
543
544 int
545 _dbus_write_socket_with_unix_fds(DBusSocket fd,
546 const DBusString *buffer,
547 int start,
548 int len,
549 const int *fds,
550 int n_fds) {
551
552 #ifndef HAVE_UNIX_FD_PASSING
553
554 if (n_fds > 0) {
555 errno = ENOTSUP;
556 return -1;
557 }
558
559 return _dbus_write_socket(fd, buffer, start, len);
560 #else
561 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
562 #endif
563 }
564
565 int
566 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
567 const DBusString *buffer1,
568 int start1,
569 int len1,
570 const DBusString *buffer2,
571 int start2,
572 int len2,
573 const int *fds,
574 int n_fds) {
575
576 #ifndef HAVE_UNIX_FD_PASSING
577
578 if (n_fds > 0) {
579 errno = ENOTSUP;
580 return -1;
581 }
582
583 return _dbus_write_socket_two(fd,
584 buffer1, start1, len1,
585 buffer2, start2, len2);
586 #else
587
588 struct msghdr m;
589 struct cmsghdr *cm;
590 struct iovec iov[2];
591 int bytes_written;
592
593 _dbus_assert (len1 >= 0);
594 _dbus_assert (len2 >= 0);
595 _dbus_assert (n_fds >= 0);
596
597 _DBUS_ZERO(iov);
598 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
599 iov[0].iov_len = len1;
600
601 if (buffer2)
602 {
603 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
604 iov[1].iov_len = len2;
605 }
606
607 _DBUS_ZERO(m);
608 m.msg_iov = iov;
609 m.msg_iovlen = buffer2 ? 2 : 1;
610
611 if (n_fds > 0)
612 {
613 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
614 m.msg_control = alloca(m.msg_controllen);
615 memset(m.msg_control, 0, m.msg_controllen);
616
617 cm = CMSG_FIRSTHDR(&m);
618 cm->cmsg_level = SOL_SOCKET;
619 cm->cmsg_type = SCM_RIGHTS;
620 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
621 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
622 }
623
624 again:
625
626 bytes_written = sendmsg (fd.fd, &m, 0
627 #if HAVE_DECL_MSG_NOSIGNAL
628 |MSG_NOSIGNAL
629 #endif
630 );
631
632 if (bytes_written < 0 && errno == EINTR)
633 goto again;
634
635 #if 0
636 if (bytes_written > 0)
637 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
638 #endif
639
640 return bytes_written;
641 #endif
642 }
643
657 int
658 _dbus_write_socket_two (DBusSocket fd,
659 const DBusString *buffer1,
660 int start1,
661 int len1,
662 const DBusString *buffer2,
663 int start2,
664 int len2)
665 {
666 #if HAVE_DECL_MSG_NOSIGNAL
667 struct iovec vectors[2];
668 const char *data1;
669 const char *data2;
670 int bytes_written;
671 struct msghdr m;
672
673 _dbus_assert (buffer1 != NULL);
674 _dbus_assert (start1 >= 0);
675 _dbus_assert (start2 >= 0);
676 _dbus_assert (len1 >= 0);
677 _dbus_assert (len2 >= 0);
678
679 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
680
681 if (buffer2 != NULL)
682 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
683 else
684 {
685 data2 = NULL;
686 start2 = 0;
687 len2 = 0;
688 }
689
690 vectors[0].iov_base = (char*) data1;
691 vectors[0].iov_len = len1;
692 vectors[1].iov_base = (char*) data2;
693 vectors[1].iov_len = len2;
694
695 _DBUS_ZERO(m);
696 m.msg_iov = vectors;
697 m.msg_iovlen = data2 ? 2 : 1;
698
699 again:
700
701 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
702
703 if (bytes_written < 0 && errno == EINTR)
704 goto again;
705
706 return bytes_written;
707
708 #else
709 return _dbus_write_two (fd.fd, buffer1, start1, len1,
710 buffer2, start2, len2);
711 #endif
712 }
713
730 int
731 _dbus_read (int fd,
732 DBusString *buffer,
733 int count)
734 {
735 int bytes_read;
736 int start;
737 char *data;
738
739 _dbus_assert (count >= 0);
740
741 start = _dbus_string_get_length (buffer);
742
743 if (!_dbus_string_lengthen (buffer, count))
744 {
745 errno = ENOMEM;
746 return -1;
747 }
748
749 data = _dbus_string_get_data_len (buffer, start, count);
750
751 again:
752
753 bytes_read = read (fd, data, count);
754
755 if (bytes_read < 0)
756 {
757 if (errno == EINTR)
758 goto again;
759 else
760 {
761 /* put length back (note that this doesn't actually realloc anything) */
762 _dbus_string_set_length (buffer, start);
763 return -1;
764 }
765 }
766 else
767 {
768 /* put length back (doesn't actually realloc) */
769 _dbus_string_set_length (buffer, start + bytes_read);
770
771 #if 0
772 if (bytes_read > 0)
773 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
774 #endif
775
776 return bytes_read;
777 }
778 }
779
790 int
791 _dbus_write (int fd,
792 const DBusString *buffer,
793 int start,
794 int len)
795 {
796 const char *data;
797 int bytes_written;
798
799 data = _dbus_string_get_const_data_len (buffer, start, len);
800
801 again:
802
803 bytes_written = write (fd, data, len);
804
805 if (bytes_written < 0 && errno == EINTR)
806 goto again;
807
808 #if 0
809 if (bytes_written > 0)
810 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
811 #endif
812
813 return bytes_written;
814 }
815
836 int
837 _dbus_write_two (int fd,
838 const DBusString *buffer1,
839 int start1,
840 int len1,
841 const DBusString *buffer2,
842 int start2,
843 int len2)
844 {
845 _dbus_assert (buffer1 != NULL);
846 _dbus_assert (start1 >= 0);
847 _dbus_assert (start2 >= 0);
848 _dbus_assert (len1 >= 0);
849 _dbus_assert (len2 >= 0);
850
851 #ifdef HAVE_WRITEV
852 {
853 struct iovec vectors[2];
854 const char *data1;
855 const char *data2;
856 int bytes_written;
857
858 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
859
860 if (buffer2 != NULL)
861 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
862 else
863 {
864 data2 = NULL;
865 start2 = 0;
866 len2 = 0;
867 }
868
869 vectors[0].iov_base = (char*) data1;
870 vectors[0].iov_len = len1;
871 vectors[1].iov_base = (char*) data2;
872 vectors[1].iov_len = len2;
873
874 again:
875
876 bytes_written = writev (fd,
877 vectors,
878 data2 ? 2 : 1);
879
880 if (bytes_written < 0 && errno == EINTR)
881 goto again;
882
883 return bytes_written;
884 }
885 #else /* HAVE_WRITEV */
886 {
887 int ret1, ret2;
888
889 ret1 = _dbus_write (fd, buffer1, start1, len1);
890 if (ret1 == len1 && buffer2 != NULL)
891 {
892 ret2 = _dbus_write (fd, buffer2, start2, len2);
893 if (ret2 < 0)
894 ret2 = 0; /* we can't report an error as the first write was OK */
895
896 return ret1 + ret2;
897 }
898 else
899 return ret1;
900 }
901 #endif /* !HAVE_WRITEV */
902 }
903
904 #define _DBUS_MAX_SUN_PATH_LENGTH 99
905
935 int
936 _dbus_connect_unix_socket (const char *path,
937 dbus_bool_t abstract,
938 DBusError *error)
939 {
940 int fd;
941 size_t path_len;
942 struct sockaddr_un addr;
943 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
944
945 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
946
947 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
948 path, abstract);
949
950
951 if (!_dbus_open_unix_socket (&fd, error))
952 {
953 _DBUS_ASSERT_ERROR_IS_SET(error);
954 return -1;
955 }
956 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
957
958 _DBUS_ZERO (addr);
959 addr.sun_family = AF_UNIX;
960 path_len = strlen (path);
961
962 if (abstract)
963 {
964 #ifdef __linux__
965 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
966 path_len++; /* Account for the extra nul byte added to the start of sun_path */
967
968 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
969 {
970 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
971 "Abstract socket name too long\n");
972 _dbus_close (fd, NULL);
973 return -1;
974 }
975
976 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
977 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
978 #else /* !__linux__ */
979 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
980 "Operating system does not support abstract socket namespace\n");
981 _dbus_close (fd, NULL);
982 return -1;
983 #endif /* !__linux__ */
984 }
985 else
986 {
987 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
988 {
989 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
990 "Socket name too long\n");
991 _dbus_close (fd, NULL);
992 return -1;
993 }
994
995 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
996 }
997
998 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
999 {
1000 dbus_set_error (error,
1001 _dbus_error_from_errno (errno),
1002 "Failed to connect to socket %s: %s",
1003 path, _dbus_strerror (errno));
1004
1005 _dbus_close (fd, NULL);
1006 return -1;
1007 }
1008
1009 if (!_dbus_set_fd_nonblocking (fd, error))
1010 {
1011 _DBUS_ASSERT_ERROR_IS_SET (error);
1012
1013 _dbus_close (fd, NULL);
1014 return -1;
1015 }
1016
1017 return fd;
1018 }
1019
1032 int
1033 _dbus_connect_exec (const char *path,
1034 char *const argv[],
1035 DBusError *error)
1036 {
1037 int fds[2];
1038 pid_t pid;
1039 int retval;
1040 dbus_bool_t cloexec_done = 0;
1041
1042 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1043
1044 _dbus_verbose ("connecting to process %s\n", path);
1045
1046 #ifdef SOCK_CLOEXEC
1047 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1048 cloexec_done = (retval >= 0);
1049
1050 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1051 #endif
1052 {
1053 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1054 }
1055
1056 if (retval < 0)
1057 {
1058 dbus_set_error (error,
1059 _dbus_error_from_errno (errno),
1060 "Failed to create socket pair: %s",
1061 _dbus_strerror (errno));
1062 return -1;
1063 }
1064
1065 if (!cloexec_done)
1066 {
1067 _dbus_fd_set_close_on_exec (fds[0]);
1068 _dbus_fd_set_close_on_exec (fds[1]);
1069 }
1070
1071 /* Make sure our output buffers aren't redundantly printed by both the
1072 * parent and the child */
1073 fflush (stdout);
1074 fflush (stderr);
1075
1076 pid = fork ();
1077 if (pid < 0)
1078 {
1079 dbus_set_error (error,
1080 _dbus_error_from_errno (errno),
1081 "Failed to fork() to call %s: %s",
1082 path, _dbus_strerror (errno));
1083 close (fds[0]);
1084 close (fds[1]);
1085 return -1;
1086 }
1087
1088 if (pid == 0)
1089 {
1090 /* child */
1091 close (fds[0]);
1092
1093 dup2 (fds[1], STDIN_FILENO);
1094 dup2 (fds[1], STDOUT_FILENO);
1095
1096 if (fds[1] != STDIN_FILENO &&
1097 fds[1] != STDOUT_FILENO)
1098 close (fds[1]);
1099
1100 /* Inherit STDERR and the controlling terminal from the
1101 parent */
1102
1103 _dbus_close_all ();
1104
1105 execvp (path, (char * const *) argv);
1106
1107 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1108
1109 _exit(1);
1110 }
1111
1112 /* parent */
1113 close (fds[1]);
1114
1115 if (!_dbus_set_fd_nonblocking (fds[0], error))
1116 {
1117 _DBUS_ASSERT_ERROR_IS_SET (error);
1118
1119 close (fds[0]);
1120 return -1;
1121 }
1122
1123 return fds[0];
1124 }
1125
1143 int
1144 _dbus_listen_unix_socket (const char *path,
1145 dbus_bool_t abstract,
1146 DBusError *error)
1147 {
1148 int listen_fd;
1149 struct sockaddr_un addr;
1150 size_t path_len;
1151 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1152
1153 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1154
1155 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1156 path, abstract);
1157
1158 if (!_dbus_open_unix_socket (&listen_fd, error))
1159 {
1160 _DBUS_ASSERT_ERROR_IS_SET(error);
1161 return -1;
1162 }
1163 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1164
1165 _DBUS_ZERO (addr);
1166 addr.sun_family = AF_UNIX;
1167 path_len = strlen (path);
1168
1169 if (abstract)
1170 {
1171 #ifdef __linux__
1172 /* remember that abstract names aren't nul-terminated so we rely
1173 * on sun_path being filled in with zeroes above.
1174 */
1175 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1176 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1177
1178 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1179 {
1180 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1181 "Abstract socket name too long\n");
1182 _dbus_close (listen_fd, NULL);
1183 return -1;
1184 }
1185
1186 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1187 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1188 #else /* !__linux__ */
1189 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1190 "Operating system does not support abstract socket namespace\n");
1191 _dbus_close (listen_fd, NULL);
1192 return -1;
1193 #endif /* !__linux__ */
1194 }
1195 else
1196 {
1197 /* Discussed security implications of this with Nalin,
1198 * and we couldn't think of where it would kick our ass, but
1199 * it still seems a bit sucky. It also has non-security suckage;
1200 * really we'd prefer to exit if the socket is already in use.
1201 * But there doesn't seem to be a good way to do this.
1202 *
1203 * Just to be extra careful, I threw in the stat() - clearly
1204 * the stat() can't *fix* any security issue, but it at least
1205 * avoids inadvertent/accidental data loss.
1206 */
1207 {
1208 struct stat sb;
1209
1210 if (stat (path, &sb) == 0 &&
1211 S_ISSOCK (sb.st_mode))
1212 unlink (path);
1213 }
1214
1215 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1216 {
1217 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1218 "Socket name too long\n");
1219 _dbus_close (listen_fd, NULL);
1220 return -1;
1221 }
1222
1223 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1224 }
1225
1226 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1227 {
1228 dbus_set_error (error, _dbus_error_from_errno (errno),
1229 "Failed to bind socket \"%s\": %s",
1230 path, _dbus_strerror (errno));
1231 _dbus_close (listen_fd, NULL);
1232 return -1;
1233 }
1234
1235 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1236 {
1237 dbus_set_error (error, _dbus_error_from_errno (errno),
1238 "Failed to listen on socket \"%s\": %s",
1239 path, _dbus_strerror (errno));
1240 _dbus_close (listen_fd, NULL);
1241 return -1;
1242 }
1243
1244 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1245 {
1246 _DBUS_ASSERT_ERROR_IS_SET (error);
1247 _dbus_close (listen_fd, NULL);
1248 return -1;
1249 }
1250
1251 /* Try opening up the permissions, but if we can't, just go ahead
1252 * and continue, maybe it will be good enough.
1253 */
1254 if (!abstract && chmod (path, 0777) < 0)
1255 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1256
1257 return listen_fd;
1258 }
1259
1270 int
1271 _dbus_listen_systemd_sockets (DBusSocket **fds,
1272 DBusError *error)
1273 {
1274 #ifdef HAVE_SYSTEMD
1275 int r, n;
1276 int fd;
1277 DBusSocket *new_fds;
1278
1279 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1280
1281 n = sd_listen_fds (TRUE);
1282 if (n < 0)
1283 {
1284 dbus_set_error (error, _dbus_error_from_errno (-n),
1285 "Failed to acquire systemd socket: %s",
1286 _dbus_strerror (-n));
1287 return -1;
1288 }
1289
1290 if (n <= 0)
1291 {
1292 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1293 "No socket received.");
1294 return -1;
1295 }
1296
1297 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1298 {
1299 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1300 if (r < 0)
1301 {
1302 dbus_set_error (error, _dbus_error_from_errno (-r),
1303 "Failed to verify systemd socket type: %s",
1304 _dbus_strerror (-r));
1305 return -1;
1306 }
1307
1308 if (!r)
1309 {
1310 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1311 "Passed socket has wrong type.");
1312 return -1;
1313 }
1314 }
1315
1316 /* OK, the file descriptors are all good, so let's take posession of
1317 them then. */
1318
1319 new_fds = dbus_new (DBusSocket, n);
1320 if (!new_fds)
1321 {
1322 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1323 "Failed to allocate file handle array.");
1324 goto fail;
1325 }
1326
1327 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1328 {
1329 if (!_dbus_set_fd_nonblocking (fd, error))
1330 {
1331 _DBUS_ASSERT_ERROR_IS_SET (error);
1332 goto fail;
1333 }
1334
1335 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1336 }
1337
1338 *fds = new_fds;
1339 return n;
1340
1341 fail:
1342
1343 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1344 {
1345 _dbus_close (fd, NULL);
1346 }
1347
1348 dbus_free (new_fds);
1349 return -1;
1350 #else
1351 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
1352 "dbus was compiled without systemd support");
1353 return -1;
1354 #endif
1355 }
1356
1357 /* Convert an error code from getaddrinfo() or getnameinfo() into
1358 * a D-Bus error name. */
1359 static const char *
1360 _dbus_error_from_gai (int gai_res,
1361 int saved_errno)
1362 {
1363 switch (gai_res)
1364 {
1365 #ifdef EAI_FAMILY
1366 case EAI_FAMILY:
1367 /* ai_family not supported (at all) */
1368 return DBUS_ERROR_NOT_SUPPORTED;
1369 #endif
1370
1371 #ifdef EAI_SOCKTYPE
1372 case EAI_SOCKTYPE:
1373 /* ai_socktype not supported (at all) */
1374 return DBUS_ERROR_NOT_SUPPORTED;
1375 #endif
1376
1377 #ifdef EAI_MEMORY
1378 case EAI_MEMORY:
1379 /* Out of memory */
1380 return DBUS_ERROR_NO_MEMORY;
1381 #endif
1382
1383 #ifdef EAI_SYSTEM
1384 case EAI_SYSTEM:
1385 /* Unspecified system error, details in errno */
1386 return _dbus_error_from_errno (saved_errno);
1387 #endif
1388
1389 case 0:
1390 /* It succeeded, but we didn't get any addresses? */
1391 return DBUS_ERROR_FAILED;
1392
1393 /* EAI_AGAIN: Transient failure */
1394 /* EAI_BADFLAGS: invalid ai_flags (programming error) */
1395 /* EAI_FAIL: Non-recoverable failure */
1396 /* EAI_NODATA: host exists but has no addresses */
1397 /* EAI_NONAME: host does not exist */
1398 /* EAI_OVERFLOW: argument buffer overflow */
1399 /* EAI_SERVICE: service not available for specified socket
1400 * type (we should never see this because we use numeric
1401 * ports) */
1402 default:
1403 return DBUS_ERROR_FAILED;
1404 }
1405 }
1406
1420 DBusSocket
1421 _dbus_connect_tcp_socket (const char *host,
1422 const char *port,
1423 const char *family,
1424 DBusError *error)
1425 {
1426 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1427 }
1428
1429 DBusSocket
1430 _dbus_connect_tcp_socket_with_nonce (const char *host,
1431 const char *port,
1432 const char *family,
1433 const char *noncefile,
1434 DBusError *error)
1435 {
1436 int saved_errno = 0;
1437 DBusList *connect_errors = NULL;
1438 DBusSocket fd = DBUS_SOCKET_INIT;
1439 int res;
1440 struct addrinfo hints;
1441 struct addrinfo *ai = NULL;
1442 const struct addrinfo *tmp;
1443 DBusError *connect_error;
1444
1445 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1446
1447 _DBUS_ZERO (hints);
1448
1449 if (!family)
1450 hints.ai_family = AF_UNSPEC;
1451 else if (!strcmp(family, "ipv4"))
1452 hints.ai_family = AF_INET;
1453 else if (!strcmp(family, "ipv6"))
1454 hints.ai_family = AF_INET6;
1455 else
1456 {
1457 dbus_set_error (error,
1458 DBUS_ERROR_BAD_ADDRESS,
1459 "Unknown address family %s", family);
1460 return _dbus_socket_get_invalid ();
1461 }
1462 hints.ai_protocol = IPPROTO_TCP;
1463 hints.ai_socktype = SOCK_STREAM;
1464 hints.ai_flags = AI_ADDRCONFIG;
1465
1466 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1467 {
1468 dbus_set_error (error,
1469 _dbus_error_from_gai (res, errno),
1470 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1471 host, port, gai_strerror(res), res);
1472 _dbus_socket_invalidate (&fd);
1473 goto out;
1474 }
1475
1476 tmp = ai;
1477 while (tmp)
1478 {
1479 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1480 {
1481 _DBUS_ASSERT_ERROR_IS_SET(error);
1482 _dbus_socket_invalidate (&fd);
1483 goto out;
1484 }
1485 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1486
1487 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1488 {
1489 saved_errno = errno;
1490 _dbus_close (fd.fd, NULL);
1491 _dbus_socket_invalidate (&fd);
1492
1493 connect_error = dbus_new0 (DBusError, 1);
1494
1495 if (connect_error == NULL)
1496 {
1497 _DBUS_SET_OOM (error);
1498 goto out;
1499 }
1500
1501 dbus_error_init (connect_error);
1502 _dbus_set_error_with_inet_sockaddr (connect_error,
1503 tmp->ai_addr, tmp->ai_addrlen,
1504 "Failed to connect to socket",
1505 saved_errno);
1506
1507 if (!_dbus_list_append (&connect_errors, connect_error))
1508 {
1509 dbus_error_free (connect_error);
1510 dbus_free (connect_error);
1511 _DBUS_SET_OOM (error);
1512 goto out;
1513 }
1514
1515 tmp = tmp->ai_next;
1516 continue;
1517 }
1518
1519 break;
1520 }
1521
1522 if (!_dbus_socket_is_valid (fd))
1523 {
1524 _dbus_combine_tcp_errors (&connect_errors, "Failed to connect",
1525 host, port, error);
1526 goto out;
1527 }
1528
1529 if (noncefile != NULL)
1530 {
1531 DBusString noncefileStr;
1532 dbus_bool_t ret;
1533 _dbus_string_init_const (&noncefileStr, noncefile);
1534 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1535
1536 if (!ret)
1537 {
1538 _dbus_close (fd.fd, NULL);
1539 _dbus_socket_invalidate (&fd);
1540 goto out;
1541 }
1542 }
1543
1544 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1545 {
1546 _dbus_close (fd.fd, NULL);
1547 _dbus_socket_invalidate (&fd);
1548 goto out;
1549 }
1550
1551 out:
1552 if (ai != NULL)
1553 freeaddrinfo (ai);
1554
1555 while ((connect_error = _dbus_list_pop_first (&connect_errors)))
1556 {
1557 dbus_error_free (connect_error);
1558 dbus_free (connect_error);
1559 }
1560
1561 return fd;
1562 }
1563
1581 int
1582 _dbus_listen_tcp_socket (const char *host,
1583 const char *port,
1584 const char *family,
1585 DBusString *retport,
1586 const char **retfamily,
1587 DBusSocket **fds_p,
1588 DBusError *error)
1589 {
1590 int saved_errno;
1591 int nlisten_fd = 0, res, i;
1592 DBusList *bind_errors = NULL;
1593 DBusError *bind_error = NULL;
1594 DBusSocket *listen_fd = NULL;
1595 struct addrinfo hints;
1596 struct addrinfo *ai, *tmp;
1597 unsigned int reuseaddr;
1598 dbus_bool_t have_ipv4 = FALSE;
1599 dbus_bool_t have_ipv6 = FALSE;
1600
1601 *fds_p = NULL;
1602 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1603
1604 _DBUS_ZERO (hints);
1605
1606 if (!family)
1607 hints.ai_family = AF_UNSPEC;
1608 else if (!strcmp(family, "ipv4"))
1609 hints.ai_family = AF_INET;
1610 else if (!strcmp(family, "ipv6"))
1611 hints.ai_family = AF_INET6;
1612 else
1613 {
1614 dbus_set_error (error,
1615 DBUS_ERROR_BAD_ADDRESS,
1616 "Unknown address family %s", family);
1617 return -1;
1618 }
1619
1620 hints.ai_protocol = IPPROTO_TCP;
1621 hints.ai_socktype = SOCK_STREAM;
1622 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1623
1624 redo_lookup_with_port:
1625 ai = NULL;
1626 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1627 {
1628 dbus_set_error (error,
1629 _dbus_error_from_gai (res, errno),
1630 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1631 host ? host : "*", port, gai_strerror(res), res);
1632 goto failed;
1633 }
1634
1635 tmp = ai;
1636 while (tmp)
1637 {
1638 int fd = -1, tcp_nodelay_on;
1639 DBusSocket *newlisten_fd;
1640
1641 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1642 {
1643 _DBUS_ASSERT_ERROR_IS_SET(error);
1644 goto failed;
1645 }
1646 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1647
1648 reuseaddr = 1;
1649 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1650 {
1651 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1652 host ? host : "*", port, _dbus_strerror (errno));
1653 }
1654
1655 /* Nagle's algorithm imposes a huge delay on the initial messages
1656 going over TCP. */
1657 tcp_nodelay_on = 1;
1658 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1659 {
1660 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1661 host ? host : "*", port, _dbus_strerror (errno));
1662 }
1663
1664 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1665 {
1666 saved_errno = errno;
1667 _dbus_close(fd, NULL);
1668
1669 /*
1670 * We don't treat this as a fatal error, because there might be
1671 * other addresses that we can listen on. In particular:
1672 *
1673 * - If saved_errno is EADDRINUSE after we
1674 * "goto redo_lookup_with_port" after binding a port on one of the
1675 * possible addresses, we will try to bind that same port on
1676 * every address, including the same address again for a second
1677 * time, which will fail with EADDRINUSE.
1678 *
1679 * - If saved_errno is EADDRINUSE, it might be because binding to
1680 * an IPv6 address implicitly binds to a corresponding IPv4
1681 * address or vice versa (e.g. Linux with bindv6only=0).
1682 *
1683 * - If saved_errno is EADDRNOTAVAIL when we asked for family
1684 * AF_UNSPEC, it might be because IPv6 is disabled for this
1685 * particular interface (e.g. Linux with
1686 * /proc/sys/net/ipv6/conf/lo/disable_ipv6).
1687 */
1688 bind_error = dbus_new0 (DBusError, 1);
1689
1690 if (bind_error == NULL)
1691 {
1692 _DBUS_SET_OOM (error);
1693 goto failed;
1694 }
1695
1696 dbus_error_init (bind_error);
1697 _dbus_set_error_with_inet_sockaddr (bind_error, tmp->ai_addr, tmp->ai_addrlen,
1698 "Failed to bind socket",
1699 saved_errno);
1700
1701 if (!_dbus_list_append (&bind_errors, bind_error))
1702 {
1703 dbus_error_free (bind_error);
1704 dbus_free (bind_error);
1705 _DBUS_SET_OOM (error);
1706 goto failed;
1707 }
1708
1709 /* Try the next address, maybe it will work better */
1710 tmp = tmp->ai_next;
1711 continue;
1712 }
1713
1714 if (listen (fd, 30 /* backlog */) < 0)
1715 {
1716 saved_errno = errno;
1717 _dbus_close (fd, NULL);
1718 _dbus_set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen,
1719 "Failed to listen on socket",
1720 saved_errno);
1721 goto failed;
1722 }
1723
1724 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1725 if (!newlisten_fd)
1726 {
1727 _dbus_close (fd, NULL);
1728 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1729 "Failed to allocate file handle array");
1730 goto failed;
1731 }
1732 listen_fd = newlisten_fd;
1733 listen_fd[nlisten_fd].fd = fd;
1734 nlisten_fd++;
1735
1736 if (tmp->ai_addr->sa_family == AF_INET)
1737 have_ipv4 = TRUE;
1738 else if (tmp->ai_addr->sa_family == AF_INET6)
1739 have_ipv6 = TRUE;
1740
1741 if (!_dbus_string_get_length(retport))
1742 {
1743 /* If the user didn't specify a port, or used 0, then
1744 the kernel chooses a port. After the first address
1745 is bound to, we need to force all remaining addresses
1746 to use the same port */
1747 if (!port || !strcmp(port, "0"))
1748 {
1749 int result;
1750 struct sockaddr_storage addr;
1751 socklen_t addrlen;
1752 char portbuf[50];
1753
1754 addrlen = sizeof(addr);
1755 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1756
1757 if (result == -1)
1758 {
1759 saved_errno = errno;
1760 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1761 "Failed to retrieve socket name for \"%s:%s\": %s",
1762 host ? host : "*", port, _dbus_strerror (saved_errno));
1763 goto failed;
1764 }
1765
1766 if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1767 portbuf, sizeof(portbuf),
1768 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1769 {
1770 saved_errno = errno;
1771 dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
1772 "Failed to resolve port \"%s:%s\": %s (%d)",
1773 host ? host : "*", port, gai_strerror(res), res);
1774 goto failed;
1775 }
1776
1777 if (!_dbus_string_append(retport, portbuf))
1778 {
1779 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1780 goto failed;
1781 }
1782
1783 /* Release current address list & redo lookup */
1784 port = _dbus_string_get_const_data(retport);
1785 freeaddrinfo(ai);
1786 goto redo_lookup_with_port;
1787 }
1788 else
1789 {
1790 if (!_dbus_string_append(retport, port))
1791 {
1792 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1793 goto failed;
1794 }
1795 }
1796 }
1797
1798 tmp = tmp->ai_next;
1799 }
1800 freeaddrinfo(ai);
1801 ai = NULL;
1802
1803 if (!nlisten_fd)
1804 {
1805 _dbus_combine_tcp_errors (&bind_errors, "Failed to bind", host,
1806 port, error);
1807 goto failed;
1808 }
1809
1810 if (have_ipv4 && !have_ipv6)
1811 *retfamily = "ipv4";
1812 else if (!have_ipv4 && have_ipv6)
1813 *retfamily = "ipv6";
1814
1815 for (i = 0 ; i < nlisten_fd ; i++)
1816 {
1817 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1818 {
1819 goto failed;
1820 }
1821 }
1822
1823 *fds_p = listen_fd;
1824
1825 /* This list might be non-empty even on success, because we might be
1826 * ignoring EADDRINUSE or EADDRNOTAVAIL */
1827 while ((bind_error = _dbus_list_pop_first (&bind_errors)))
1828 {
1829 dbus_error_free (bind_error);
1830 dbus_free (bind_error);
1831 }
1832
1833 return nlisten_fd;
1834
1835 failed:
1836 if (ai)
1837 freeaddrinfo(ai);
1838 for (i = 0 ; i < nlisten_fd ; i++)
1839 _dbus_close(listen_fd[i].fd, NULL);
1840
1841 while ((bind_error = _dbus_list_pop_first (&bind_errors)))
1842 {
1843 dbus_error_free (bind_error);
1844 dbus_free (bind_error);
1845 }
1846
1847 dbus_free(listen_fd);
1848 return -1;
1849 }
1850
1851 static dbus_bool_t
1852 write_credentials_byte (int server_fd,
1853 DBusError *error)
1854 {
1855 int bytes_written;
1856 char buf[1] = { '\0' };
1857 #if defined(HAVE_CMSGCRED)
1858 union {
1859 struct cmsghdr hdr;
1860 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1861 } cmsg;
1862 struct iovec iov;
1863 struct msghdr msg;
1864 iov.iov_base = buf;
1865 iov.iov_len = 1;
1866
1867 _DBUS_ZERO(msg);
1868 msg.msg_iov = &iov;
1869 msg.msg_iovlen = 1;
1870
1871 msg.msg_control = (caddr_t) &cmsg;
1872 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1873 _DBUS_ZERO(cmsg);
1874 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1875 cmsg.hdr.cmsg_level = SOL_SOCKET;
1876 cmsg.hdr.cmsg_type = SCM_CREDS;
1877 #endif
1878
1879 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1880
1881 again:
1882
1883 #if defined(HAVE_CMSGCRED)
1884 bytes_written = sendmsg (server_fd, &msg, 0
1885 #if HAVE_DECL_MSG_NOSIGNAL
1886 |MSG_NOSIGNAL
1887 #endif
1888 );
1889
1890 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1891 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1892 * only allows that on AF_UNIX. Try just doing a send() instead. */
1893 if (bytes_written < 0 && errno == EINVAL)
1894 #endif
1895 {
1896 bytes_written = send (server_fd, buf, 1, 0
1897 #if HAVE_DECL_MSG_NOSIGNAL
1898 |MSG_NOSIGNAL
1899 #endif
1900 );
1901 }
1902
1903 if (bytes_written < 0 && errno == EINTR)
1904 goto again;
1905
1906 if (bytes_written < 0)
1907 {
1908 dbus_set_error (error, _dbus_error_from_errno (errno),
1909 "Failed to write credentials byte: %s",
1910 _dbus_strerror (errno));
1911 return FALSE;
1912 }
1913 else if (bytes_written == 0)
1914 {
1915 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1916 "wrote zero bytes writing credentials byte");
1917 return FALSE;
1918 }
1919 else
1920 {
1921 _dbus_assert (bytes_written == 1);
1922 _dbus_verbose ("wrote credentials byte\n");
1923 return TRUE;
1924 }
1925 }
1926
1927 /* return FALSE on OOM, TRUE otherwise, even if no groups were found */
1928 static dbus_bool_t
1929 add_groups_to_credentials (int client_fd,
1930 DBusCredentials *credentials,
1931 dbus_gid_t primary)
1932 {
1933 #if defined(__linux__) && defined(SO_PEERGROUPS)
1934 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1935 gid_t *buf = NULL;
1936 socklen_t len = 1024;
1937 dbus_bool_t oom = FALSE;
1938 /* libdbus has a different representation of group IDs just to annoy you */
1939 dbus_gid_t *converted_gids = NULL;
1940 dbus_bool_t need_primary = TRUE;
1941 size_t n_gids;
1942 size_t i;
1943
1944 n_gids = ((size_t) len) / sizeof (gid_t);
1945 buf = dbus_new (gid_t, n_gids);
1946
1947 if (buf == NULL)
1948 return FALSE;
1949
1950 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERGROUPS, buf, &len) < 0)
1951 {
1952 int e = errno;
1953 gid_t *replacement;
1954
1955 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1956 _dbus_strerror (e), (unsigned long) len);
1957
1958 if (e != ERANGE || (size_t) len <= n_gids * sizeof (gid_t))
1959 {
1960 _dbus_verbose ("Failed to getsockopt(SO_PEERGROUPS): %s\n",
1961 _dbus_strerror (e));
1962 goto out;
1963 }
1964
1965 /* If not enough space, len is updated to be enough.
1966 * Try again with a large enough buffer. */
1967 n_gids = ((size_t) len) / sizeof (gid_t);
1968 replacement = dbus_realloc (buf, len);
1969
1970 if (replacement == NULL)
1971 {
1972 oom = TRUE;
1973 goto out;
1974 }
1975
1976 buf = replacement;
1977 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1978 }
1979
1980 if (len <= 0)
1981 {
1982 _dbus_verbose ("getsockopt(SO_PEERGROUPS) yielded <= 0 bytes: %ld\n",
1983 (long) len);
1984 goto out;
1985 }
1986
1987 if (len > n_gids * sizeof (gid_t))
1988 {
1989 _dbus_verbose ("%lu > %zu", (unsigned long) len, n_gids * sizeof (gid_t));
1990 _dbus_assert_not_reached ("getsockopt(SO_PEERGROUPS) overflowed");
1991 }
1992
1993 if (len % sizeof (gid_t) != 0)
1994 {
1995 _dbus_verbose ("getsockopt(SO_PEERGROUPS) did not return an "
1996 "integer multiple of sizeof(gid_t): %lu should be "
1997 "divisible by %zu",
1998 (unsigned long) len, sizeof (gid_t));
1999 goto out;
2000 }
2001
2002 /* Allocate an extra space for the primary group ID */
2003 n_gids = ((size_t) len) / sizeof (gid_t);
2004
2005 /* If n_gids is less than this, then (n_gids + 1) certainly doesn't
2006 * overflow, and neither does multiplying that by sizeof(dbus_gid_t).
2007 * This is using _DBUS_INT32_MAX as a conservative lower bound for
2008 * the maximum size_t. */
2009 if (n_gids >= (_DBUS_INT32_MAX / sizeof (dbus_gid_t)) - 1)
2010 {
2011 _dbus_verbose ("getsockopt(SO_PEERGROUPS) returned a huge number "
2012 "of groups (%lu bytes), ignoring",
2013 (unsigned long) len);
2014 goto out;
2015 }
2016
2017 converted_gids = dbus_new (dbus_gid_t, n_gids + 1);
2018
2019 if (converted_gids == NULL)
2020 {
2021 oom = TRUE;
2022 goto out;
2023 }
2024
2025 for (i = 0; i < n_gids; i++)
2026 {
2027 converted_gids[i] = (dbus_gid_t) buf[i];
2028
2029 if (converted_gids[i] == primary)
2030 need_primary = FALSE;
2031 }
2032
2033 if (need_primary && primary != DBUS_GID_UNSET)
2034 {
2035 converted_gids[n_gids] = primary;
2036 n_gids++;
2037 }
2038
2039 _dbus_credentials_take_unix_gids (credentials, converted_gids, n_gids);
2040
2041 out:
2042 dbus_free (buf);
2043 return !oom;
2044 #else
2045 /* no error */
2046 return TRUE;
2047 #endif
2048 }
2049
2050 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
2051 static dbus_bool_t
2052 add_linux_security_label_to_credentials (int client_fd,
2053 DBusCredentials *credentials)
2054 {
2055 #if defined(__linux__) && defined(SO_PEERSEC)
2056 DBusString buf;
2057 socklen_t len = 1024;
2058 dbus_bool_t oom = FALSE;
2059
2060 if (!_dbus_string_init_preallocated (&buf, len) ||
2061 !_dbus_string_set_length (&buf, len))
2062 return FALSE;
2063
2064 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
2065 _dbus_string_get_data (&buf), &len) < 0)
2066 {
2067 int e = errno;
2068
2069 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
2070 _dbus_strerror (e), (unsigned long) len);
2071
2072 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
2073 {
2074 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
2075 _dbus_strerror (e));
2076 goto out;
2077 }
2078
2079 /* If not enough space, len is updated to be enough.
2080 * Try again with a large enough buffer. */
2081 if (!_dbus_string_set_length (&buf, len))
2082 {
2083 oom = TRUE;
2084 goto out;
2085 }
2086
2087 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
2088 }
2089
2090 if (len <= 0)
2091 {
2092 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
2093 (unsigned long) len);
2094 goto out;
2095 }
2096
2097 if (len > _dbus_string_get_length_uint (&buf))
2098 {
2099 _dbus_verbose ("%lu > %u", (unsigned long) len,
2100 _dbus_string_get_length_uint (&buf));
2101 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
2102 }
2103
2104 if (_dbus_string_get_byte (&buf, len - 1) == 0)
2105 {
2106 /* the kernel included the trailing \0 in its count,
2107 * but DBusString always has an extra \0 after the data anyway */
2108 _dbus_verbose ("subtracting trailing \\0\n");
2109 len--;
2110 }
2111
2112 if (!_dbus_string_set_length (&buf, len))
2113 {
2114 _dbus_assert_not_reached ("shortening string should not lead to OOM");
2115 oom = TRUE;
2116 goto out;
2117 }
2118
2119 if (strlen (_dbus_string_get_const_data (&buf)) != len)
2120 {
2121 /* LSM people on the linux-security-module@ mailing list say this
2122 * should never happen: the label should be a bytestring with
2123 * an optional trailing \0 */
2124 _dbus_verbose ("security label from kernel had an embedded \\0, "
2125 "ignoring it\n");
2126 goto out;
2127 }
2128
2129 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
2130 (unsigned long) len,
2131 _dbus_string_get_const_data (&buf));
2132
2133 if (!_dbus_credentials_add_linux_security_label (credentials,
2134 _dbus_string_get_const_data (&buf)))
2135 {
2136 oom = TRUE;
2137 goto out;
2138 }
2139
2140 out:
2141 _dbus_string_free (&buf);
2142 return !oom;
2143 #else
2144 /* no error */
2145 return TRUE;
2146 #endif
2147 }
2148
2189 dbus_bool_t
2190 _dbus_read_credentials_socket (DBusSocket client_fd,
2191 DBusCredentials *credentials,
2192 DBusError *error)
2193 {
2194 struct msghdr msg;
2195 struct iovec iov;
2196 char buf;
2197 dbus_uid_t uid_read;
2198 dbus_gid_t primary_gid_read;
2199 dbus_pid_t pid_read;
2200 int bytes_read;
2201
2202 #ifdef HAVE_CMSGCRED
2203 union {
2204 struct cmsghdr hdr;
2205 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
2206 } cmsg;
2207 #endif
2208
2209 /* The POSIX spec certainly doesn't promise this, but
2210 * we need these assertions to fail as soon as we're wrong about
2211 * it so we can do the porting fixups
2212 */
2213 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2214 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2215 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2216
2217 uid_read = DBUS_UID_UNSET;
2218 primary_gid_read = DBUS_GID_UNSET;
2219 pid_read = DBUS_PID_UNSET;
2220
2221 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2222
2223 _dbus_credentials_clear (credentials);
2224
2225 iov.iov_base = &buf;
2226 iov.iov_len = 1;
2227
2228 _DBUS_ZERO(msg);
2229 msg.msg_iov = &iov;
2230 msg.msg_iovlen = 1;
2231
2232 #if defined(HAVE_CMSGCRED)
2233 _DBUS_ZERO(cmsg);
2234 msg.msg_control = (caddr_t) &cmsg;
2235 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
2236 #endif
2237
2238 again:
2239 bytes_read = recvmsg (client_fd.fd, &msg, 0);
2240
2241 if (bytes_read < 0)
2242 {
2243 if (errno == EINTR)
2244 goto again;
2245
2246 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
2247 * normally only call read_credentials if the socket was ready
2248 * for reading
2249 */
2250
2251 dbus_set_error (error, _dbus_error_from_errno (errno),
2252 "Failed to read credentials byte: %s",
2253 _dbus_strerror (errno));
2254 return FALSE;
2255 }
2256 else if (bytes_read == 0)
2257 {
2258 /* this should not happen unless we are using recvmsg wrong,
2259 * so is essentially here for paranoia
2260 */
2261 dbus_set_error (error, DBUS_ERROR_FAILED,
2262 "Failed to read credentials byte (zero-length read)");
2263 return FALSE;
2264 }
2265 else if (buf != '\0')
2266 {
2267 dbus_set_error (error, DBUS_ERROR_FAILED,
2268 "Credentials byte was not nul");
2269 return FALSE;
2270 }
2271
2272 _dbus_verbose ("read credentials byte\n");
2273
2274 {
2275 #ifdef SO_PEERCRED
2276 /* Supported by at least Linux and OpenBSD, with minor differences.
2277 *
2278 * This mechanism passes the process ID through and does not require
2279 * the peer's cooperation, so we prefer it over all others. Notably,
2280 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
2281 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
2282 * because this is much less fragile.
2283 */
2284 #ifdef __OpenBSD__
2285 struct sockpeercred cr;
2286 #else
2287 struct ucred cr;
2288 #endif
2289 socklen_t cr_len = sizeof (cr);
2290
2291 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
2292 {
2293 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
2294 _dbus_strerror (errno));
2295 }
2296 else if (cr_len != sizeof (cr))
2297 {
2298 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2299 cr_len, (int) sizeof (cr));
2300 }
2301 else
2302 {
2303 pid_read = cr.pid;
2304 uid_read = cr.uid;
2305 #ifdef __linux__
2306 /* Do other platforms have cr.gid? (Not that it really matters,
2307 * because the gid is useless to us unless we know the complete
2308 * group vector, which we only know on Linux.) */
2309 primary_gid_read = cr.gid;
2310 #endif
2311 }
2312 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2313 /* Another variant of the above - used on NetBSD
2314 */
2315 struct unpcbid cr;
2316 socklen_t cr_len = sizeof (cr);
2317
2318 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2319 {
2320 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2321 _dbus_strerror (errno));
2322 }
2323 else if (cr_len != sizeof (cr))
2324 {
2325 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2326 cr_len, (int) sizeof (cr));
2327 }
2328 else
2329 {
2330 pid_read = cr.unp_pid;
2331 uid_read = cr.unp_euid;
2332 }
2333 #elif defined(HAVE_CMSGCRED)
2334 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2335 * presence of that struct implies SCM_CREDS. Supported by at least
2336 * FreeBSD and DragonflyBSD.
2337 *
2338 * This mechanism requires the peer to help us (it has to send us a
2339 * SCM_CREDS message) but it does pass the process ID through,
2340 * which makes it better than getpeereid().
2341 */
2342 struct cmsgcred *cred;
2343 struct cmsghdr *cmsgp;
2344
2345 for (cmsgp = CMSG_FIRSTHDR (&msg);
2346 cmsgp != NULL;
2347 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2348 {
2349 if (cmsgp->cmsg_type == SCM_CREDS &&
2350 cmsgp->cmsg_level == SOL_SOCKET &&
2351 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2352 {
2353 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2354 pid_read = cred->cmcred_pid;
2355 uid_read = cred->cmcred_euid;
2356 break;
2357 }
2358 }
2359
2360 #elif defined(HAVE_GETPEERUCRED)
2361 /* Supported in at least Solaris >= 10. It should probably be higher
2362 * up this list, because it carries the pid and we use this code path
2363 * for audit data. */
2364 ucred_t * ucred = NULL;
2365 if (getpeerucred (client_fd.fd, &ucred) == 0)
2366 {
2367 #ifdef HAVE_ADT
2368 adt_session_data_t *adth = NULL;
2369 #endif
2370 pid_read = ucred_getpid (ucred);
2371 uid_read = ucred_geteuid (ucred);
2372 #ifdef HAVE_ADT
2373 /* generate audit session data based on socket ucred */
2374 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2375 {
2376 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2377 }
2378 else
2379 {
2380 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2381 {
2382 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2383 }
2384 else
2385 {
2386 adt_export_data_t *data = NULL;
2387 size_t size = adt_export_session_data (adth, &data);
2388 if (size <= 0)
2389 {
2390 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2391 }
2392 else
2393 {
2394 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2395 free (data);
2396 }
2397 }
2398 (void) adt_end_session (adth);
2399 }
2400 #endif /* HAVE_ADT */
2401 }
2402 else
2403 {
2404 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2405 }
2406 if (ucred != NULL)
2407 ucred_free (ucred);
2408
2409 /* ----------------------------------------------------------------
2410 * When adding new mechanisms, please add them above this point
2411 * if they support passing the process ID through, or below if not.
2412 * ---------------------------------------------------------------- */
2413
2414 #elif defined(HAVE_GETPEEREID)
2415 /* getpeereid() originates from D.J. Bernstein and is fairly
2416 * widely-supported. According to a web search, it might be present in
2417 * any/all of:
2418 *
2419 * - AIX?
2420 * - Blackberry?
2421 * - Cygwin
2422 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2423 * - Mac OS X
2424 * - Minix 3.1.8+
2425 * - MirBSD?
2426 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2427 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2428 * - QNX?
2429 */
2430 uid_t euid;
2431 gid_t egid;
2432 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2433 {
2434 uid_read = euid;
2435 }
2436 else
2437 {
2438 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2439 }
2440 #else /* no supported mechanism */
2441
2442 #warning Socket credentials not supported on this Unix OS
2443 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2444
2445 /* Please add other operating systems known to support at least one of
2446 * the mechanisms above to this list, keeping alphabetical order.
2447 * Everything not in this list is best-effort.
2448 */
2449 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2450 defined(__linux__) || \
2451 defined(__OpenBSD__) || \
2452 defined(__NetBSD__)
2453 # error Credentials passing not working on this OS is a regression!
2454 #endif
2455
2456 _dbus_verbose ("Socket credentials not supported on this OS\n");
2457 #endif
2458 }
2459
2460 _dbus_verbose ("Credentials:"
2461 " pid "DBUS_PID_FORMAT
2462 " uid "DBUS_UID_FORMAT
2463 "\n",
2464 pid_read,
2465 uid_read);
2466
2467 if (pid_read != DBUS_PID_UNSET)
2468 {
2469 if (!_dbus_credentials_add_pid (credentials, pid_read))
2470 {
2471 _DBUS_SET_OOM (error);
2472 return FALSE;
2473 }
2474 }
2475
2476 if (uid_read != DBUS_UID_UNSET)
2477 {
2478 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2479 {
2480 _DBUS_SET_OOM (error);
2481 return FALSE;
2482 }
2483 }
2484
2485 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2486 {
2487 _DBUS_SET_OOM (error);
2488 return FALSE;
2489 }
2490
2491 /* We don't put any groups in the credentials unless we can put them
2492 * all there. */
2493 if (!add_groups_to_credentials (client_fd.fd, credentials, primary_gid_read))
2494 {
2495 _DBUS_SET_OOM (error);
2496 return FALSE;
2497 }
2498
2499 return TRUE;
2500 }
2501
2519 dbus_bool_t
2520 _dbus_send_credentials_socket (DBusSocket server_fd,
2521 DBusError *error)
2522 {
2523 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2524
2525 if (write_credentials_byte (server_fd.fd, error))
2526 return TRUE;
2527 else
2528 return FALSE;
2529 }
2530
2540 DBusSocket
2541 _dbus_accept (DBusSocket listen_fd)
2542 {
2543 DBusSocket client_fd;
2544 struct sockaddr addr;
2545 socklen_t addrlen;
2546 #ifdef HAVE_ACCEPT4
2547 dbus_bool_t cloexec_done;
2548 #endif
2549
2550 addrlen = sizeof (addr);
2551
2552 retry:
2553
2554 #ifdef HAVE_ACCEPT4
2555 /*
2556 * At compile-time, we assume that if accept4() is available in
2557 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2558 * not necessarily true that either is supported by the running kernel.
2559 */
2560 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2561 cloexec_done = client_fd.fd >= 0;
2562
2563 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2564 #endif
2565 {
2566 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2567 }
2568
2569 if (client_fd.fd < 0)
2570 {
2571 if (errno == EINTR)
2572 goto retry;
2573 }
2574
2575 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2576
2577 #ifdef HAVE_ACCEPT4
2578 if (!cloexec_done)
2579 #endif
2580 {
2581 _dbus_fd_set_close_on_exec(client_fd.fd);
2582 }
2583
2584 return client_fd;
2585 }
2586
2595 dbus_bool_t
2596 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2597 {
2598 const char *directory;
2599 struct stat sb;
2600
2601 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2602
2603 directory = _dbus_string_get_const_data (dir);
2604
2605 if (stat (directory, &sb) < 0)
2606 {
2607 dbus_set_error (error, _dbus_error_from_errno (errno),
2608 "%s", _dbus_strerror (errno));
2609
2610 return FALSE;
2611 }
2612
2613 if (sb.st_uid != geteuid ())
2614 {
2615 dbus_set_error (error, DBUS_ERROR_FAILED,
2616 "%s directory is owned by user %lu, not %lu",
2617 directory,
2618 (unsigned long) sb.st_uid,
2619 (unsigned long) geteuid ());
2620 return FALSE;
2621 }
2622
2623 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2624 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2625 {
2626 dbus_set_error (error, DBUS_ERROR_FAILED,
2627 "%s directory is not private to the user", directory);
2628 return FALSE;
2629 }
2630
2631 return TRUE;
2632 }
2633
2634 static dbus_bool_t
2635 fill_user_info_from_passwd (struct passwd *p,
2636 DBusUserInfo *info,
2637 DBusError *error)
2638 {
2639 _dbus_assert (p->pw_name != NULL);
2640 _dbus_assert (p->pw_dir != NULL);
2641
2642 info->uid = p->pw_uid;
2643 info->primary_gid = p->pw_gid;
2644 info->username = _dbus_strdup (p->pw_name);
2645 info->homedir = _dbus_strdup (p->pw_dir);
2646
2647 if (info->username == NULL ||
2648 info->homedir == NULL)
2649 {
2650 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2651 return FALSE;
2652 }
2653
2654 return TRUE;
2655 }
2656
2657 static dbus_bool_t
2658 fill_user_info (DBusUserInfo *info,
2659 dbus_uid_t uid,
2660 const DBusString *username,
2661 DBusError *error)
2662 {
2663 const char *username_c;
2664
2665 /* exactly one of username/uid provided */
2666 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2667 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2668
2669 info->uid = DBUS_UID_UNSET;
2670 info->primary_gid = DBUS_GID_UNSET;
2671 info->group_ids = NULL;
2672 info->n_group_ids = 0;
2673 info->username = NULL;
2674 info->homedir = NULL;
2675
2676 if (username != NULL)
2677 username_c = _dbus_string_get_const_data (username);
2678 else
2679 username_c = NULL;
2680
2681 /* For now assuming that the getpwnam() and getpwuid() flavors
2682 * are always symmetrical, if not we have to add more configure
2683 * checks
2684 */
2685
2686 #ifdef HAVE_GETPWNAM_R
2687 {
2688 struct passwd *p;
2689 int result;
2690 size_t buflen;
2691 char *buf;
2692 struct passwd p_str;
2693
2694 /* retrieve maximum needed size for buf */
2695 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2696
2697 /* sysconf actually returns a long, but everything else expects size_t,
2698 * so just recast here.
2699 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2700 */
2701 if ((long) buflen <= 0)
2702 buflen = 1024;
2703
2704 result = -1;
2705 while (1)
2706 {
2707 buf = dbus_malloc (buflen);
2708 if (buf == NULL)
2709 {
2710 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2711 return FALSE;
2712 }
2713
2714 p = NULL;
2715 if (uid != DBUS_UID_UNSET)
2716 result = getpwuid_r (uid, &p_str, buf, buflen,
2717 &p);
2718 else
2719 result = getpwnam_r (username_c, &p_str, buf, buflen,
2720 &p);
2721 //Try a bigger buffer if ERANGE was returned
2722 if (result == ERANGE && buflen < 512 * 1024)
2723 {
2724 dbus_free (buf);
2725 buflen *= 2;
2726 }
2727 else
2728 {
2729 break;
2730 }
2731 }
2732 if (result == 0 && p == &p_str)
2733 {
2734 if (!fill_user_info_from_passwd (p, info, error))
2735 {
2736 dbus_free (buf);
2737 return FALSE;
2738 }
2739 dbus_free (buf);
2740 }
2741 else
2742 {
2743 dbus_set_error (error, _dbus_error_from_errno (errno),
2744 "User \"%s\" unknown or no memory to allocate password entry\n",
2745 username_c ? username_c : "???");
2746 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2747 dbus_free (buf);
2748 return FALSE;
2749 }
2750 }
2751 #else /* ! HAVE_GETPWNAM_R */
2752 {
2753 /* I guess we're screwed on thread safety here */
2754 struct passwd *p;
2755
2756 #warning getpwnam_r() not available, please report this to the dbus maintainers with details of your OS
2757
2758 if (uid != DBUS_UID_UNSET)
2759 p = getpwuid (uid);
2760 else
2761 p = getpwnam (username_c);
2762
2763 if (p != NULL)
2764 {
2765 if (!fill_user_info_from_passwd (p, info, error))
2766 {
2767 return FALSE;
2768 }
2769 }
2770 else
2771 {
2772 dbus_set_error (error, _dbus_error_from_errno (errno),
2773 "User \"%s\" unknown or no memory to allocate password entry\n",
2774 username_c ? username_c : "???");
2775 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2776 return FALSE;
2777 }
2778 }
2779 #endif /* ! HAVE_GETPWNAM_R */
2780
2781 /* Fill this in so we can use it to get groups */
2782 username_c = info->username;
2783
2784 #ifdef HAVE_GETGROUPLIST
2785 {
2786 gid_t *buf;
2787 int buf_count;
2788 int i;
2789 int initial_buf_count;
2790
2791 initial_buf_count = 17;
2792 buf_count = initial_buf_count;
2793 buf = dbus_new (gid_t, buf_count);
2794 if (buf == NULL)
2795 {
2796 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2797 goto failed;
2798 }
2799
2800 if (getgrouplist (username_c,
2801 info->primary_gid,
2802 buf, &buf_count) < 0)
2803 {
2804 gid_t *new;
2805 /* Presumed cause of negative return code: buf has insufficient
2806 entries to hold the entire group list. The Linux behavior in this
2807 case is to pass back the actual number of groups in buf_count, but
2808 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2809 So as a hack, try to help out a bit by guessing a larger
2810 number of groups, within reason.. might still fail, of course,
2811 but we can at least print a more informative message. I looked up
2812 the "right way" to do this by downloading Apple's own source code
2813 for the "id" command, and it turns out that they use an
2814 undocumented library function getgrouplist_2 (!) which is not
2815 declared in any header in /usr/include (!!). That did not seem
2816 like the way to go here.
2817 */
2818 if (buf_count == initial_buf_count)
2819 {
2820 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2821 }
2822 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2823 if (new == NULL)
2824 {
2825 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2826 dbus_free (buf);
2827 goto failed;
2828 }
2829
2830 buf = new;
2831
2832 errno = 0;
2833 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2834 {
2835 if (errno == 0)
2836 {
2837 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2838 username_c, buf_count, buf_count);
2839 }
2840 else
2841 {
2842 dbus_set_error (error,
2843 _dbus_error_from_errno (errno),
2844 "Failed to get groups for username \"%s\" primary GID "
2845 DBUS_GID_FORMAT ": %s\n",
2846 username_c, info->primary_gid,
2847 _dbus_strerror (errno));
2848 dbus_free (buf);
2849 goto failed;
2850 }
2851 }
2852 }
2853
2854 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2855 if (info->group_ids == NULL)
2856 {
2857 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2858 dbus_free (buf);
2859 goto failed;
2860 }
2861
2862 for (i = 0; i < buf_count; ++i)
2863 info->group_ids[i] = buf[i];
2864
2865 info->n_group_ids = buf_count;
2866
2867 dbus_free (buf);
2868 }
2869 #else /* HAVE_GETGROUPLIST */
2870 {
2871 /* We just get the one group ID */
2872 info->group_ids = dbus_new (dbus_gid_t, 1);
2873 if (info->group_ids == NULL)
2874 {
2875 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2876 goto failed;
2877 }
2878
2879 info->n_group_ids = 1;
2880
2881 (info->group_ids)[0] = info->primary_gid;
2882 }
2883 #endif /* HAVE_GETGROUPLIST */
2884
2885 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2886
2887 return TRUE;
2888
2889 failed:
2890 _DBUS_ASSERT_ERROR_IS_SET (error);
2891 return FALSE;
2892 }
2893
2902 dbus_bool_t
2903 _dbus_user_info_fill (DBusUserInfo *info,
2904 const DBusString *username,
2905 DBusError *error)
2906 {
2907 return fill_user_info (info, DBUS_UID_UNSET,
2908 username, error);
2909 }
2910
2919 dbus_bool_t
2920 _dbus_user_info_fill_uid (DBusUserInfo *info,
2921 dbus_uid_t uid,
2922 DBusError *error)
2923 {
2924 return fill_user_info (info, uid,
2925 NULL, error);
2926 }
2927
2941 dbus_bool_t
2942 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2943 {
2944 /* The POSIX spec certainly doesn't promise this, but
2945 * we need these assertions to fail as soon as we're wrong about
2946 * it so we can do the porting fixups
2947 */
2948 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2949 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2950 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2951
2952 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2953 return FALSE;
2954 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2955 return FALSE;
2956
2957 return TRUE;
2958 }
2959
2971 dbus_bool_t
2972 _dbus_append_user_from_current_process (DBusString *str)
2973 {
2974 return _dbus_string_append_uint (str,
2975 _dbus_geteuid ());
2976 }
2977
2982 dbus_pid_t
2983 _dbus_getpid (void)
2984 {
2985 return getpid ();
2986 }
2987
2991 dbus_uid_t
2992 _dbus_getuid (void)
2993 {
2994 return getuid ();
2995 }
2996
3000 dbus_uid_t
3001 _dbus_geteuid (void)
3002 {
3003 return geteuid ();
3004 }
3005
3012 unsigned long
3013 _dbus_pid_for_log (void)
3014 {
3015 return getpid ();
3016 }
3017
3018 #if !DBUS_USE_SYNC
3019 /* To be thread-safe by default on platforms that don't necessarily have
3020 * atomic operations (notably Debian armel, which is armv4t), we must
3021 * use a mutex that can be initialized statically, like this.
3022 * GLib >= 2.32 uses a similar system.
3023 */
3024 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
3025 #endif
3026
3033 dbus_int32_t
3034 _dbus_atomic_inc (DBusAtomic *atomic)
3035 {
3036 #if DBUS_USE_SYNC
3037 return __sync_add_and_fetch(&atomic->value, 1)-1;
3038 #else
3039 dbus_int32_t res;
3040
3041 pthread_mutex_lock (&atomic_mutex);
3042 res = atomic->value;
3043 atomic->value += 1;
3044 pthread_mutex_unlock (&atomic_mutex);
3045
3046 return res;
3047 #endif
3048 }
3049
3056 dbus_int32_t
3057 _dbus_atomic_dec (DBusAtomic *atomic)
3058 {
3059 #if DBUS_USE_SYNC
3060 return __sync_sub_and_fetch(&atomic->value, 1)+1;
3061 #else
3062 dbus_int32_t res;
3063
3064 pthread_mutex_lock (&atomic_mutex);
3065 res = atomic->value;
3066 atomic->value -= 1;
3067 pthread_mutex_unlock (&atomic_mutex);
3068
3069 return res;
3070 #endif
3071 }
3072
3080 dbus_int32_t
3081 _dbus_atomic_get (DBusAtomic *atomic)
3082 {
3083 #if DBUS_USE_SYNC
3084 __sync_synchronize ();
3085 return atomic->value;
3086 #else
3087 dbus_int32_t res;
3088
3089 pthread_mutex_lock (&atomic_mutex);
3090 res = atomic->value;
3091 pthread_mutex_unlock (&atomic_mutex);
3092
3093 return res;
3094 #endif
3095 }
3096
3102 void
3103 _dbus_atomic_set_zero (DBusAtomic *atomic)
3104 {
3105 #if DBUS_USE_SYNC
3106 /* Atomic version of "*atomic &= 0; return *atomic" */
3107 __sync_and_and_fetch (&atomic->value, 0);
3108 #else
3109 pthread_mutex_lock (&atomic_mutex);
3110 atomic->value = 0;
3111 pthread_mutex_unlock (&atomic_mutex);
3112 #endif
3113 }
3114
3120 void
3121 _dbus_atomic_set_nonzero (DBusAtomic *atomic)
3122 {
3123 #if DBUS_USE_SYNC
3124 /* Atomic version of "*atomic |= 1; return *atomic" */
3125 __sync_or_and_fetch (&atomic->value, 1);
3126 #else
3127 pthread_mutex_lock (&atomic_mutex);
3128 atomic->value = 1;
3129 pthread_mutex_unlock (&atomic_mutex);
3130 #endif
3131 }
3132
3141 int
3142 _dbus_poll (DBusPollFD *fds,
3143 int n_fds,
3144 int timeout_milliseconds)
3145 {
3146 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
3147 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
3148 if (timeout_milliseconds < -1)
3149 {
3150 timeout_milliseconds = -1;
3151 }
3152
3153 return poll (fds,
3154 n_fds,
3155 timeout_milliseconds);
3156 #else /* ! HAVE_POLL */
3157 /* Emulate poll() in terms of select() */
3158 fd_set read_set, write_set, err_set;
3159 int max_fd = 0;
3160 int i;
3161 struct timeval tv;
3162 int ready;
3163
3164 FD_ZERO (&read_set);
3165 FD_ZERO (&write_set);
3166 FD_ZERO (&err_set);
3167
3168 for (i = 0; i < n_fds; i++)
3169 {
3170 DBusPollFD *fdp = &fds[i];
3171
3172 if (fdp->events & _DBUS_POLLIN)
3173 FD_SET (fdp->fd, &read_set);
3174
3175 if (fdp->events & _DBUS_POLLOUT)
3176 FD_SET (fdp->fd, &write_set);
3177
3178 FD_SET (fdp->fd, &err_set);
3179
3180 max_fd = MAX (max_fd, fdp->fd);
3181 }
3182
3183 tv.tv_sec = timeout_milliseconds / 1000;
3184 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
3185
3186 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
3187 timeout_milliseconds < 0 ? NULL : &tv);
3188
3189 if (ready > 0)
3190 {
3191 for (i = 0; i < n_fds; i++)
3192 {
3193 DBusPollFD *fdp = &fds[i];
3194
3195 fdp->revents = 0;
3196
3197 if (FD_ISSET (fdp->fd, &read_set))
3198 fdp->revents |= _DBUS_POLLIN;
3199
3200 if (FD_ISSET (fdp->fd, &write_set))
3201 fdp->revents |= _DBUS_POLLOUT;
3202
3203 if (FD_ISSET (fdp->fd, &err_set))
3204 fdp->revents |= _DBUS_POLLERR;
3205 }
3206 }
3207
3208 return ready;
3209 #endif
3210 }
3211
3219 void
3220 _dbus_get_monotonic_time (long *tv_sec,
3221 long *tv_usec)
3222 {
3223 #ifdef HAVE_MONOTONIC_CLOCK
3224 struct timespec ts;
3225 clock_gettime (CLOCK_MONOTONIC, &ts);
3226
3227 if (tv_sec)
3228 *tv_sec = ts.tv_sec;
3229 if (tv_usec)
3230 *tv_usec = ts.tv_nsec / 1000;
3231 #else
3232 struct timeval t;
3233
3234 gettimeofday (&t, NULL);
3235
3236 if (tv_sec)
3237 *tv_sec = t.tv_sec;
3238 if (tv_usec)
3239 *tv_usec = t.tv_usec;
3240 #endif
3241 }
3242
3250 void
3251 _dbus_get_real_time (long *tv_sec,
3252 long *tv_usec)
3253 {
3254 struct timeval t;
3255
3256 gettimeofday (&t, NULL);
3257
3258 if (tv_sec)
3259 *tv_sec = t.tv_sec;
3260 if (tv_usec)
3261 *tv_usec = t.tv_usec;
3262 }
3263
3272 dbus_bool_t
3273 _dbus_ensure_directory (const DBusString *filename,
3274 DBusError *error)
3275 {
3276 const char *filename_c;
3277
3278 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3279
3280 filename_c = _dbus_string_get_const_data (filename);
3281
3282 if (mkdir (filename_c, 0700) < 0)
3283 {
3284 if (errno == EEXIST)
3285 return TRUE;
3286
3287 dbus_set_error (error, DBUS_ERROR_FAILED,
3288 "Failed to create directory %s: %s\n",
3289 filename_c, _dbus_strerror (errno));
3290 return FALSE;
3291 }
3292 else
3293 return TRUE;
3294 }
3295
3304 dbus_bool_t
3305 _dbus_create_directory (const DBusString *filename,
3306 DBusError *error)
3307 {
3308 const char *filename_c;
3309
3310 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3311
3312 filename_c = _dbus_string_get_const_data (filename);
3313
3314 if (mkdir (filename_c, 0700) < 0)
3315 {
3316 dbus_set_error (error, DBUS_ERROR_FAILED,
3317 "Failed to create directory %s: %s\n",
3318 filename_c, _dbus_strerror (errno));
3319 return FALSE;
3320 }
3321 else
3322 return TRUE;
3323 }
3324
3335 dbus_bool_t
3336 _dbus_concat_dir_and_file (DBusString *dir,
3337 const DBusString *next_component)
3338 {
3339 dbus_bool_t dir_ends_in_slash;
3340 dbus_bool_t file_starts_with_slash;
3341
3342 if (_dbus_string_get_length (dir) == 0 ||
3343 _dbus_string_get_length (next_component) == 0)
3344 return TRUE;
3345
3346 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3347 _dbus_string_get_length (dir) - 1);
3348
3349 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3350
3351 if (dir_ends_in_slash && file_starts_with_slash)
3352 {
3353 _dbus_string_shorten (dir, 1);
3354 }
3355 else if (!(dir_ends_in_slash || file_starts_with_slash))
3356 {
3357 if (!_dbus_string_append_byte (dir, '/'))
3358 return FALSE;
3359 }
3360
3361 return _dbus_string_copy (next_component, 0, dir,
3362 _dbus_string_get_length (dir));
3363 }
3364
3366 #define NANOSECONDS_PER_SECOND 1000000000
3367
3368 #define MICROSECONDS_PER_SECOND 1000000
3369
3370 #define MILLISECONDS_PER_SECOND 1000
3371
3372 #define NANOSECONDS_PER_MILLISECOND 1000000
3373
3374 #define MICROSECONDS_PER_MILLISECOND 1000
3375
3380 void
3381 _dbus_sleep_milliseconds (int milliseconds)
3382 {
3383 #ifdef HAVE_NANOSLEEP
3384 struct timespec req;
3385 struct timespec rem;
3386
3387 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3388 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3389 rem.tv_sec = 0;
3390 rem.tv_nsec = 0;
3391
3392 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3393 req = rem;
3394 #elif defined (HAVE_USLEEP)
3395 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3396 #else /* ! HAVE_USLEEP */
3397 sleep (MAX (milliseconds / 1000, 1));
3398 #endif
3399 }
3400
3410 dbus_bool_t
3411 _dbus_generate_random_bytes (DBusString *str,
3412 int n_bytes,
3413 DBusError *error)
3414 {
3415 int old_len = _dbus_string_get_length (str);
3416 int fd;
3417 int result;
3418 #ifdef HAVE_GETRANDOM
3419 char *buffer;
3420
3421 if (!_dbus_string_lengthen (str, n_bytes))
3422 {
3423 _DBUS_SET_OOM (error);
3424 return FALSE;
3425 }
3426
3427 buffer = _dbus_string_get_data_len (str, old_len, n_bytes);
3428 result = getrandom (buffer, n_bytes, GRND_NONBLOCK);
3429
3430 if (result == n_bytes)
3431 return TRUE;
3432
3433 _dbus_string_set_length (str, old_len);
3434 #endif
3435
3436 /* note, urandom on linux will fall back to pseudorandom */
3437 fd = open ("/dev/urandom", O_RDONLY);
3438
3439 if (fd < 0)
3440 {
3441 dbus_set_error (error, _dbus_error_from_errno (errno),
3442 "Could not open /dev/urandom: %s",
3443 _dbus_strerror (errno));
3444 return FALSE;
3445 }
3446
3447 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3448
3449 result = _dbus_read (fd, str, n_bytes);
3450
3451 if (result != n_bytes)
3452 {
3453 if (result < 0)
3454 dbus_set_error (error, _dbus_error_from_errno (errno),
3455 "Could not read /dev/urandom: %s",
3456 _dbus_strerror (errno));
3457 else
3458 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
3459 "Short read from /dev/urandom");
3460
3461 _dbus_close (fd, NULL);
3462 _dbus_string_set_length (str, old_len);
3463 return FALSE;
3464 }
3465
3466 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3467 n_bytes);
3468
3469 _dbus_close (fd, NULL);
3470
3471 return TRUE;
3472 }
3473
3479 void
3480 _dbus_exit (int code)
3481 {
3482 _exit (code);
3483 }
3484
3493 const char*
3494 _dbus_strerror (int error_number)
3495 {
3496 const char *msg;
3497
3498 msg = strerror (error_number);
3499 if (msg == NULL)
3500 msg = "unknown";
3501
3502 return msg;
3503 }
3504
3508 void
3509 _dbus_disable_sigpipe (void)
3510 {
3511 signal (SIGPIPE, SIG_IGN);
3512 }
3513
3521 void
3522 _dbus_fd_set_close_on_exec (int fd)
3523 {
3524 int val;
3525
3526 val = fcntl (fd, F_GETFD, 0);
3527
3528 if (val < 0)
3529 return;
3530
3531 val |= FD_CLOEXEC;
3532
3533 fcntl (fd, F_SETFD, val);
3534 }
3535
3543 void
3544 _dbus_fd_clear_close_on_exec (int fd)
3545 {
3546 int val;
3547
3548 val = fcntl (fd, F_GETFD, 0);
3549
3550 if (val < 0)
3551 return;
3552
3553 val &= ~FD_CLOEXEC;
3554
3555 fcntl (fd, F_SETFD, val);
3556 }
3557
3565 dbus_bool_t
3566 _dbus_close (int fd,
3567 DBusError *error)
3568 {
3569 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3570
3571 again:
3572 if (close (fd) < 0)
3573 {
3574 if (errno == EINTR)
3575 goto again;
3576
3577 dbus_set_error (error, _dbus_error_from_errno (errno),
3578 "Could not close fd %d", fd);
3579 return FALSE;
3580 }
3581
3582 return TRUE;
3583 }
3584
3593 int
3594 _dbus_dup(int fd,
3595 DBusError *error)
3596 {
3597 int new_fd;
3598
3599 #ifdef F_DUPFD_CLOEXEC
3600 dbus_bool_t cloexec_done;
3601
3602 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3603 cloexec_done = new_fd >= 0;
3604
3605 if (new_fd < 0 && errno == EINVAL)
3606 #endif
3607 {
3608 new_fd = fcntl(fd, F_DUPFD, 3);
3609 }
3610
3611 if (new_fd < 0) {
3612
3613 dbus_set_error (error, _dbus_error_from_errno (errno),
3614 "Could not duplicate fd %d", fd);
3615 return -1;
3616 }
3617
3618 #ifdef F_DUPFD_CLOEXEC
3619 if (!cloexec_done)
3620 #endif
3621 {
3622 _dbus_fd_set_close_on_exec(new_fd);
3623 }
3624
3625 return new_fd;
3626 }
3627
3635 dbus_bool_t
3636 _dbus_set_socket_nonblocking (DBusSocket fd,
3637 DBusError *error)
3638 {
3639 return _dbus_set_fd_nonblocking (fd.fd, error);
3640 }
3641
3642 static dbus_bool_t
3643 _dbus_set_fd_nonblocking (int fd,
3644 DBusError *error)
3645 {
3646 int val;
3647
3648 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3649
3650 val = fcntl (fd, F_GETFL, 0);
3651 if (val < 0)
3652 {
3653 dbus_set_error (error, _dbus_error_from_errno (errno),
3654 "Failed to get flags from file descriptor %d: %s",
3655 fd, _dbus_strerror (errno));
3656 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3657 _dbus_strerror (errno));
3658 return FALSE;
3659 }
3660
3661 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3662 {
3663 dbus_set_error (error, _dbus_error_from_errno (errno),
3664 "Failed to set nonblocking flag of file descriptor %d: %s",
3665 fd, _dbus_strerror (errno));
3666 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3667 fd, _dbus_strerror (errno));
3668
3669 return FALSE;
3670 }
3671
3672 return TRUE;
3673 }
3674
3680 void
3681 _dbus_print_backtrace (void)
3682 {
3683 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3684 void *bt[500];
3685 int bt_size;
3686 int i;
3687 char **syms;
3688
3689 bt_size = backtrace (bt, 500);
3690
3691 syms = backtrace_symbols (bt, bt_size);
3692
3693 i = 0;
3694 while (i < bt_size)
3695 {
3696 /* don't use dbus_warn since it can _dbus_abort() */
3697 fprintf (stderr, " %s\n", syms[i]);
3698 ++i;
3699 }
3700 fflush (stderr);
3701
3702 free (syms);
3703 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3704 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3705 #else
3706 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3707 #endif
3708 }
3709
3722 dbus_bool_t
3723 _dbus_socketpair (DBusSocket *fd1,
3724 DBusSocket *fd2,
3725 dbus_bool_t blocking,
3726 DBusError *error)
3727 {
3728 #ifdef HAVE_SOCKETPAIR
3729 int fds[2];
3730 int retval;
3731
3732 #ifdef SOCK_CLOEXEC
3733 dbus_bool_t cloexec_done;
3734
3735 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3736 cloexec_done = retval >= 0;
3737
3738 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3739 #endif
3740 {
3741 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3742 }
3743
3744 if (retval < 0)
3745 {
3746 dbus_set_error (error, _dbus_error_from_errno (errno),
3747 "Could not create full-duplex pipe");
3748 return FALSE;
3749 }
3750
3751 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3752
3753 #ifdef SOCK_CLOEXEC
3754 if (!cloexec_done)
3755 #endif
3756 {
3757 _dbus_fd_set_close_on_exec (fds[0]);
3758 _dbus_fd_set_close_on_exec (fds[1]);
3759 }
3760
3761 if (!blocking &&
3762 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3763 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3764 {
3765 dbus_set_error (error, _dbus_error_from_errno (errno),
3766 "Could not set full-duplex pipe nonblocking");
3767
3768 _dbus_close (fds[0], NULL);
3769 _dbus_close (fds[1], NULL);
3770
3771 return FALSE;
3772 }
3773
3774 fd1->fd = fds[0];
3775 fd2->fd = fds[1];
3776
3777 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3778 fd1->fd, fd2->fd);
3779
3780 return TRUE;
3781 #else
3782 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3783 dbus_set_error (error, DBUS_ERROR_FAILED,
3784 "_dbus_socketpair() not implemented on this OS");
3785 return FALSE;
3786 #endif
3787 }
3788
3797 int
3798 _dbus_printf_string_upper_bound (const char *format,
3799 va_list args)
3800 {
3801 char static_buf[1024];
3802 int bufsize = sizeof (static_buf);
3803 int len;
3804 va_list args_copy;
3805
3806 DBUS_VA_COPY (args_copy, args);
3807 len = vsnprintf (static_buf, bufsize, format, args_copy);
3808 va_end (args_copy);
3809
3810 /* If vsnprintf() returned non-negative, then either the string fits in
3811 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3812 * returns the number of characters that were needed, or this OS returns the
3813 * truncated length.
3814 *
3815 * We ignore the possibility that snprintf might just ignore the length and
3816 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3817 * If your libc is really that bad, come back when you have a better one. */
3818 if (len == bufsize)
3819 {
3820 /* This could be the truncated length (Tru64 and IRIX have this bug),
3821 * or the real length could be coincidentally the same. Which is it?
3822 * If vsnprintf returns the truncated length, we'll go to the slow
3823 * path. */
3824 DBUS_VA_COPY (args_copy, args);
3825
3826 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3827 len = -1;
3828
3829 va_end (args_copy);
3830 }
3831
3832 /* If vsnprintf() returned negative, we have to do more work.
3833 * HP-UX returns negative. */
3834 while (len < 0)
3835 {
3836 char *buf;
3837
3838 bufsize *= 2;
3839
3840 buf = dbus_malloc (bufsize);
3841
3842 if (buf == NULL)
3843 return -1;
3844
3845 DBUS_VA_COPY (args_copy, args);
3846 len = vsnprintf (buf, bufsize, format, args_copy);
3847 va_end (args_copy);
3848
3849 dbus_free (buf);
3850
3851 /* If the reported length is exactly the buffer size, round up to the
3852 * next size, in case vsnprintf has been returning the truncated
3853 * length */
3854 if (len == bufsize)
3855 len = -1;
3856 }
3857
3858 return len;
3859 }
3860
3867 const char*
3868 _dbus_get_tmpdir(void)
3869 {
3870 /* Protected by _DBUS_LOCK_sysdeps */
3871 static const char* tmpdir = NULL;
3872
3873 if (!_DBUS_LOCK (sysdeps))
3874 return NULL;
3875
3876 if (tmpdir == NULL)
3877 {
3878 /* TMPDIR is what glibc uses, then
3879 * glibc falls back to the P_tmpdir macro which
3880 * just expands to "/tmp"
3881 */
3882 if (tmpdir == NULL)
3883 tmpdir = getenv("TMPDIR");
3884
3885 /* These two env variables are probably
3886 * broken, but maybe some OS uses them?
3887 */
3888 if (tmpdir == NULL)
3889 tmpdir = getenv("TMP");
3890 if (tmpdir == NULL)
3891 tmpdir = getenv("TEMP");
3892
3893 /* And this is the sane fallback. */
3894 if (tmpdir == NULL)
3895 tmpdir = "/tmp";
3896 }
3897
3898 _DBUS_UNLOCK (sysdeps);
3899
3900 _dbus_assert(tmpdir != NULL);
3901
3902 return tmpdir;
3903 }
3904
3905 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3906
3925 static dbus_bool_t
3926 _read_subprocess_line_argv (const char *progpath,
3927 dbus_bool_t path_fallback,
3928 const char * const *argv,
3929 DBusString *result,
3930 DBusError *error)
3931 {
3932 int result_pipe[2] = { -1, -1 };
3933 int errors_pipe[2] = { -1, -1 };
3934 pid_t pid;
3935 int ret;
3936 int status;
3937 int orig_len;
3938
3939 dbus_bool_t retval;
3940 sigset_t new_set, old_set;
3941
3942 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3943 retval = FALSE;
3944
3945 /* We need to block any existing handlers for SIGCHLD temporarily; they
3946 * will cause waitpid() below to fail.
3947 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3948 */
3949 sigemptyset (&new_set);
3950 sigaddset (&new_set, SIGCHLD);
3951 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3952
3953 orig_len = _dbus_string_get_length (result);
3954
3955 #define READ_END 0
3956 #define WRITE_END 1
3957 if (pipe (result_pipe) < 0)
3958 {
3959 dbus_set_error (error, _dbus_error_from_errno (errno),
3960 "Failed to create a pipe to call %s: %s",
3961 progpath, _dbus_strerror (errno));
3962 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3963 progpath, _dbus_strerror (errno));
3964 goto out;
3965 }
3966 if (pipe (errors_pipe) < 0)
3967 {
3968 dbus_set_error (error, _dbus_error_from_errno (errno),
3969 "Failed to create a pipe to call %s: %s",
3970 progpath, _dbus_strerror (errno));
3971 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3972 progpath, _dbus_strerror (errno));
3973 goto out;
3974 }
3975
3976 /* Make sure our output buffers aren't redundantly printed by both the
3977 * parent and the child */
3978 fflush (stdout);
3979 fflush (stderr);
3980
3981 pid = fork ();
3982 if (pid < 0)
3983 {
3984 dbus_set_error (error, _dbus_error_from_errno (errno),
3985 "Failed to fork() to call %s: %s",
3986 progpath, _dbus_strerror (errno));
3987 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3988 progpath, _dbus_strerror (errno));
3989 goto out;
3990 }
3991
3992 if (pid == 0)
3993 {
3994 /* child process */
3995 const char *error_str;
3996
3997 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
3998 {
3999 int saved_errno = errno;
4000
4001 /* Try to write details into the pipe, but don't bother
4002 * trying too hard (no retry loop). */
4003
4004 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
4005 write (errors_pipe[WRITE_END], ": ", 2) < 0)
4006 {
4007 /* ignore, not much we can do */
4008 }
4009
4010 error_str = _dbus_strerror (saved_errno);
4011
4012 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
4013 {
4014 /* ignore, not much we can do */
4015 }
4016
4017 _exit (1);
4018 }
4019
4020 /* set-up stdXXX */
4021 close (result_pipe[READ_END]);
4022 close (errors_pipe[READ_END]);
4023
4024 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
4025 _exit (1);
4026 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
4027 _exit (1);
4028
4029 _dbus_close_all ();
4030
4031 sigprocmask (SIG_SETMASK, &old_set, NULL);
4032
4033 /* If it looks fully-qualified, try execv first */
4034 if (progpath[0] == '/')
4035 {
4036 execv (progpath, (char * const *) argv);
4037 /* Ok, that failed. Now if path_fallback is given, let's
4038 * try unqualified. This is mostly a hack to work
4039 * around systems which ship dbus-launch in /usr/bin
4040 * but everything else in /bin (because dbus-launch
4041 * depends on X11).
4042 */
4043 if (path_fallback)
4044 /* We must have a slash, because we checked above */
4045 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
4046 }
4047 else
4048 execvp (progpath, (char * const *) argv);
4049
4050 /* still nothing, we failed */
4051 _exit (1);
4052 }
4053
4054 /* parent process */
4055 close (result_pipe[WRITE_END]);
4056 close (errors_pipe[WRITE_END]);
4057 result_pipe[WRITE_END] = -1;
4058 errors_pipe[WRITE_END] = -1;
4059
4060 ret = 0;
4061 do
4062 {
4063 ret = _dbus_read (result_pipe[READ_END], result, 1024);
4064 }
4065 while (ret > 0);
4066
4067 /* reap the child process to avoid it lingering as zombie */
4068 do
4069 {
4070 ret = waitpid (pid, &status, 0);
4071 }
4072 while (ret == -1 && errno == EINTR);
4073
4074 /* We succeeded if the process exited with status 0 and
4075 anything was read */
4076 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
4077 {
4078 /* The process ended with error */
4079 DBusString error_message;
4080 if (!_dbus_string_init (&error_message))
4081 {
4082 _DBUS_SET_OOM (error);
4083 goto out;
4084 }
4085
4086 ret = 0;
4087 do
4088 {
4089 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
4090 }
4091 while (ret > 0);
4092
4093 _dbus_string_set_length (result, orig_len);
4094 if (_dbus_string_get_length (&error_message) > 0)
4095 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
4096 "%s terminated abnormally with the following error: %s",
4097 progpath, _dbus_string_get_data (&error_message));
4098 else
4099 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
4100 "%s terminated abnormally without any error message",
4101 progpath);
4102 goto out;
4103 }
4104
4105 retval = TRUE;
4106
4107 out:
4108 sigprocmask (SIG_SETMASK, &old_set, NULL);
4109
4110 _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
4111
4112 if (result_pipe[0] != -1)
4113 close (result_pipe[0]);
4114 if (result_pipe[1] != -1)
4115 close (result_pipe[1]);
4116 if (errors_pipe[0] != -1)
4117 close (errors_pipe[0]);
4118 if (errors_pipe[1] != -1)
4119 close (errors_pipe[1]);
4120
4121 return retval;
4122 }
4123 #endif
4124
4137 dbus_bool_t
4138 _dbus_get_autolaunch_address (const char *scope,
4139 DBusString *address,
4140 DBusError *error)
4141 {
4142 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
4143 static const char arg_dbus_launch[] = "dbus-launch";
4144 static const char arg_autolaunch[] = "--autolaunch";
4145 static const char arg_binary_syntax[] = "--binary-syntax";
4146 static const char arg_close_stderr[] = "--close-stderr";
4147
4148 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
4149 * but that's done elsewhere, and if it worked, this function wouldn't
4150 * be called.) */
4151 const char *display;
4152 const char *progpath;
4153 const char *argv[6];
4154 int i;
4155 DBusString uuid;
4156 dbus_bool_t retval;
4157
4158 if (_dbus_check_setuid ())
4159 {
4160 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4161 "Unable to autolaunch when setuid");
4162 return FALSE;
4163 }
4164
4165 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4166 retval = FALSE;
4167
4168 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
4169 * dbus-launch-x11 is just going to fail. Rather than trying to
4170 * run it, we might as well bail out early with a nice error.
4171 *
4172 * This is not strictly true in a world where the user bus exists,
4173 * because dbus-launch --autolaunch knows how to connect to that -
4174 * but if we were going to connect to the user bus, we'd have done
4175 * so before trying autolaunch: in any case. */
4176 display = _dbus_getenv ("DISPLAY");
4177
4178 if (display == NULL || display[0] == '\0')
4179 {
4180 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4181 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
4182 return FALSE;
4183 }
4184
4185 if (!_dbus_string_init (&uuid))
4186 {
4187 _DBUS_SET_OOM (error);
4188 return FALSE;
4189 }
4190
4191 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
4192 {
4193 goto out;
4194 }
4195
4196 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4197 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
4198
4199 if (progpath == NULL)
4200 #endif
4201 progpath = DBUS_BINDIR "/dbus-launch";
4202 /*
4203 * argv[0] is always dbus-launch, that's the name what we'll
4204 * get from /proc, or ps(1), regardless what the progpath is,
4205 * see fd.o#69716
4206 */
4207 i = 0;
4208 argv[i] = arg_dbus_launch;
4209 ++i;
4210 argv[i] = arg_autolaunch;
4211 ++i;
4212 argv[i] = _dbus_string_get_data (&uuid);
4213 ++i;
4214 argv[i] = arg_binary_syntax;
4215 ++i;
4216 argv[i] = arg_close_stderr;
4217 ++i;
4218 argv[i] = NULL;
4219 ++i;
4220
4221 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4222
4223 retval = _read_subprocess_line_argv (progpath,
4224 TRUE,
4225 argv, address, error);
4226
4227 out:
4228 _dbus_string_free (&uuid);
4229 return retval;
4230 #else
4231 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4232 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
4233 "set your DBUS_SESSION_BUS_ADDRESS instead");
4234 return FALSE;
4235 #endif
4236 }
4237
4256 dbus_bool_t
4257 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
4258 dbus_bool_t create_if_not_found,
4259 DBusError *error)
4260 {
4261 DBusError our_error = DBUS_ERROR_INIT;
4262 DBusError etc_error = DBUS_ERROR_INIT;
4263 DBusString filename;
4264 dbus_bool_t b;
4265
4266 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4267
4268 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
4269 if (b)
4270 return TRUE;
4271
4272 /* Fallback to the system machine ID */
4273 _dbus_string_init_const (&filename, "/etc/machine-id");
4274 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
4275
4276 if (b)
4277 {
4278 if (create_if_not_found)
4279 {
4280 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
4281 * complain if that isn't possible for whatever reason */
4282 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4283 _dbus_write_uuid_file (&filename, machine_id, NULL);
4284 }
4285
4286 dbus_error_free (&our_error);
4287 return TRUE;
4288 }
4289
4290 if (!create_if_not_found)
4291 {
4292 dbus_set_error (error, etc_error.name,
4293 "D-Bus library appears to be incorrectly set up: "
4294 "see the manual page for dbus-uuidgen to correct "
4295 "this issue. (%s; %s)",
4296 our_error.message, etc_error.message);
4297 dbus_error_free (&our_error);
4298 dbus_error_free (&etc_error);
4299 return FALSE;
4300 }
4301
4302 dbus_error_free (&our_error);
4303 dbus_error_free (&etc_error);
4304
4305 /* if none found, try to make a new one */
4306 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4307
4308 if (!_dbus_generate_uuid (machine_id, error))
4309 return FALSE;
4310
4311 return _dbus_write_uuid_file (&filename, machine_id, error);
4312 }
4313
4321 dbus_bool_t
4322 _dbus_lookup_launchd_socket (DBusString *socket_path,
4323 const char *launchd_env_var,
4324 DBusError *error)
4325 {
4326 #ifdef DBUS_ENABLE_LAUNCHD
4327 char *argv[4];
4328 int i;
4329
4330 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4331
4332 if (_dbus_check_setuid ())
4333 {
4334 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4335 "Unable to find launchd socket when setuid");
4336 return FALSE;
4337 }
4338
4339 i = 0;
4340 argv[i] = "launchctl";
4341 ++i;
4342 argv[i] = "getenv";
4343 ++i;
4344 argv[i] = (char*)launchd_env_var;
4345 ++i;
4346 argv[i] = NULL;
4347 ++i;
4348
4349 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4350
4351 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4352 {
4353 return FALSE;
4354 }
4355
4356 /* no error, but no result either */
4357 if (_dbus_string_get_length(socket_path) == 0)
4358 {
4359 return FALSE;
4360 }
4361
4362 /* strip the carriage-return */
4363 _dbus_string_shorten(socket_path, 1);
4364 return TRUE;
4365 #else /* DBUS_ENABLE_LAUNCHD */
4366 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
4367 "can't lookup socket from launchd; launchd support not compiled in");
4368 return FALSE;
4369 #endif
4370 }
4371
4372 #ifdef DBUS_ENABLE_LAUNCHD
4373 static dbus_bool_t
4374 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4375 {
4376 dbus_bool_t valid_socket;
4377 DBusString socket_path;
4378
4379 if (_dbus_check_setuid ())
4380 {
4381 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
4382 "Unable to find launchd socket when setuid");
4383 return FALSE;
4384 }
4385
4386 if (!_dbus_string_init (&socket_path))
4387 {
4388 _DBUS_SET_OOM (error);
4389 return FALSE;
4390 }
4391
4392 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4393
4394 if (dbus_error_is_set(error))
4395 {
4396 _dbus_string_free(&socket_path);
4397 return FALSE;
4398 }
4399
4400 if (!valid_socket)
4401 {
4402 dbus_set_error(error, "no socket path",
4403 "launchd did not provide a socket path, "
4404 "verify that org.freedesktop.dbus-session.plist is loaded!");
4405 _dbus_string_free(&socket_path);
4406 return FALSE;
4407 }
4408 if (!_dbus_string_append (address, "unix:path="))
4409 {
4410 _DBUS_SET_OOM (error);
4411 _dbus_string_free(&socket_path);
4412 return FALSE;
4413 }
4414 if (!_dbus_string_copy (&socket_path, 0, address,
4415 _dbus_string_get_length (address)))
4416 {
4417 _DBUS_SET_OOM (error);
4418 _dbus_string_free(&socket_path);
4419 return FALSE;
4420 }
4421
4422 _dbus_string_free(&socket_path);
4423 return TRUE;
4424 }
4425 #endif
4426
4427 dbus_bool_t
4428 _dbus_lookup_user_bus (dbus_bool_t *supported,
4429 DBusString *address,
4430 DBusError *error)
4431 {
4432 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4433 dbus_bool_t ret = FALSE;
4434 struct stat stbuf;
4435 DBusString user_bus_path;
4436
4437 if (runtime_dir == NULL)
4438 {
4439 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4440 *supported = FALSE;
4441 return TRUE; /* Cannot use it, but not an error */
4442 }
4443
4444 if (!_dbus_string_init (&user_bus_path))
4445 {
4446 _DBUS_SET_OOM (error);
4447 return FALSE;
4448 }
4449
4450 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4451 {
4452 _DBUS_SET_OOM (error);
4453 goto out;
4454 }
4455
4456 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4457 {
4458 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4459 _dbus_strerror (errno));
4460 *supported = FALSE;
4461 ret = TRUE; /* Cannot use it, but not an error */
4462 goto out;
4463 }
4464
4465 if (stbuf.st_uid != getuid ())
4466 {
4467 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4468 (long) stbuf.st_uid, (long) getuid ());
4469 *supported = FALSE;
4470 ret = TRUE; /* Cannot use it, but not an error */
4471 goto out;
4472 }
4473
4474 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4475 {
4476 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4477 (long) stbuf.st_mode);
4478 *supported = FALSE;
4479 ret = TRUE; /* Cannot use it, but not an error */
4480 goto out;
4481 }
4482
4483 if (!_dbus_string_append (address, "unix:path=") ||
4484 !_dbus_address_append_escaped (address, &user_bus_path))
4485 {
4486 _DBUS_SET_OOM (error);
4487 goto out;
4488 }
4489
4490 *supported = TRUE;
4491 ret = TRUE;
4492
4493 out:
4494 _dbus_string_free (&user_bus_path);
4495 return ret;
4496 }
4497
4517 dbus_bool_t
4518 _dbus_lookup_session_address (dbus_bool_t *supported,
4519 DBusString *address,
4520 DBusError *error)
4521 {
4522 #ifdef DBUS_ENABLE_LAUNCHD
4523 *supported = TRUE;
4524 return _dbus_lookup_session_address_launchd (address, error);
4525 #else
4526 *supported = FALSE;
4527
4528 if (!_dbus_lookup_user_bus (supported, address, error))
4529 return FALSE;
4530 else if (*supported)
4531 return TRUE;
4532
4533 /* On non-Mac Unix platforms, if the session address isn't already
4534 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4535 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4536 * autolaunch: global default; see init_session_address in
4537 * dbus/dbus-bus.c. */
4538 return TRUE;
4539 #endif
4540 }
4541
4549 void
4550 _dbus_flush_caches (void)
4551 {
4552 _dbus_user_database_flush_system ();
4553 }
4554
4568 dbus_bool_t
4569 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
4570 DBusCredentials *credentials)
4571 {
4572 DBusString homedir;
4573 DBusString dotdir;
4574 dbus_uid_t uid;
4575
4576 _dbus_assert (credentials != NULL);
4577 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
4578
4579 if (!_dbus_string_init (&homedir))
4580 return FALSE;
4581
4582 uid = _dbus_credentials_get_unix_uid (credentials);
4583 _dbus_assert (uid != DBUS_UID_UNSET);
4584
4585 if (!_dbus_homedir_from_uid (uid, &homedir))
4586 goto failed;
4587
4588 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4589 {
4590 const char *override;
4591
4592 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4593 if (override != NULL && *override != '\0')
4594 {
4595 _dbus_string_set_length (&homedir, 0);
4596 if (!_dbus_string_append (&homedir, override))
4597 goto failed;
4598
4599 _dbus_verbose ("Using fake homedir for testing: %s\n",
4600 _dbus_string_get_const_data (&homedir));
4601 }
4602 else
4603 {
4604 /* Not strictly thread-safe, but if we fail at thread-safety here,
4605 * the worst that will happen is some extra warnings. */
4606 static dbus_bool_t already_warned = FALSE;
4607 if (!already_warned)
4608 {
4609 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4610 _dbus_string_get_const_data (&homedir));
4611 already_warned = TRUE;
4612 }
4613 }
4614 }
4615 #endif
4616
4617 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4618 if (!_dbus_concat_dir_and_file (&homedir,
4619 &dotdir))
4620 goto failed;
4621
4622 if (!_dbus_string_copy (&homedir, 0,
4623 directory, _dbus_string_get_length (directory))) {
4624 goto failed;
4625 }
4626
4627 _dbus_string_free (&homedir);
4628 return TRUE;
4629
4630 failed:
4631 _dbus_string_free (&homedir);
4632 return FALSE;
4633 }
4634
4635 //PENDING(kdab) docs
4636 dbus_bool_t
4637 _dbus_daemon_publish_session_bus_address (const char* addr,
4638 const char *scope)
4639 {
4640 return TRUE;
4641 }
4642
4643 //PENDING(kdab) docs
4644 void
4645 _dbus_daemon_unpublish_session_bus_address (void)
4646 {
4647
4648 }
4649
4656 dbus_bool_t
4657 _dbus_get_is_errno_eagain_or_ewouldblock (int e)
4658 {
4659 /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
4660 * EWOULDBLOCK are numerically equal, which is permitted as described by
4661 * errno(3).
4662 */
4663 #if EAGAIN == EWOULDBLOCK
4664 return e == EAGAIN;
4665 #else
4666 return e == EAGAIN || e == EWOULDBLOCK;
4667 #endif
4668 }
4669
4677 dbus_bool_t
4678 _dbus_delete_directory (const DBusString *filename,
4679 DBusError *error)
4680 {
4681 const char *filename_c;
4682
4683 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4684
4685 filename_c = _dbus_string_get_const_data (filename);
4686
4687 if (rmdir (filename_c) != 0)
4688 {
4689 dbus_set_error (error, DBUS_ERROR_FAILED,
4690 "Failed to remove directory %s: %s\n",
4691 filename_c, _dbus_strerror (errno));
4692 return FALSE;
4693 }
4694
4695 return TRUE;
4696 }
4697
4705 dbus_bool_t
4706 _dbus_socket_can_pass_unix_fd (DBusSocket fd)
4707 {
4708 #ifdef SCM_RIGHTS
4709 union {
4710 struct sockaddr sa;
4711 struct sockaddr_storage storage;
4712 struct sockaddr_un un;
4713 } sa_buf;
4714
4715 socklen_t sa_len = sizeof(sa_buf);
4716
4717 _DBUS_ZERO(sa_buf);
4718
4719 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4720 return FALSE;
4721
4722 return sa_buf.sa.sa_family == AF_UNIX;
4723
4724 #else
4725 return FALSE;
4726
4727 #endif
4728 }
4729
4730 static void
4731 close_ignore_error (int fd)
4732 {
4733 close (fd);
4734 }
4735
4736 /*
4737 * Similar to Solaris fdwalk(3), but without the ability to stop iteration,
4738 * and may call func for integers that are not actually valid fds.
4739 */
4740 static void
4741 act_on_fds_3_and_up (void (*func) (int fd))
4742 {
4743 int maxfds, i;
4744
4745 #ifdef __linux__
4746 DIR *d;
4747
4748 /* On Linux we can optimize this a bit if /proc is available. If it
4749 isn't available, fall back to the brute force way. */
4750
4751 d = opendir ("/proc/self/fd");
4752 if (d)
4753 {
4754 for (;;)
4755 {
4756 struct dirent *de;
4757 int fd;
4758 long l;
4759 char *e = NULL;
4760
4761 de = readdir (d);
4762 if (!de)
4763 break;
4764
4765 if (de->d_name[0] == '.')
4766 continue;
4767
4768 errno = 0;
4769 l = strtol (de->d_name, &e, 10);
4770 if (errno != 0 || e == NULL || *e != '\0')
4771 continue;
4772
4773 fd = (int) l;
4774 if (fd < 3)
4775 continue;
4776
4777 if (fd == dirfd (d))
4778 continue;
4779
4780 func (fd);
4781 }
4782
4783 closedir (d);
4784 return;
4785 }
4786 #endif
4787
4788 maxfds = sysconf (_SC_OPEN_MAX);
4789
4790 /* Pick something reasonable if for some reason sysconf says
4791 * unlimited.
4792 */
4793 if (maxfds < 0)
4794 maxfds = 1024;
4795
4796 /* close all inherited fds */
4797 for (i = 3; i < maxfds; i++)
4798 func (i);
4799 }
4800
4805 void
4806 _dbus_close_all (void)
4807 {
4808 act_on_fds_3_and_up (close_ignore_error);
4809 }
4810
4815 void
4816 _dbus_fd_set_all_close_on_exec (void)
4817 {
4818 act_on_fds_3_and_up (_dbus_fd_set_close_on_exec);
4819 }
4820
4830 dbus_bool_t
4831 _dbus_check_setuid (void)
4832 {
4833 /* TODO: get __libc_enable_secure exported from glibc.
4834 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4835 */
4836 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4837 {
4838 /* See glibc/include/unistd.h */
4839 extern int __libc_enable_secure;
4840 return __libc_enable_secure;
4841 }
4842 #elif defined(HAVE_ISSETUGID)
4843 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4844 return issetugid ();
4845 #else
4846 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4847 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4848
4849 /* We call into this function from _dbus_threads_init_platform_specific()
4850 * to make sure these are initialized before we start threading. */
4851 static dbus_bool_t check_setuid_initialised;
4852 static dbus_bool_t is_setuid;
4853
4854 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4855 {
4856 #ifdef HAVE_GETRESUID
4857 if (getresuid (&ruid, &euid, &suid) != 0 ||
4858 getresgid (&rgid, &egid, &sgid) != 0)
4859 #endif /* HAVE_GETRESUID */
4860 {
4861 suid = ruid = getuid ();
4862 sgid = rgid = getgid ();
4863 euid = geteuid ();
4864 egid = getegid ();
4865 }
4866
4867 check_setuid_initialised = TRUE;
4868 is_setuid = (ruid != euid || ruid != suid ||
4869 rgid != egid || rgid != sgid);
4870
4871 }
4872 return is_setuid;
4873 #endif
4874 }
4875
4883 dbus_bool_t
4884 _dbus_append_address_from_socket (DBusSocket fd,
4885 DBusString *address,
4886 DBusError *error)
4887 {
4888 union {
4889 struct sockaddr sa;
4890 struct sockaddr_storage storage;
4891 struct sockaddr_un un;
4892 struct sockaddr_in ipv4;
4893 struct sockaddr_in6 ipv6;
4894 } socket;
4895 char hostip[INET6_ADDRSTRLEN];
4896 socklen_t size = sizeof (socket);
4897 DBusString path_str;
4898 const char *family_name = NULL;
4899 dbus_uint16_t port;
4900
4901 if (getsockname (fd.fd, &socket.sa, &size))
4902 goto err;
4903
4904 switch (socket.sa.sa_family)
4905 {
4906 case AF_UNIX:
4907 if (socket.un.sun_path[0]=='\0')
4908 {
4909 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4910 if (_dbus_string_append (address, "unix:abstract=") &&
4911 _dbus_address_append_escaped (address, &path_str))
4912 {
4913 return TRUE;
4914 }
4915 else
4916 {
4917 _DBUS_SET_OOM (error);
4918 return FALSE;
4919 }
4920 }
4921 else
4922 {
4923 _dbus_string_init_const (&path_str, socket.un.sun_path);
4924 if (_dbus_string_append (address, "unix:path=") &&
4925 _dbus_address_append_escaped (address, &path_str))
4926 {
4927 return TRUE;
4928 }
4929 else
4930 {
4931 _DBUS_SET_OOM (error);
4932 return FALSE;
4933 }
4934 }
4935 /* not reached */
4936 break;
4937
4938 case AF_INET:
4939 #ifdef AF_INET6
4940 case AF_INET6:
4941 #endif
4942 _dbus_string_init_const (&path_str, hostip);
4943
4944 if (_dbus_inet_sockaddr_to_string (&socket, size, hostip, sizeof (hostip),
4945 &family_name, &port, error))
4946 {
4947 if (_dbus_string_append_printf (address, "tcp:family=%s,port=%u,host=",
4948 family_name, port) &&
4949 _dbus_address_append_escaped (address, &path_str))
4950 {
4951 return TRUE;
4952 }
4953 else
4954 {
4955 _DBUS_SET_OOM (error);
4956 return FALSE;
4957 }
4958 }
4959 else
4960 {
4961 return FALSE;
4962 }
4963 /* not reached */
4964 break;
4965
4966 default:
4967 dbus_set_error (error,
4968 _dbus_error_from_errno (EINVAL),
4969 "Failed to read address from socket: Unknown socket type.");
4970 return FALSE;
4971 }
4972 err:
4973 dbus_set_error (error,
4974 _dbus_error_from_errno (errno),
4975 "Failed to read address from socket: %s",
4976 _dbus_strerror (errno));
4977 return FALSE;
4978 }
4979
4980 int
4981 _dbus_save_socket_errno (void)
4982 {
4983 return errno;
4984 }
4985
4986 void
4987 _dbus_restore_socket_errno (int saved_errno)
4988 {
4989 errno = saved_errno;
4990 }
4991
4992 static const char *syslog_tag = "dbus";
4993 #ifdef HAVE_SYSLOG_H
4994 static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4995 #endif
4996
5011 void
5012 _dbus_init_system_log (const char *tag,
5013 DBusLogFlags flags)
5014 {
5015 /* We never want to turn off logging completely */
5016 _dbus_assert (
5017 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
5018
5019 syslog_tag = tag;
5020
5021 #ifdef HAVE_SYSLOG_H
5022 log_flags = flags;
5023
5024 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
5025 openlog (tag, LOG_PID, LOG_DAEMON);
5026 #endif
5027 }
5028
5036 void
5037 _dbus_logv (DBusSystemLogSeverity severity,
5038 const char *msg,
5039 va_list args)
5040 {
5041 va_list tmp;
5042 #ifdef HAVE_SYSLOG_H
5043 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
5044 {
5045 int flags;
5046 switch (severity)
5047 {
5048 case DBUS_SYSTEM_LOG_INFO:
5049 flags = LOG_DAEMON | LOG_INFO;
5050 break;
5051 case DBUS_SYSTEM_LOG_WARNING:
5052 flags = LOG_DAEMON | LOG_WARNING;
5053 break;
5054 case DBUS_SYSTEM_LOG_SECURITY:
5055 flags = LOG_AUTH | LOG_NOTICE;
5056 break;
5057 case DBUS_SYSTEM_LOG_ERROR:
5058 flags = LOG_DAEMON|LOG_CRIT;
5059 break;
5060 default:
5061 _dbus_assert_not_reached ("invalid log severity");
5062 }
5063
5064 DBUS_VA_COPY (tmp, args);
5065 vsyslog (flags, msg, tmp);
5066 va_end (tmp);
5067 }
5068
5069 /* If we don't have syslog.h, we always behave as though stderr was in
5070 * the flags */
5071 if (log_flags & DBUS_LOG_FLAGS_STDERR)
5072 #endif
5073 {
5074 DBUS_VA_COPY (tmp, args);
5075 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
5076 vfprintf (stderr, msg, tmp);
5077 fputc ('\n', stderr);
5078 va_end (tmp);
5079 }
5080 }
5081
5082 /*
5083 * Return the low-level representation of a socket error, as used by
5084 * cross-platform socket APIs like inet_ntop(), send() and recv(). This
5085 * is the standard errno on Unix, but is WSAGetLastError() on Windows.
5086 *
5087 * Some libdbus internal functions copy this into errno, but with
5088 * hindsight that was probably a design flaw.
5089 */
5090 int
5091 _dbus_get_low_level_socket_errno (void)
5092 {
5093 return errno;
5094 }
5095
5096 /* tests in dbus-sysdeps-util.c */
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:3057
_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:2903
_dbus_create_directory
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
Definition: dbus-sysdeps-unix.c:3305
DBusUserInfo::group_ids
dbus_gid_t * group_ids
Groups IDs, including above primary group.
Definition: dbus-sysdeps-unix.h:111
_DBUS_N_ELEMENTS
#define _DBUS_N_ELEMENTS(array)
Definition: dbus-internals.h:189
_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:2920
DBusUserInfo::n_group_ids
int n_group_ids
Size of group IDs array.
Definition: dbus-sysdeps-unix.h:112
_dbus_getuid
dbus_uid_t _dbus_getuid(void)
Gets our UID.
Definition: dbus-sysdeps-unix.c:2992
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:604
_dbus_ensure_standard_fds
dbus_bool_t _dbus_ensure_standard_fds(DBusEnsureStandardFdsFlags flags, const char **error_str_p)
Ensure that the standard file descriptors stdin, stdout and stderr are open, by opening /dev/null if ...
Definition: dbus-sysdeps-unix.c:155
_dbus_append_address_from_socket
dbus_bool_t _dbus_append_address_from_socket(DBusSocket fd, DBusString *address, DBusError *error)
Read the address from the socket and append it to the string.
Definition: dbus-sysdeps-unix.c:4884
_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:3336
_dbus_read_socket_with_unix_fds
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, unsigned int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
Definition: dbus-sysdeps-unix.c:358
DBusAtomic::value
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:331
_dbus_verbose_bytes_of_string
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
Definition: dbus-marshal-basic.c:1421
DBusPollFD::revents
short revents
Events that occurred.
Definition: dbus-sysdeps.h:425
_dbus_accept
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
Definition: dbus-sysdeps-unix.c:2541
_dbus_credentials_add_from_current_process
dbus_bool_t _dbus_credentials_add_from_current_process(DBusCredentials *credentials)
Adds the most important credentials of the current process (the uid and pid) to the passed-in credent...
Definition: dbus-sysdeps-unix.c:2942
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:271
_dbus_atomic_set_nonzero
void _dbus_atomic_set_nonzero(DBusAtomic *atomic)
Atomically set the value of an integer to something nonzero.
Definition: dbus-sysdeps-unix.c:3121
_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:4322
_dbus_generate_uuid
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
Definition: dbus-internals.c:720
_dbus_listen_systemd_sockets
int _dbus_listen_systemd_sockets(DBusSocket **fds, DBusError *error)
Acquires one or more sockets passed in from systemd.
Definition: dbus-sysdeps-unix.c:1271
_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:4138
_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:599
_dbus_set_socket_nonblocking
dbus_bool_t _dbus_set_socket_nonblocking(DBusSocket fd, DBusError *error)
Sets a file descriptor to be nonblocking.
Definition: dbus-sysdeps-unix.c:3636
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_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:791
_dbus_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition: dbus-sysdeps-unix.c:3509
_dbus_string_append_uint
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:401
DBUS_UID_FORMAT
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:151
_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:4550
_dbus_logv
void _dbus_logv(DBusSystemLogSeverity severity, const char *msg, va_list args)
Log a message to the system log file (e.g.
Definition: dbus-sysdeps-unix.c:5037
_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:936
DBusPollFD::events
short events
Events to poll for.
Definition: dbus-sysdeps.h:424
_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:4518
_dbus_atomic_set_zero
void _dbus_atomic_set_zero(DBusAtomic *atomic)
Atomically set the value of an integer to 0.
Definition: dbus-sysdeps-unix.c:3103
_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:1307
_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:784
_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:4569
_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:3220
DBusGUID
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
Definition: dbus-internals.h:433
DBusUserInfo::uid
dbus_uid_t uid
UID.
Definition: dbus-sysdeps-unix.h:109
dbus_error_init
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:188
_dbus_generate_random_bytes
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of securely random bytes, using the best mechanism we can come up with.
Definition: dbus-sysdeps-unix.c:3411
_dbus_connect_tcp_socket
DBusSocket _dbus_connect_tcp_socket(const char *host, const char *port, const char *family, DBusError *error)
Creates a socket and connects to a socket at the given host and port.
Definition: dbus-sysdeps-unix.c:1421
_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:1144
_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:1181
dbus_gid_t
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:139
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition: dbus-sysdeps-unix.c:3081
_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:1033
_DBUS_LOCK
#define _DBUS_LOCK(name)
Definition: dbus-internals.h:412
dbus_int32_t
int dbus_int32_t
Definition: dbus-arch-deps.h:42
_dbus_dup
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
Definition: dbus-sysdeps-unix.c:3594
TRUE
#define TRUE
_dbus_list_append
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
WRITE_END
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn-unix.c:895
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition: dbus-protocol.h:359
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition: dbus-protocol.h:420
_dbus_init_system_log
void _dbus_init_system_log(const char *tag, DBusLogFlags flags)
Initialize the system log.
Definition: dbus-sysdeps-unix.c:5012
_dbus_write_socket
int _dbus_write_socket(DBusSocket fd, const DBusString *buffer, int start, int len)
Like _dbus_write(), but only supports sockets and is thus available on Windows.
Definition: dbus-sysdeps-unix.c:320
DBusUserInfo::username
char * username
Username.
Definition: dbus-sysdeps-unix.h:113
_dbus_listen_tcp_socket
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, const char **retfamily, DBusSocket **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
Definition: dbus-sysdeps-unix.c:1582
_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:731
_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:362
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:704
_dbus_socket_can_pass_unix_fd
dbus_bool_t _dbus_socket_can_pass_unix_fd(DBusSocket fd)
Checks whether file descriptors may be passed via the socket.
Definition: dbus-sysdeps-unix.c:4706
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:435
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:464
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition: dbus-sysdeps-unix.c:3381
_dbus_exit
void _dbus_exit(int code)
Exit the process, returning the given value.
Definition: dbus-sysdeps-unix.c:3480
DBUS_ERROR_BAD_ADDRESS
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
Definition: dbus-protocol.h:371
_dbus_string_init_preallocated
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:139
DBusString
Definition: dbus-string.h:43
_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:4831
_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:1138
DBusPollFD::fd
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:423
DBusUserInfo::homedir
char * homedir
Home directory.
Definition: dbus-sysdeps-unix.h:114
_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:158
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:181
DBusError::name
const char * name
public error name field
Definition: dbus-errors.h:50
_dbus_list_pop_first
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:677
_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:899
_dbus_credentials_clear
void _dbus_credentials_clear(DBusCredentials *credentials)
Clear all credentials in the object.
Definition: dbus-credentials.c:593
_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:3798
DBusCredentials
Definition: dbus-credentials.c:49
DBUS_MAXIMUM_MESSAGE_UNIX_FDS
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
Definition: dbus-protocol.h:218
dbus_pid_t
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:135
dbus_uid_t
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:137
DBUS_GID_FORMAT
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
Definition: dbus-sysdeps.h:153
FALSE
#define FALSE
DBusPollFD
Definition: dbus-sysdeps.h:422
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition: dbus-protocol.h:361
_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:514
DBUS_ERROR_INIT
#define DBUS_ERROR_INIT
Definition: dbus-errors.h:62
_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:837
dbus_uint16_t
unsigned short dbus_uint16_t
Definition: dbus-arch-deps.h:46
_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:2596
DBUS_UID_UNSET
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:144
DBUS_PID_UNSET
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
Definition: dbus-sysdeps.h:142
_dbus_getenv
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:195
_dbus_send_credentials_socket
dbus_bool_t _dbus_send_credentials_socket(DBusSocket server_fd, DBusError *error)
Sends a single nul byte with our UNIX credentials as ancillary data.
Definition: dbus-sysdeps-unix.c:2520
_dbus_fd_set_close_on_exec
void _dbus_fd_set_close_on_exec(int fd)
Sets the file descriptor to be close on exec.
Definition: dbus-sysdeps-unix.c:3522
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_poll
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
Definition: dbus-sysdeps-unix.c:3142
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Definition: dbus-internals.h:164
_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:826
_dbus_read_socket
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
Definition: dbus-sysdeps-unix.c:302
DBusAtomic
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:327
dbus_new
#define dbus_new(type, count)
Definition: dbus-memory.h:57
_dbus_close_socket
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
Definition: dbus-sysdeps-unix.c:286
READ_END
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn-unix.c:893
_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:107
_dbus_credentials_take_unix_gids
void _dbus_credentials_take_unix_gids(DBusCredentials *credentials, dbus_gid_t *gids, size_t n_gids)
Add UNIX group IDs to the credentials, replacing any group IDs that might already have been present.
Definition: dbus-credentials.c:205
_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:3251
_dbus_assert
#define _dbus_assert(condition)
Definition: dbus-internals.h:153
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
Information about a UNIX user.
Definition: dbus-sysdeps-unix.h:107
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3566
_dbus_socketpair
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
Definition: dbus-sysdeps-unix.c:3723
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition: dbus-internals.c:238
_dbus_geteuid
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
Definition: dbus-sysdeps-unix.c:3001
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition: dbus-internals.c:589
_dbus_user_database_flush_system
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
Definition: dbus-userdb.c:394
_dbus_fd_clear_close_on_exec
void _dbus_fd_clear_close_on_exec(int fd)
Sets the file descriptor to not be close-on-exec.
Definition: dbus-sysdeps-unix.c:3544
_dbus_getpid
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
Definition: dbus-sysdeps-unix.c:2983
_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:479
DBusError
Object representing an exception.
Definition: dbus-errors.h:49
_dbus_print_backtrace
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
Definition: dbus-sysdeps-unix.c:3681
_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:294
DBusList
Definition: dbus-list.h:35
_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:2972
_dbus_ensure_directory
dbus_bool_t _dbus_ensure_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
Definition: dbus-sysdeps-unix.c:3273
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_PID_FORMAT
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:149
_DBUS_POLLIN
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:429
DBusUserInfo::primary_gid
dbus_gid_t primary_gid
GID.
Definition: dbus-sysdeps-unix.h:110
_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:850
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition: dbus-sysdeps-unix.c:3034
_DBUS_UNLOCK
#define _DBUS_UNLOCK(name)
Definition: dbus-internals.h:413
_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:4257
_dbus_credentials_add_linux_security_label
dbus_bool_t _dbus_credentials_add_linux_security_label(DBusCredentials *credentials, const char *label)
Add a Linux security label, as used by LSMs such as SELinux, Smack and AppArmor, to the credentials.
Definition: dbus-credentials.c:270
DBusError::message
const char * message
public error message field
Definition: dbus-errors.h:51
_DBUS_ZERO
#define _DBUS_ZERO(object)
Definition: dbus-internals.h:194
_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:464
_dbus_get_local_machine_uuid_encoded
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
Definition: dbus-internals.c:951
DBUS_GID_UNSET
#define DBUS_GID_UNSET
an invalid GID used to represent an uninitialized dbus_gid_t field
Definition: dbus-sysdeps.h:146
_dbus_string_init_const
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
dbus_new0
#define dbus_new0(type, count)
Definition: dbus-memory.h:58
_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:4678
_dbus_fd_set_all_close_on_exec
void _dbus_fd_set_all_close_on_exec(void)
Sets all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:4816
_dbus_get_is_errno_eagain_or_ewouldblock
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(int e)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted)
Definition: dbus-sysdeps-unix.c:4657
DBUS_ERROR_NOT_SUPPORTED
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
Definition: dbus-protocol.h:373
_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:804
_dbus_close_all
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
Definition: dbus-sysdeps-unix.c:4806
_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:959
_dbus_write_socket_two
int _dbus_write_socket_two(DBusSocket fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write_two() but only works on sockets and is thus available on Windows.
Definition: dbus-sysdeps-unix.c:658
_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:3013
_dbus_get_tmpdir
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory by inspecting the environment variables TMPDIR,...
Definition: dbus-sysdeps-unix.c:3868
_DBUS_POLLOUT
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:433
_DBUS_INT32_MAX
#define _DBUS_INT32_MAX
Definition: dbus-internals.h:298
DBUS_ERROR_IO_ERROR
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
Definition: dbus-protocol.h:369
_dbus_read_credentials_socket
dbus_bool_t _dbus_read_credentials_socket(DBusSocket client_fd, DBusCredentials *credentials, DBusError *error)
Reads a single byte which must be nul (an error occurs otherwise), and reads unix credentials if avai...
Definition: dbus-sysdeps-unix.c:2190
dbus_bool_t
dbus_uint32_t dbus_bool_t
Definition: dbus-types.h:35
NULL
#define NULL
_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:173