D-Bus  1.4.18
dbus-sysdeps-unix.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
00003  *
00004  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 
00027 #include "dbus-internals.h"
00028 #include "dbus-sysdeps.h"
00029 #include "dbus-sysdeps-unix.h"
00030 #include "dbus-threads.h"
00031 #include "dbus-protocol.h"
00032 #include "dbus-transport.h"
00033 #include "dbus-string.h"
00034 #include "dbus-userdb.h"
00035 #include "dbus-list.h"
00036 #include "dbus-credentials.h"
00037 #include "dbus-nonce.h"
00038 
00039 #include <sys/types.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <signal.h>
00043 #include <unistd.h>
00044 #include <stdio.h>
00045 #include <fcntl.h>
00046 #include <sys/socket.h>
00047 #include <dirent.h>
00048 #include <sys/un.h>
00049 #include <pwd.h>
00050 #include <time.h>
00051 #include <locale.h>
00052 #include <sys/time.h>
00053 #include <sys/stat.h>
00054 #include <sys/wait.h>
00055 #include <netinet/in.h>
00056 #include <netdb.h>
00057 #include <grp.h>
00058 
00059 #ifdef HAVE_ERRNO_H
00060 #include <errno.h>
00061 #endif
00062 #ifdef HAVE_WRITEV
00063 #include <sys/uio.h>
00064 #endif
00065 #ifdef HAVE_POLL
00066 #include <sys/poll.h>
00067 #endif
00068 #ifdef HAVE_BACKTRACE
00069 #include <execinfo.h>
00070 #endif
00071 #ifdef HAVE_GETPEERUCRED
00072 #include <ucred.h>
00073 #endif
00074 
00075 #ifdef HAVE_ADT
00076 #include <bsm/adt.h>
00077 #endif
00078 
00079 #include "sd-daemon.h"
00080 
00081 #ifndef O_BINARY
00082 #define O_BINARY 0
00083 #endif
00084 
00085 #ifndef AI_ADDRCONFIG
00086 #define AI_ADDRCONFIG 0
00087 #endif
00088 
00089 #ifndef HAVE_SOCKLEN_T
00090 #define socklen_t int
00091 #endif
00092 
00093 #if defined (__sun) || defined (__sun__)
00094 /*
00095  * CMS_SPACE etc. definitions for Solaris < 10, based on
00096  *   http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
00097  * via
00098  *   http://wiki.opencsw.org/porting-faq#toc10
00099  *
00100  * These are only redefined for Solaris, for now: if your OS needs these too,
00101  * please file a bug. (Or preferably, improve your OS so they're not needed.)
00102  */
00103 
00104 # ifndef CMSG_ALIGN
00105 #   ifdef __sun__
00106 #     define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
00107 #   else
00108       /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
00109 #     define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
00110                               ~(sizeof (long) - 1))
00111 #   endif
00112 # endif
00113 
00114 # ifndef CMSG_SPACE
00115 #   define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
00116                             CMSG_ALIGN (len))
00117 # endif
00118 
00119 # ifndef CMSG_LEN
00120 #   define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
00121 # endif
00122 
00123 #endif /* Solaris */
00124 
00125 static dbus_bool_t
00126 _dbus_open_socket (int              *fd_p,
00127                    int               domain,
00128                    int               type,
00129                    int               protocol,
00130                    DBusError        *error)
00131 {
00132 #ifdef SOCK_CLOEXEC
00133   dbus_bool_t cloexec_done;
00134 
00135   *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
00136   cloexec_done = *fd_p >= 0;
00137 
00138   /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
00139   if (*fd_p < 0 && errno == EINVAL)
00140 #endif
00141     {
00142       *fd_p = socket (domain, type, protocol);
00143     }
00144 
00145   if (*fd_p >= 0)
00146     {
00147 #ifdef SOCK_CLOEXEC
00148       if (!cloexec_done)
00149 #endif
00150         {
00151           _dbus_fd_set_close_on_exec(*fd_p);
00152         }
00153 
00154       _dbus_verbose ("socket fd %d opened\n", *fd_p);
00155       return TRUE;
00156     }
00157   else
00158     {
00159       dbus_set_error(error,
00160                      _dbus_error_from_errno (errno),
00161                      "Failed to open socket: %s",
00162                      _dbus_strerror (errno));
00163       return FALSE;
00164     }
00165 }
00166 
00167 dbus_bool_t
00168 _dbus_open_tcp_socket (int              *fd,
00169                        DBusError        *error)
00170 {
00171   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00172 }
00173 
00184 dbus_bool_t
00185 _dbus_open_unix_socket (int              *fd,
00186                         DBusError        *error)
00187 {
00188   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00189 }
00190 
00199 dbus_bool_t
00200 _dbus_close_socket (int               fd,
00201                     DBusError        *error)
00202 {
00203   return _dbus_close (fd, error);
00204 }
00205 
00215 int
00216 _dbus_read_socket (int               fd,
00217                    DBusString       *buffer,
00218                    int               count)
00219 {
00220   return _dbus_read (fd, buffer, count);
00221 }
00222 
00233 int
00234 _dbus_write_socket (int               fd,
00235                     const DBusString *buffer,
00236                     int               start,
00237                     int               len)
00238 {
00239 #if HAVE_DECL_MSG_NOSIGNAL
00240   const char *data;
00241   int bytes_written;
00242 
00243   data = _dbus_string_get_const_data_len (buffer, start, len);
00244 
00245  again:
00246 
00247   bytes_written = send (fd, data, len, MSG_NOSIGNAL);
00248 
00249   if (bytes_written < 0 && errno == EINTR)
00250     goto again;
00251 
00252   return bytes_written;
00253 
00254 #else
00255   return _dbus_write (fd, buffer, start, len);
00256 #endif
00257 }
00258 
00271 int
00272 _dbus_read_socket_with_unix_fds (int               fd,
00273                                  DBusString       *buffer,
00274                                  int               count,
00275                                  int              *fds,
00276                                  int              *n_fds) {
00277 #ifndef HAVE_UNIX_FD_PASSING
00278   int r;
00279 
00280   if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
00281     return r;
00282 
00283   *n_fds = 0;
00284   return r;
00285 
00286 #else
00287   int bytes_read;
00288   int start;
00289   struct msghdr m;
00290   struct iovec iov;
00291 
00292   _dbus_assert (count >= 0);
00293   _dbus_assert (*n_fds >= 0);
00294 
00295   start = _dbus_string_get_length (buffer);
00296 
00297   if (!_dbus_string_lengthen (buffer, count))
00298     {
00299       errno = ENOMEM;
00300       return -1;
00301     }
00302 
00303   _DBUS_ZERO(iov);
00304   iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
00305   iov.iov_len = count;
00306 
00307   _DBUS_ZERO(m);
00308   m.msg_iov = &iov;
00309   m.msg_iovlen = 1;
00310 
00311   /* Hmm, we have no clue how long the control data will actually be
00312      that is queued for us. The least we can do is assume that the
00313      caller knows. Hence let's make space for the number of fds that
00314      we shall read at max plus the cmsg header. */
00315   m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
00316 
00317   /* It's probably safe to assume that systems with SCM_RIGHTS also
00318      know alloca() */
00319   m.msg_control = alloca(m.msg_controllen);
00320   memset(m.msg_control, 0, m.msg_controllen);
00321 
00322   /* Do not include the padding at the end when we tell the kernel
00323    * how much we're willing to receive. This avoids getting
00324    * the padding filled with additional fds that we weren't expecting,
00325    * if a (potentially malicious) sender included them. (fd.o #83622) */
00326   m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
00327 
00328  again:
00329 
00330   bytes_read = recvmsg(fd, &m, 0
00331 #ifdef MSG_CMSG_CLOEXEC
00332                        |MSG_CMSG_CLOEXEC
00333 #endif
00334                        );
00335 
00336   if (bytes_read < 0)
00337     {
00338       if (errno == EINTR)
00339         goto again;
00340       else
00341         {
00342           /* put length back (note that this doesn't actually realloc anything) */
00343           _dbus_string_set_length (buffer, start);
00344           return -1;
00345         }
00346     }
00347   else
00348     {
00349       struct cmsghdr *cm;
00350       dbus_bool_t found = FALSE;
00351 
00352       for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
00353         if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
00354           {
00355             size_t i;
00356             int *payload = (int *) CMSG_DATA (cm);
00357             size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
00358             size_t payload_len_fds = payload_len_bytes / sizeof (int);
00359             size_t fds_to_use;
00360 
00361             /* Every non-negative int fits in a size_t without truncation,
00362              * and we already know that *n_fds is non-negative, so
00363              * casting (size_t) *n_fds is OK */
00364             _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
00365 
00366             if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
00367               {
00368                 /* The fds in the payload will fit in our buffer */
00369                 fds_to_use = payload_len_fds;
00370               }
00371             else
00372               {
00373                 /* Too many fds in the payload. This shouldn't happen
00374                  * any more because we're setting m.msg_controllen to
00375                  * the exact number we can accept, but be safe and
00376                  * truncate. */
00377                 fds_to_use = (size_t) *n_fds;
00378 
00379                 /* Close the excess fds to avoid DoS: if they stayed open,
00380                  * someone could send us an extra fd per message
00381                  * and we'd eventually run out. */
00382                 for (i = fds_to_use; i < payload_len_fds; i++)
00383                   {
00384                     close (payload[i]);
00385                   }
00386               }
00387 
00388             memcpy (fds, payload, fds_to_use * sizeof (int));
00389             found = TRUE;
00390             /* This cannot overflow because we have chosen fds_to_use
00391              * to be <= *n_fds */
00392             *n_fds = (int) fds_to_use;
00393 
00394             /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
00395                worked, hence we need to go through this list and set
00396                CLOEXEC everywhere in any case */
00397             for (i = 0; i < fds_to_use; i++)
00398               _dbus_fd_set_close_on_exec(fds[i]);
00399 
00400             break;
00401           }
00402 
00403       if (!found)
00404         *n_fds = 0;
00405 
00406       if (m.msg_flags & MSG_CTRUNC)
00407         {
00408           int i;
00409 
00410           /* Hmm, apparently the control data was truncated. The bad
00411              thing is that we might have completely lost a couple of fds
00412              without chance to recover them. Hence let's treat this as a
00413              serious error. */
00414 
00415           /* We still need to close whatever fds we *did* receive,
00416            * otherwise they'll never get closed. (CVE-2020-12049) */
00417           for (i = 0; i < *n_fds; i++)
00418             close (fds[i]);
00419 
00420           *n_fds = 0;
00421           errno = ENOSPC;
00422           _dbus_string_set_length (buffer, start);
00423           return -1;
00424         }
00425 
00426       /* put length back (doesn't actually realloc) */
00427       _dbus_string_set_length (buffer, start + bytes_read);
00428 
00429 #if 0
00430       if (bytes_read > 0)
00431         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00432 #endif
00433 
00434       return bytes_read;
00435     }
00436 #endif
00437 }
00438 
00439 int
00440 _dbus_write_socket_with_unix_fds(int               fd,
00441                                  const DBusString *buffer,
00442                                  int               start,
00443                                  int               len,
00444                                  const int        *fds,
00445                                  int               n_fds) {
00446 
00447 #ifndef HAVE_UNIX_FD_PASSING
00448 
00449   if (n_fds > 0) {
00450     errno = ENOTSUP;
00451     return -1;
00452   }
00453 
00454   return _dbus_write_socket(fd, buffer, start, len);
00455 #else
00456   return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
00457 #endif
00458 }
00459 
00460 int
00461 _dbus_write_socket_with_unix_fds_two(int               fd,
00462                                      const DBusString *buffer1,
00463                                      int               start1,
00464                                      int               len1,
00465                                      const DBusString *buffer2,
00466                                      int               start2,
00467                                      int               len2,
00468                                      const int        *fds,
00469                                      int               n_fds) {
00470 
00471 #ifndef HAVE_UNIX_FD_PASSING
00472 
00473   if (n_fds > 0) {
00474     errno = ENOTSUP;
00475     return -1;
00476   }
00477 
00478   return _dbus_write_socket_two(fd,
00479                                 buffer1, start1, len1,
00480                                 buffer2, start2, len2);
00481 #else
00482 
00483   struct msghdr m;
00484   struct cmsghdr *cm;
00485   struct iovec iov[2];
00486   int bytes_written;
00487 
00488   _dbus_assert (len1 >= 0);
00489   _dbus_assert (len2 >= 0);
00490   _dbus_assert (n_fds >= 0);
00491 
00492   _DBUS_ZERO(iov);
00493   iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
00494   iov[0].iov_len = len1;
00495 
00496   if (buffer2)
00497     {
00498       iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
00499       iov[1].iov_len = len2;
00500     }
00501 
00502   _DBUS_ZERO(m);
00503   m.msg_iov = iov;
00504   m.msg_iovlen = buffer2 ? 2 : 1;
00505 
00506   if (n_fds > 0)
00507     {
00508       m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
00509       m.msg_control = alloca(m.msg_controllen);
00510       memset(m.msg_control, 0, m.msg_controllen);
00511 
00512       cm = CMSG_FIRSTHDR(&m);
00513       cm->cmsg_level = SOL_SOCKET;
00514       cm->cmsg_type = SCM_RIGHTS;
00515       cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
00516       memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
00517     }
00518 
00519  again:
00520 
00521   bytes_written = sendmsg (fd, &m, 0
00522 #if HAVE_DECL_MSG_NOSIGNAL
00523                            |MSG_NOSIGNAL
00524 #endif
00525                            );
00526 
00527   if (bytes_written < 0 && errno == EINTR)
00528     goto again;
00529 
00530 #if 0
00531   if (bytes_written > 0)
00532     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00533 #endif
00534 
00535   return bytes_written;
00536 #endif
00537 }
00538 
00552 int
00553 _dbus_write_socket_two (int               fd,
00554                         const DBusString *buffer1,
00555                         int               start1,
00556                         int               len1,
00557                         const DBusString *buffer2,
00558                         int               start2,
00559                         int               len2)
00560 {
00561 #if HAVE_DECL_MSG_NOSIGNAL
00562   struct iovec vectors[2];
00563   const char *data1;
00564   const char *data2;
00565   int bytes_written;
00566   struct msghdr m;
00567 
00568   _dbus_assert (buffer1 != NULL);
00569   _dbus_assert (start1 >= 0);
00570   _dbus_assert (start2 >= 0);
00571   _dbus_assert (len1 >= 0);
00572   _dbus_assert (len2 >= 0);
00573 
00574   data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00575 
00576   if (buffer2 != NULL)
00577     data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00578   else
00579     {
00580       data2 = NULL;
00581       start2 = 0;
00582       len2 = 0;
00583     }
00584 
00585   vectors[0].iov_base = (char*) data1;
00586   vectors[0].iov_len = len1;
00587   vectors[1].iov_base = (char*) data2;
00588   vectors[1].iov_len = len2;
00589 
00590   _DBUS_ZERO(m);
00591   m.msg_iov = vectors;
00592   m.msg_iovlen = data2 ? 2 : 1;
00593 
00594  again:
00595 
00596   bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
00597 
00598   if (bytes_written < 0 && errno == EINTR)
00599     goto again;
00600 
00601   return bytes_written;
00602 
00603 #else
00604   return _dbus_write_two (fd, buffer1, start1, len1,
00605                           buffer2, start2, len2);
00606 #endif
00607 }
00608 
00609 dbus_bool_t
00610 _dbus_socket_is_invalid (int fd)
00611 {
00612     return fd < 0 ? TRUE : FALSE;
00613 }
00614 
00631 int
00632 _dbus_read (int               fd,
00633             DBusString       *buffer,
00634             int               count)
00635 {
00636   int bytes_read;
00637   int start;
00638   char *data;
00639 
00640   _dbus_assert (count >= 0);
00641 
00642   start = _dbus_string_get_length (buffer);
00643 
00644   if (!_dbus_string_lengthen (buffer, count))
00645     {
00646       errno = ENOMEM;
00647       return -1;
00648     }
00649 
00650   data = _dbus_string_get_data_len (buffer, start, count);
00651 
00652  again:
00653 
00654   bytes_read = read (fd, data, count);
00655 
00656   if (bytes_read < 0)
00657     {
00658       if (errno == EINTR)
00659         goto again;
00660       else
00661         {
00662           /* put length back (note that this doesn't actually realloc anything) */
00663           _dbus_string_set_length (buffer, start);
00664           return -1;
00665         }
00666     }
00667   else
00668     {
00669       /* put length back (doesn't actually realloc) */
00670       _dbus_string_set_length (buffer, start + bytes_read);
00671 
00672 #if 0
00673       if (bytes_read > 0)
00674         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00675 #endif
00676 
00677       return bytes_read;
00678     }
00679 }
00680 
00691 int
00692 _dbus_write (int               fd,
00693              const DBusString *buffer,
00694              int               start,
00695              int               len)
00696 {
00697   const char *data;
00698   int bytes_written;
00699 
00700   data = _dbus_string_get_const_data_len (buffer, start, len);
00701 
00702  again:
00703 
00704   bytes_written = write (fd, data, len);
00705 
00706   if (bytes_written < 0 && errno == EINTR)
00707     goto again;
00708 
00709 #if 0
00710   if (bytes_written > 0)
00711     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00712 #endif
00713 
00714   return bytes_written;
00715 }
00716 
00737 int
00738 _dbus_write_two (int               fd,
00739                  const DBusString *buffer1,
00740                  int               start1,
00741                  int               len1,
00742                  const DBusString *buffer2,
00743                  int               start2,
00744                  int               len2)
00745 {
00746   _dbus_assert (buffer1 != NULL);
00747   _dbus_assert (start1 >= 0);
00748   _dbus_assert (start2 >= 0);
00749   _dbus_assert (len1 >= 0);
00750   _dbus_assert (len2 >= 0);
00751 
00752 #ifdef HAVE_WRITEV
00753   {
00754     struct iovec vectors[2];
00755     const char *data1;
00756     const char *data2;
00757     int bytes_written;
00758 
00759     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00760 
00761     if (buffer2 != NULL)
00762       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00763     else
00764       {
00765         data2 = NULL;
00766         start2 = 0;
00767         len2 = 0;
00768       }
00769 
00770     vectors[0].iov_base = (char*) data1;
00771     vectors[0].iov_len = len1;
00772     vectors[1].iov_base = (char*) data2;
00773     vectors[1].iov_len = len2;
00774 
00775   again:
00776 
00777     bytes_written = writev (fd,
00778                             vectors,
00779                             data2 ? 2 : 1);
00780 
00781     if (bytes_written < 0 && errno == EINTR)
00782       goto again;
00783 
00784     return bytes_written;
00785   }
00786 #else /* HAVE_WRITEV */
00787   {
00788     int ret1;
00789 
00790     ret1 = _dbus_write (fd, buffer1, start1, len1);
00791     if (ret1 == len1 && buffer2 != NULL)
00792       {
00793         ret2 = _dbus_write (fd, buffer2, start2, len2);
00794         if (ret2 < 0)
00795           ret2 = 0; /* we can't report an error as the first write was OK */
00796 
00797         return ret1 + ret2;
00798       }
00799     else
00800       return ret1;
00801   }
00802 #endif /* !HAVE_WRITEV */
00803 }
00804 
00805 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00806 
00836 int
00837 _dbus_connect_unix_socket (const char     *path,
00838                            dbus_bool_t     abstract,
00839                            DBusError      *error)
00840 {
00841   int fd;
00842   size_t path_len;
00843   struct sockaddr_un addr;
00844 
00845   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00846 
00847   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00848                  path, abstract);
00849 
00850 
00851   if (!_dbus_open_unix_socket (&fd, error))
00852     {
00853       _DBUS_ASSERT_ERROR_IS_SET(error);
00854       return -1;
00855     }
00856   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00857 
00858   _DBUS_ZERO (addr);
00859   addr.sun_family = AF_UNIX;
00860   path_len = strlen (path);
00861 
00862   if (abstract)
00863     {
00864 #ifdef HAVE_ABSTRACT_SOCKETS
00865       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
00866       path_len++; /* Account for the extra nul byte added to the start of sun_path */
00867 
00868       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00869         {
00870           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00871                       "Abstract socket name too long\n");
00872           _dbus_close (fd, NULL);
00873           return -1;
00874         }
00875 
00876       strncpy (&addr.sun_path[1], path, path_len);
00877       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
00878 #else /* HAVE_ABSTRACT_SOCKETS */
00879       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00880                       "Operating system does not support abstract socket namespace\n");
00881       _dbus_close (fd, NULL);
00882       return -1;
00883 #endif /* ! HAVE_ABSTRACT_SOCKETS */
00884     }
00885   else
00886     {
00887       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00888         {
00889           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00890                       "Socket name too long\n");
00891           _dbus_close (fd, NULL);
00892           return -1;
00893         }
00894 
00895       strncpy (addr.sun_path, path, path_len);
00896     }
00897 
00898   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00899     {
00900       dbus_set_error (error,
00901                       _dbus_error_from_errno (errno),
00902                       "Failed to connect to socket %s: %s",
00903                       path, _dbus_strerror (errno));
00904 
00905       _dbus_close (fd, NULL);
00906       return -1;
00907     }
00908 
00909   if (!_dbus_set_fd_nonblocking (fd, error))
00910     {
00911       _DBUS_ASSERT_ERROR_IS_SET (error);
00912 
00913       _dbus_close (fd, NULL);
00914       return -1;
00915     }
00916 
00917   return fd;
00918 }
00919 
00929 static dbus_bool_t
00930 _dbus_set_local_creds (int fd, dbus_bool_t on)
00931 {
00932   dbus_bool_t retval = TRUE;
00933 
00934 #if defined(HAVE_CMSGCRED)
00935   /* NOOP just to make sure only one codepath is used
00936    *      and to prefer CMSGCRED
00937    */
00938 #elif defined(LOCAL_CREDS)
00939   int val = on ? 1 : 0;
00940   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00941     {
00942       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00943       retval = FALSE;
00944     }
00945   else
00946     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00947                    on ? "enabled" : "disabled", fd);
00948 #endif
00949 
00950   return retval;
00951 }
00952 
00970 int
00971 _dbus_listen_unix_socket (const char     *path,
00972                           dbus_bool_t     abstract,
00973                           DBusError      *error)
00974 {
00975   int listen_fd;
00976   struct sockaddr_un addr;
00977   size_t path_len;
00978   unsigned int reuseaddr;
00979 
00980   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00981 
00982   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00983                  path, abstract);
00984 
00985   if (!_dbus_open_unix_socket (&listen_fd, error))
00986     {
00987       _DBUS_ASSERT_ERROR_IS_SET(error);
00988       return -1;
00989     }
00990   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00991 
00992   _DBUS_ZERO (addr);
00993   addr.sun_family = AF_UNIX;
00994   path_len = strlen (path);
00995 
00996   if (abstract)
00997     {
00998 #ifdef HAVE_ABSTRACT_SOCKETS
00999       /* remember that abstract names aren't nul-terminated so we rely
01000        * on sun_path being filled in with zeroes above.
01001        */
01002       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
01003       path_len++; /* Account for the extra nul byte added to the start of sun_path */
01004 
01005       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01006         {
01007           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01008                       "Abstract socket name too long\n");
01009           _dbus_close (listen_fd, NULL);
01010           return -1;
01011         }
01012 
01013       strncpy (&addr.sun_path[1], path, path_len);
01014       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
01015 #else /* HAVE_ABSTRACT_SOCKETS */
01016       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
01017                       "Operating system does not support abstract socket namespace\n");
01018       _dbus_close (listen_fd, NULL);
01019       return -1;
01020 #endif /* ! HAVE_ABSTRACT_SOCKETS */
01021     }
01022   else
01023     {
01024       /* Discussed security implications of this with Nalin,
01025        * and we couldn't think of where it would kick our ass, but
01026        * it still seems a bit sucky. It also has non-security suckage;
01027        * really we'd prefer to exit if the socket is already in use.
01028        * But there doesn't seem to be a good way to do this.
01029        *
01030        * Just to be extra careful, I threw in the stat() - clearly
01031        * the stat() can't *fix* any security issue, but it at least
01032        * avoids inadvertent/accidental data loss.
01033        */
01034       {
01035         struct stat sb;
01036 
01037         if (stat (path, &sb) == 0 &&
01038             S_ISSOCK (sb.st_mode))
01039           unlink (path);
01040       }
01041 
01042       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01043         {
01044           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01045                       "Abstract socket name too long\n");
01046           _dbus_close (listen_fd, NULL);
01047           return -1;
01048         }
01049 
01050       strncpy (addr.sun_path, path, path_len);
01051     }
01052 
01053   reuseaddr = 1;
01054   if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01055     {
01056       _dbus_warn ("Failed to set socket option\"%s\": %s",
01057                   path, _dbus_strerror (errno));
01058     }
01059 
01060   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
01061     {
01062       dbus_set_error (error, _dbus_error_from_errno (errno),
01063                       "Failed to bind socket \"%s\": %s",
01064                       path, _dbus_strerror (errno));
01065       _dbus_close (listen_fd, NULL);
01066       return -1;
01067     }
01068 
01069   if (listen (listen_fd, 30 /* backlog */) < 0)
01070     {
01071       dbus_set_error (error, _dbus_error_from_errno (errno),
01072                       "Failed to listen on socket \"%s\": %s",
01073                       path, _dbus_strerror (errno));
01074       _dbus_close (listen_fd, NULL);
01075       return -1;
01076     }
01077 
01078   if (!_dbus_set_local_creds (listen_fd, TRUE))
01079     {
01080       dbus_set_error (error, _dbus_error_from_errno (errno),
01081                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
01082                       path, _dbus_strerror (errno));
01083       close (listen_fd);
01084       return -1;
01085     }
01086 
01087   if (!_dbus_set_fd_nonblocking (listen_fd, error))
01088     {
01089       _DBUS_ASSERT_ERROR_IS_SET (error);
01090       _dbus_close (listen_fd, NULL);
01091       return -1;
01092     }
01093 
01094   /* Try opening up the permissions, but if we can't, just go ahead
01095    * and continue, maybe it will be good enough.
01096    */
01097   if (!abstract && chmod (path, 0777) < 0)
01098     _dbus_warn ("Could not set mode 0777 on socket %s\n",
01099                 path);
01100 
01101   return listen_fd;
01102 }
01103 
01114 int
01115 _dbus_listen_systemd_sockets (int       **fds,
01116                               DBusError *error)
01117 {
01118   int r, n;
01119   unsigned fd;
01120   int *new_fds;
01121 
01122   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01123 
01124   n = sd_listen_fds (TRUE);
01125   if (n < 0)
01126     {
01127       dbus_set_error (error, _dbus_error_from_errno (-n),
01128                       "Failed to acquire systemd socket: %s",
01129                       _dbus_strerror (-n));
01130       return -1;
01131     }
01132 
01133   if (n <= 0)
01134     {
01135       dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01136                       "No socket received.");
01137       return -1;
01138     }
01139 
01140   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01141     {
01142       r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
01143       if (r < 0)
01144         {
01145           dbus_set_error (error, _dbus_error_from_errno (-r),
01146                           "Failed to verify systemd socket type: %s",
01147                           _dbus_strerror (-r));
01148           return -1;
01149         }
01150 
01151       if (!r)
01152         {
01153           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01154                           "Passed socket has wrong type.");
01155           return -1;
01156         }
01157     }
01158 
01159   /* OK, the file descriptors are all good, so let's take posession of
01160      them then. */
01161 
01162   new_fds = dbus_new (int, n);
01163   if (!new_fds)
01164     {
01165       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
01166                       "Failed to allocate file handle array.");
01167       goto fail;
01168     }
01169 
01170   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01171     {
01172       if (!_dbus_set_local_creds (fd, TRUE))
01173         {
01174           dbus_set_error (error, _dbus_error_from_errno (errno),
01175                           "Failed to enable LOCAL_CREDS on systemd socket: %s",
01176                           _dbus_strerror (errno));
01177           goto fail;
01178         }
01179 
01180       if (!_dbus_set_fd_nonblocking (fd, error))
01181         {
01182           _DBUS_ASSERT_ERROR_IS_SET (error);
01183           goto fail;
01184         }
01185 
01186       new_fds[fd - SD_LISTEN_FDS_START] = fd;
01187     }
01188 
01189   *fds = new_fds;
01190   return n;
01191 
01192  fail:
01193 
01194   for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01195     {
01196       _dbus_close (fd, NULL);
01197     }
01198 
01199   dbus_free (new_fds);
01200   return -1;
01201 }
01202 
01216 int
01217 _dbus_connect_tcp_socket (const char     *host,
01218                           const char     *port,
01219                           const char     *family,
01220                           DBusError      *error)
01221 {
01222     return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
01223 }
01224 
01225 int
01226 _dbus_connect_tcp_socket_with_nonce (const char     *host,
01227                                      const char     *port,
01228                                      const char     *family,
01229                                      const char     *noncefile,
01230                                      DBusError      *error)
01231 {
01232   int saved_errno = 0;
01233   int fd = -1, res;
01234   struct addrinfo hints;
01235   struct addrinfo *ai, *tmp;
01236 
01237   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01238 
01239   _DBUS_ZERO (hints);
01240 
01241   if (!family)
01242     hints.ai_family = AF_UNSPEC;
01243   else if (!strcmp(family, "ipv4"))
01244     hints.ai_family = AF_INET;
01245   else if (!strcmp(family, "ipv6"))
01246     hints.ai_family = AF_INET6;
01247   else
01248     {
01249       dbus_set_error (error,
01250                       DBUS_ERROR_BAD_ADDRESS,
01251                       "Unknown address family %s", family);
01252       return -1;
01253     }
01254   hints.ai_protocol = IPPROTO_TCP;
01255   hints.ai_socktype = SOCK_STREAM;
01256   hints.ai_flags = AI_ADDRCONFIG;
01257 
01258   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
01259     {
01260       dbus_set_error (error,
01261                       _dbus_error_from_errno (errno),
01262                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01263                       host, port, gai_strerror(res), res);
01264       return -1;
01265     }
01266 
01267   tmp = ai;
01268   while (tmp)
01269     {
01270       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01271         {
01272           freeaddrinfo(ai);
01273           _DBUS_ASSERT_ERROR_IS_SET(error);
01274           return -1;
01275         }
01276       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01277 
01278       if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01279         {
01280           saved_errno = errno;
01281           _dbus_close(fd, NULL);
01282           fd = -1;
01283           tmp = tmp->ai_next;
01284           continue;
01285         }
01286 
01287       break;
01288     }
01289   freeaddrinfo(ai);
01290 
01291   if (fd == -1)
01292     {
01293       dbus_set_error (error,
01294                       _dbus_error_from_errno (saved_errno),
01295                       "Failed to connect to socket \"%s:%s\" %s",
01296                       host, port, _dbus_strerror(saved_errno));
01297       return -1;
01298     }
01299 
01300   if (noncefile != NULL)
01301     {
01302       DBusString noncefileStr;
01303       dbus_bool_t ret;
01304       _dbus_string_init_const (&noncefileStr, noncefile);
01305       ret = _dbus_send_nonce (fd, &noncefileStr, error);
01306       _dbus_string_free (&noncefileStr);
01307 
01308       if (!ret)
01309     {
01310       _dbus_close (fd, NULL);
01311           return -1;
01312         }
01313     }
01314 
01315   if (!_dbus_set_fd_nonblocking (fd, error))
01316     {
01317       _dbus_close (fd, NULL);
01318       return -1;
01319     }
01320 
01321   return fd;
01322 }
01323 
01340 int
01341 _dbus_listen_tcp_socket (const char     *host,
01342                          const char     *port,
01343                          const char     *family,
01344                          DBusString     *retport,
01345                          int           **fds_p,
01346                          DBusError      *error)
01347 {
01348   int saved_errno;
01349   int nlisten_fd = 0, *listen_fd = NULL, res, i;
01350   struct addrinfo hints;
01351   struct addrinfo *ai, *tmp;
01352   unsigned int reuseaddr;
01353 
01354   *fds_p = NULL;
01355   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01356 
01357   _DBUS_ZERO (hints);
01358 
01359   if (!family)
01360     hints.ai_family = AF_UNSPEC;
01361   else if (!strcmp(family, "ipv4"))
01362     hints.ai_family = AF_INET;
01363   else if (!strcmp(family, "ipv6"))
01364     hints.ai_family = AF_INET6;
01365   else
01366     {
01367       dbus_set_error (error,
01368                       DBUS_ERROR_BAD_ADDRESS,
01369                       "Unknown address family %s", family);
01370       return -1;
01371     }
01372 
01373   hints.ai_protocol = IPPROTO_TCP;
01374   hints.ai_socktype = SOCK_STREAM;
01375   hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
01376 
01377  redo_lookup_with_port:
01378   ai = NULL;
01379   if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01380     {
01381       dbus_set_error (error,
01382                       _dbus_error_from_errno (errno),
01383                       "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01384                       host ? host : "*", port, gai_strerror(res), res);
01385       goto failed;
01386     }
01387 
01388   tmp = ai;
01389   while (tmp)
01390     {
01391       int fd = -1, *newlisten_fd;
01392       if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01393         {
01394           _DBUS_ASSERT_ERROR_IS_SET(error);
01395           goto failed;
01396         }
01397       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01398 
01399       reuseaddr = 1;
01400       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01401         {
01402           _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01403                       host ? host : "*", port, _dbus_strerror (errno));
01404         }
01405 
01406       if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01407         {
01408           saved_errno = errno;
01409           _dbus_close(fd, NULL);
01410           if (saved_errno == EADDRINUSE)
01411             {
01412               /* Depending on kernel policy, it may or may not
01413                  be neccessary to bind to both IPv4 & 6 addresses
01414                  so ignore EADDRINUSE here */
01415               tmp = tmp->ai_next;
01416               continue;
01417             }
01418           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01419                           "Failed to bind socket \"%s:%s\": %s",
01420                           host ? host : "*", port, _dbus_strerror (saved_errno));
01421           goto failed;
01422         }
01423 
01424       if (listen (fd, 30 /* backlog */) < 0)
01425         {
01426           saved_errno = errno;
01427           _dbus_close (fd, NULL);
01428           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01429                           "Failed to listen on socket \"%s:%s\": %s",
01430                           host ? host : "*", port, _dbus_strerror (saved_errno));
01431           goto failed;
01432         }
01433 
01434       newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
01435       if (!newlisten_fd)
01436         {
01437           saved_errno = errno;
01438           _dbus_close (fd, NULL);
01439           dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01440                           "Failed to allocate file handle array: %s",
01441                           _dbus_strerror (saved_errno));
01442           goto failed;
01443         }
01444       listen_fd = newlisten_fd;
01445       listen_fd[nlisten_fd] = fd;
01446       nlisten_fd++;
01447 
01448       if (!_dbus_string_get_length(retport))
01449         {
01450           /* If the user didn't specify a port, or used 0, then
01451              the kernel chooses a port. After the first address
01452              is bound to, we need to force all remaining addresses
01453              to use the same port */
01454           if (!port || !strcmp(port, "0"))
01455             {
01456               int result;
01457               struct sockaddr_storage addr;
01458               socklen_t addrlen;
01459               char portbuf[50];
01460 
01461               addrlen = sizeof(addr);
01462               result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01463 
01464               if (result == -1 ||
01465                   (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
01466                                       portbuf, sizeof(portbuf),
01467                                       NI_NUMERICHOST)) != 0)
01468                 {
01469                   dbus_set_error (error, _dbus_error_from_errno (errno),
01470                                   "Failed to resolve port \"%s:%s\": %s (%s)",
01471                                   host ? host : "*", port, gai_strerror(res), res);
01472                   goto failed;
01473                 }
01474               if (!_dbus_string_append(retport, portbuf))
01475                 {
01476                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01477                   goto failed;
01478                 }
01479 
01480               /* Release current address list & redo lookup */
01481               port = _dbus_string_get_const_data(retport);
01482               freeaddrinfo(ai);
01483               goto redo_lookup_with_port;
01484             }
01485           else
01486             {
01487               if (!_dbus_string_append(retport, port))
01488                 {
01489                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01490                     goto failed;
01491                 }
01492             }
01493         }
01494 
01495       tmp = tmp->ai_next;
01496     }
01497   freeaddrinfo(ai);
01498   ai = NULL;
01499 
01500   if (!nlisten_fd)
01501     {
01502       errno = EADDRINUSE;
01503       dbus_set_error (error, _dbus_error_from_errno (errno),
01504                       "Failed to bind socket \"%s:%s\": %s",
01505                       host ? host : "*", port, _dbus_strerror (errno));
01506       goto failed;
01507     }
01508 
01509   for (i = 0 ; i < nlisten_fd ; i++)
01510     {
01511       if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01512         {
01513           goto failed;
01514         }
01515     }
01516 
01517   *fds_p = listen_fd;
01518 
01519   return nlisten_fd;
01520 
01521  failed:
01522   if (ai)
01523     freeaddrinfo(ai);
01524   for (i = 0 ; i < nlisten_fd ; i++)
01525     _dbus_close(listen_fd[i], NULL);
01526   dbus_free(listen_fd);
01527   return -1;
01528 }
01529 
01530 static dbus_bool_t
01531 write_credentials_byte (int             server_fd,
01532                         DBusError      *error)
01533 {
01534   int bytes_written;
01535   char buf[1] = { '\0' };
01536 #if defined(HAVE_CMSGCRED)
01537   union {
01538           struct cmsghdr hdr;
01539           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01540   } cmsg;
01541   struct iovec iov;
01542   struct msghdr msg;
01543   iov.iov_base = buf;
01544   iov.iov_len = 1;
01545 
01546   _DBUS_ZERO(msg);
01547   msg.msg_iov = &iov;
01548   msg.msg_iovlen = 1;
01549 
01550   msg.msg_control = (caddr_t) &cmsg;
01551   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01552   _DBUS_ZERO(cmsg);
01553   cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01554   cmsg.hdr.cmsg_level = SOL_SOCKET;
01555   cmsg.hdr.cmsg_type = SCM_CREDS;
01556 #endif
01557 
01558   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01559 
01560  again:
01561 
01562 #if defined(HAVE_CMSGCRED)
01563   bytes_written = sendmsg (server_fd, &msg, 0
01564 #if HAVE_DECL_MSG_NOSIGNAL
01565                            |MSG_NOSIGNAL
01566 #endif
01567                            );
01568 #else
01569   bytes_written = send (server_fd, buf, 1, 0
01570 #if HAVE_DECL_MSG_NOSIGNAL
01571                         |MSG_NOSIGNAL
01572 #endif
01573                         );
01574 #endif
01575 
01576   if (bytes_written < 0 && errno == EINTR)
01577     goto again;
01578 
01579   if (bytes_written < 0)
01580     {
01581       dbus_set_error (error, _dbus_error_from_errno (errno),
01582                       "Failed to write credentials byte: %s",
01583                      _dbus_strerror (errno));
01584       return FALSE;
01585     }
01586   else if (bytes_written == 0)
01587     {
01588       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01589                       "wrote zero bytes writing credentials byte");
01590       return FALSE;
01591     }
01592   else
01593     {
01594       _dbus_assert (bytes_written == 1);
01595       _dbus_verbose ("wrote credentials byte\n");
01596       return TRUE;
01597     }
01598 }
01599 
01621 dbus_bool_t
01622 _dbus_read_credentials_socket  (int              client_fd,
01623                                 DBusCredentials *credentials,
01624                                 DBusError       *error)
01625 {
01626   struct msghdr msg;
01627   struct iovec iov;
01628   char buf;
01629   dbus_uid_t uid_read;
01630   dbus_pid_t pid_read;
01631   int bytes_read;
01632 
01633 #ifdef HAVE_CMSGCRED
01634   union {
01635     struct cmsghdr hdr;
01636     char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01637   } cmsg;
01638 
01639 #elif defined(LOCAL_CREDS)
01640   struct {
01641     struct cmsghdr hdr;
01642     struct sockcred cred;
01643   } cmsg;
01644 #endif
01645 
01646   uid_read = DBUS_UID_UNSET;
01647   pid_read = DBUS_PID_UNSET;
01648 
01649   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01650 
01651   /* The POSIX spec certainly doesn't promise this, but
01652    * we need these assertions to fail as soon as we're wrong about
01653    * it so we can do the porting fixups
01654    */
01655   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01656   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01657   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01658 
01659   _dbus_credentials_clear (credentials);
01660 
01661   /* Systems supporting LOCAL_CREDS are configured to have this feature
01662    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
01663    * the connection.  Therefore, the received message must carry the
01664    * credentials information without doing anything special.
01665    */
01666 
01667   iov.iov_base = &buf;
01668   iov.iov_len = 1;
01669 
01670   _DBUS_ZERO(msg);
01671   msg.msg_iov = &iov;
01672   msg.msg_iovlen = 1;
01673 
01674 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01675   _DBUS_ZERO(cmsg);
01676   msg.msg_control = (caddr_t) &cmsg;
01677   msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01678 #endif
01679 
01680  again:
01681   bytes_read = recvmsg (client_fd, &msg, 0);
01682 
01683   if (bytes_read < 0)
01684     {
01685       if (errno == EINTR)
01686         goto again;
01687 
01688       /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
01689        * normally only call read_credentials if the socket was ready
01690        * for reading
01691        */
01692 
01693       dbus_set_error (error, _dbus_error_from_errno (errno),
01694                       "Failed to read credentials byte: %s",
01695                       _dbus_strerror (errno));
01696       return FALSE;
01697     }
01698   else if (bytes_read == 0)
01699     {
01700       /* this should not happen unless we are using recvmsg wrong,
01701        * so is essentially here for paranoia
01702        */
01703       dbus_set_error (error, DBUS_ERROR_FAILED,
01704                       "Failed to read credentials byte (zero-length read)");
01705       return FALSE;
01706     }
01707   else if (buf != '\0')
01708     {
01709       dbus_set_error (error, DBUS_ERROR_FAILED,
01710                       "Credentials byte was not nul");
01711       return FALSE;
01712     }
01713 
01714 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01715   if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01716                   || cmsg.hdr.cmsg_type != SCM_CREDS)
01717     {
01718       dbus_set_error (error, DBUS_ERROR_FAILED,
01719                       "Message from recvmsg() was not SCM_CREDS");
01720       return FALSE;
01721     }
01722 #endif
01723 
01724   _dbus_verbose ("read credentials byte\n");
01725 
01726   {
01727 #ifdef SO_PEERCRED
01728 #ifdef __OpenBSD__
01729     struct sockpeercred cr;
01730 #else
01731     struct ucred cr;
01732 #endif
01733     int cr_len = sizeof (cr);
01734 
01735     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01736         cr_len == sizeof (cr))
01737       {
01738         pid_read = cr.pid;
01739         uid_read = cr.uid;
01740       }
01741     else
01742       {
01743         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01744                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01745       }
01746 #elif defined(HAVE_CMSGCRED)
01747     struct cmsgcred *cred;
01748 
01749     cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01750     pid_read = cred->cmcred_pid;
01751     uid_read = cred->cmcred_euid;
01752 #elif defined(LOCAL_CREDS)
01753     pid_read = DBUS_PID_UNSET;
01754     uid_read = cmsg.cred.sc_uid;
01755     /* Since we have already got the credentials from this socket, we can
01756      * disable its LOCAL_CREDS flag if it was ever set. */
01757     _dbus_set_local_creds (client_fd, FALSE);
01758 #elif defined(HAVE_GETPEEREID)
01759     uid_t euid;
01760     gid_t egid;
01761     if (getpeereid (client_fd, &euid, &egid) == 0)
01762       {
01763         uid_read = euid;
01764       }
01765     else
01766       {
01767         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01768       }
01769 #elif defined(HAVE_GETPEERUCRED)
01770     ucred_t * ucred = NULL;
01771     if (getpeerucred (client_fd, &ucred) == 0)
01772       {
01773         pid_read = ucred_getpid (ucred);
01774         uid_read = ucred_geteuid (ucred);
01775 #ifdef HAVE_ADT
01776         /* generate audit session data based on socket ucred */
01777         adt_session_data_t *adth = NULL;
01778         adt_export_data_t *data = NULL;
01779         size_t size = 0;
01780         if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01781           {
01782             _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01783           }
01784         else
01785           {
01786             if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01787               {
01788                 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01789               }
01790             else
01791               {
01792                 size = adt_export_session_data (adth, &data);
01793                 if (size <= 0)
01794                   {
01795                     _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01796                   }
01797                 else
01798                   {
01799                     _dbus_credentials_add_adt_audit_data (credentials, data, size);
01800                     free (data);
01801                   }
01802               }
01803             (void) adt_end_session (adth);
01804           }
01805 #endif /* HAVE_ADT */
01806       }
01807     else
01808       {
01809         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01810       }
01811     if (ucred != NULL)
01812       ucred_free (ucred);
01813 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
01814     _dbus_verbose ("Socket credentials not supported on this OS\n");
01815 #endif
01816   }
01817 
01818   _dbus_verbose ("Credentials:"
01819                  "  pid "DBUS_PID_FORMAT
01820                  "  uid "DBUS_UID_FORMAT
01821                  "\n",
01822                  pid_read,
01823                  uid_read);
01824 
01825   if (pid_read != DBUS_PID_UNSET)
01826     {
01827       if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01828         {
01829           _DBUS_SET_OOM (error);
01830           return FALSE;
01831         }
01832     }
01833 
01834   if (uid_read != DBUS_UID_UNSET)
01835     {
01836       if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01837         {
01838           _DBUS_SET_OOM (error);
01839           return FALSE;
01840         }
01841     }
01842 
01843   return TRUE;
01844 }
01845 
01863 dbus_bool_t
01864 _dbus_send_credentials_socket  (int              server_fd,
01865                                 DBusError       *error)
01866 {
01867   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01868 
01869   if (write_credentials_byte (server_fd, error))
01870     return TRUE;
01871   else
01872     return FALSE;
01873 }
01874 
01884 int
01885 _dbus_accept  (int listen_fd)
01886 {
01887   int client_fd;
01888   struct sockaddr addr;
01889   socklen_t addrlen;
01890 #ifdef HAVE_ACCEPT4
01891   dbus_bool_t cloexec_done;
01892 #endif
01893 
01894   addrlen = sizeof (addr);
01895 
01896  retry:
01897 
01898 #ifdef HAVE_ACCEPT4
01899   /* We assume that if accept4 is available SOCK_CLOEXEC is too */
01900   client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
01901   cloexec_done = client_fd >= 0;
01902 
01903   if (client_fd < 0 && errno == ENOSYS)
01904 #endif
01905     {
01906       client_fd = accept (listen_fd, &addr, &addrlen);
01907     }
01908 
01909   if (client_fd < 0)
01910     {
01911       if (errno == EINTR)
01912         goto retry;
01913     }
01914 
01915   _dbus_verbose ("client fd %d accepted\n", client_fd);
01916 
01917 #ifdef HAVE_ACCEPT4
01918   if (!cloexec_done)
01919 #endif
01920     {
01921       _dbus_fd_set_close_on_exec(client_fd);
01922     }
01923 
01924   return client_fd;
01925 }
01926 
01935 dbus_bool_t
01936 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01937 {
01938   const char *directory;
01939   struct stat sb;
01940 
01941   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01942 
01943   directory = _dbus_string_get_const_data (dir);
01944 
01945   if (stat (directory, &sb) < 0)
01946     {
01947       dbus_set_error (error, _dbus_error_from_errno (errno),
01948                       "%s", _dbus_strerror (errno));
01949 
01950       return FALSE;
01951     }
01952 
01953   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01954       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01955     {
01956       dbus_set_error (error, DBUS_ERROR_FAILED,
01957                      "%s directory is not private to the user", directory);
01958       return FALSE;
01959     }
01960 
01961   return TRUE;
01962 }
01963 
01964 static dbus_bool_t
01965 fill_user_info_from_passwd (struct passwd *p,
01966                             DBusUserInfo  *info,
01967                             DBusError     *error)
01968 {
01969   _dbus_assert (p->pw_name != NULL);
01970   _dbus_assert (p->pw_dir != NULL);
01971 
01972   info->uid = p->pw_uid;
01973   info->primary_gid = p->pw_gid;
01974   info->username = _dbus_strdup (p->pw_name);
01975   info->homedir = _dbus_strdup (p->pw_dir);
01976 
01977   if (info->username == NULL ||
01978       info->homedir == NULL)
01979     {
01980       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01981       return FALSE;
01982     }
01983 
01984   return TRUE;
01985 }
01986 
01987 static dbus_bool_t
01988 fill_user_info (DBusUserInfo       *info,
01989                 dbus_uid_t          uid,
01990                 const DBusString   *username,
01991                 DBusError          *error)
01992 {
01993   const char *username_c;
01994 
01995   /* exactly one of username/uid provided */
01996   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01997   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01998 
01999   info->uid = DBUS_UID_UNSET;
02000   info->primary_gid = DBUS_GID_UNSET;
02001   info->group_ids = NULL;
02002   info->n_group_ids = 0;
02003   info->username = NULL;
02004   info->homedir = NULL;
02005 
02006   if (username != NULL)
02007     username_c = _dbus_string_get_const_data (username);
02008   else
02009     username_c = NULL;
02010 
02011   /* For now assuming that the getpwnam() and getpwuid() flavors
02012    * are always symmetrical, if not we have to add more configure
02013    * checks
02014    */
02015 
02016 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
02017   {
02018     struct passwd *p;
02019     int result;
02020     size_t buflen;
02021     char *buf;
02022     struct passwd p_str;
02023 
02024     /* retrieve maximum needed size for buf */
02025     buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
02026 
02027     /* sysconf actually returns a long, but everything else expects size_t,
02028      * so just recast here.
02029      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
02030      */
02031     if ((long) buflen <= 0)
02032       buflen = 1024;
02033 
02034     result = -1;
02035     while (1)
02036       {
02037         buf = dbus_malloc (buflen);
02038         if (buf == NULL)
02039           {
02040             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02041             return FALSE;
02042           }
02043 
02044         p = NULL;
02045 #ifdef HAVE_POSIX_GETPWNAM_R
02046         if (uid != DBUS_UID_UNSET)
02047           result = getpwuid_r (uid, &p_str, buf, buflen,
02048                                &p);
02049         else
02050           result = getpwnam_r (username_c, &p_str, buf, buflen,
02051                                &p);
02052 #else
02053         if (uid != DBUS_UID_UNSET)
02054           p = getpwuid_r (uid, &p_str, buf, buflen);
02055         else
02056           p = getpwnam_r (username_c, &p_str, buf, buflen);
02057         result = 0;
02058 #endif /* !HAVE_POSIX_GETPWNAM_R */
02059         //Try a bigger buffer if ERANGE was returned
02060         if (result == ERANGE && buflen < 512 * 1024)
02061           {
02062             dbus_free (buf);
02063             buflen *= 2;
02064           }
02065         else
02066           {
02067             break;
02068           }
02069       }
02070     if (result == 0 && p == &p_str)
02071       {
02072         if (!fill_user_info_from_passwd (p, info, error))
02073           {
02074             dbus_free (buf);
02075             return FALSE;
02076           }
02077         dbus_free (buf);
02078       }
02079     else
02080       {
02081         dbus_set_error (error, _dbus_error_from_errno (errno),
02082                         "User \"%s\" unknown or no memory to allocate password entry\n",
02083                         username_c ? username_c : "???");
02084         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02085         dbus_free (buf);
02086         return FALSE;
02087       }
02088   }
02089 #else /* ! HAVE_GETPWNAM_R */
02090   {
02091     /* I guess we're screwed on thread safety here */
02092     struct passwd *p;
02093 
02094     if (uid != DBUS_UID_UNSET)
02095       p = getpwuid (uid);
02096     else
02097       p = getpwnam (username_c);
02098 
02099     if (p != NULL)
02100       {
02101         if (!fill_user_info_from_passwd (p, info, error))
02102           {
02103             return FALSE;
02104           }
02105       }
02106     else
02107       {
02108         dbus_set_error (error, _dbus_error_from_errno (errno),
02109                         "User \"%s\" unknown or no memory to allocate password entry\n",
02110                         username_c ? username_c : "???");
02111         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02112         return FALSE;
02113       }
02114   }
02115 #endif  /* ! HAVE_GETPWNAM_R */
02116 
02117   /* Fill this in so we can use it to get groups */
02118   username_c = info->username;
02119 
02120 #ifdef HAVE_GETGROUPLIST
02121   {
02122     gid_t *buf;
02123     int buf_count;
02124     int i;
02125     int initial_buf_count;
02126 
02127     initial_buf_count = 17;
02128     buf_count = initial_buf_count;
02129     buf = dbus_new (gid_t, buf_count);
02130     if (buf == NULL)
02131       {
02132         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02133         goto failed;
02134       }
02135 
02136     if (getgrouplist (username_c,
02137                       info->primary_gid,
02138                       buf, &buf_count) < 0)
02139       {
02140         gid_t *new;
02141         /* Presumed cause of negative return code: buf has insufficient
02142            entries to hold the entire group list. The Linux behavior in this
02143            case is to pass back the actual number of groups in buf_count, but
02144            on Mac OS X 10.5, buf_count is unhelpfully left alone.
02145            So as a hack, try to help out a bit by guessing a larger
02146            number of groups, within reason.. might still fail, of course,
02147            but we can at least print a more informative message.  I looked up
02148            the "right way" to do this by downloading Apple's own source code
02149            for the "id" command, and it turns out that they use an
02150            undocumented library function getgrouplist_2 (!) which is not
02151            declared in any header in /usr/include (!!). That did not seem
02152            like the way to go here.
02153         */
02154         if (buf_count == initial_buf_count)
02155           {
02156             buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
02157           }
02158         new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02159         if (new == NULL)
02160           {
02161             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02162             dbus_free (buf);
02163             goto failed;
02164           }
02165 
02166         buf = new;
02167 
02168         errno = 0;
02169         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02170           {
02171             if (errno == 0)
02172               {
02173                 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02174                             username_c, buf_count, buf_count);
02175               }
02176             else
02177               {
02178                 dbus_set_error (error,
02179                                 _dbus_error_from_errno (errno),
02180                                 "Failed to get groups for username \"%s\" primary GID "
02181                                 DBUS_GID_FORMAT ": %s\n",
02182                                 username_c, info->primary_gid,
02183                                 _dbus_strerror (errno));
02184                 dbus_free (buf);
02185                 goto failed;
02186               }
02187           }
02188       }
02189 
02190     info->group_ids = dbus_new (dbus_gid_t, buf_count);
02191     if (info->group_ids == NULL)
02192       {
02193         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02194         dbus_free (buf);
02195         goto failed;
02196       }
02197 
02198     for (i = 0; i < buf_count; ++i)
02199       info->group_ids[i] = buf[i];
02200 
02201     info->n_group_ids = buf_count;
02202 
02203     dbus_free (buf);
02204   }
02205 #else  /* HAVE_GETGROUPLIST */
02206   {
02207     /* We just get the one group ID */
02208     info->group_ids = dbus_new (dbus_gid_t, 1);
02209     if (info->group_ids == NULL)
02210       {
02211         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02212         goto failed;
02213       }
02214 
02215     info->n_group_ids = 1;
02216 
02217     (info->group_ids)[0] = info->primary_gid;
02218   }
02219 #endif /* HAVE_GETGROUPLIST */
02220 
02221   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02222 
02223   return TRUE;
02224 
02225  failed:
02226   _DBUS_ASSERT_ERROR_IS_SET (error);
02227   return FALSE;
02228 }
02229 
02238 dbus_bool_t
02239 _dbus_user_info_fill (DBusUserInfo     *info,
02240                       const DBusString *username,
02241                       DBusError        *error)
02242 {
02243   return fill_user_info (info, DBUS_UID_UNSET,
02244                          username, error);
02245 }
02246 
02255 dbus_bool_t
02256 _dbus_user_info_fill_uid (DBusUserInfo *info,
02257                           dbus_uid_t    uid,
02258                           DBusError    *error)
02259 {
02260   return fill_user_info (info, uid,
02261                          NULL, error);
02262 }
02263 
02271 dbus_bool_t
02272 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02273 {
02274   /* The POSIX spec certainly doesn't promise this, but
02275    * we need these assertions to fail as soon as we're wrong about
02276    * it so we can do the porting fixups
02277    */
02278   _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
02279   _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
02280   _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
02281 
02282   if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
02283     return FALSE;
02284   if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02285     return FALSE;
02286 
02287   return TRUE;
02288 }
02289 
02301 dbus_bool_t
02302 _dbus_append_user_from_current_process (DBusString *str)
02303 {
02304   return _dbus_string_append_uint (str,
02305                                    _dbus_geteuid ());
02306 }
02307 
02312 dbus_pid_t
02313 _dbus_getpid (void)
02314 {
02315   return getpid ();
02316 }
02317 
02321 dbus_uid_t
02322 _dbus_getuid (void)
02323 {
02324   return getuid ();
02325 }
02326 
02330 dbus_uid_t
02331 _dbus_geteuid (void)
02332 {
02333   return geteuid ();
02334 }
02335 
02342 unsigned long
02343 _dbus_pid_for_log (void)
02344 {
02345   return getpid ();
02346 }
02347 
02355 dbus_bool_t
02356 _dbus_parse_uid (const DBusString      *uid_str,
02357                  dbus_uid_t            *uid)
02358 {
02359   int end;
02360   long val;
02361 
02362   if (_dbus_string_get_length (uid_str) == 0)
02363     {
02364       _dbus_verbose ("UID string was zero length\n");
02365       return FALSE;
02366     }
02367 
02368   val = -1;
02369   end = 0;
02370   if (!_dbus_string_parse_int (uid_str, 0, &val,
02371                                &end))
02372     {
02373       _dbus_verbose ("could not parse string as a UID\n");
02374       return FALSE;
02375     }
02376 
02377   if (end != _dbus_string_get_length (uid_str))
02378     {
02379       _dbus_verbose ("string contained trailing stuff after UID\n");
02380       return FALSE;
02381     }
02382 
02383   *uid = val;
02384 
02385   return TRUE;
02386 }
02387 
02388 #if !DBUS_USE_SYNC
02389 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
02390 #endif
02391 
02398 dbus_int32_t
02399 _dbus_atomic_inc (DBusAtomic *atomic)
02400 {
02401 #if DBUS_USE_SYNC
02402   return __sync_add_and_fetch(&atomic->value, 1)-1;
02403 #else
02404   dbus_int32_t res;
02405   _DBUS_LOCK (atomic);
02406   res = atomic->value;
02407   atomic->value += 1;
02408   _DBUS_UNLOCK (atomic);
02409   return res;
02410 #endif
02411 }
02412 
02419 dbus_int32_t
02420 _dbus_atomic_dec (DBusAtomic *atomic)
02421 {
02422 #if DBUS_USE_SYNC
02423   return __sync_sub_and_fetch(&atomic->value, 1)+1;
02424 #else
02425   dbus_int32_t res;
02426 
02427   _DBUS_LOCK (atomic);
02428   res = atomic->value;
02429   atomic->value -= 1;
02430   _DBUS_UNLOCK (atomic);
02431   return res;
02432 #endif
02433 }
02434 
02442 dbus_int32_t
02443 _dbus_atomic_get (DBusAtomic *atomic)
02444 {
02445 #if DBUS_USE_SYNC
02446   __sync_synchronize ();
02447   return atomic->value;
02448 #else
02449   dbus_int32_t res;
02450 
02451   _DBUS_LOCK (atomic);
02452   res = atomic->value;
02453   _DBUS_UNLOCK (atomic);
02454   return res;
02455 #endif
02456 }
02457 
02458 #ifdef DBUS_BUILD_TESTS
02459 
02462 dbus_gid_t
02463 _dbus_getgid (void)
02464 {
02465   return getgid ();
02466 }
02467 #endif
02468 
02477 int
02478 _dbus_poll (DBusPollFD *fds,
02479             int         n_fds,
02480             int         timeout_milliseconds)
02481 {
02482 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02483   /* This big thing is a constant expression and should get optimized
02484    * out of existence. So it's more robust than a configure check at
02485    * no cost.
02486    */
02487   if (_DBUS_POLLIN == POLLIN &&
02488       _DBUS_POLLPRI == POLLPRI &&
02489       _DBUS_POLLOUT == POLLOUT &&
02490       _DBUS_POLLERR == POLLERR &&
02491       _DBUS_POLLHUP == POLLHUP &&
02492       _DBUS_POLLNVAL == POLLNVAL &&
02493       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
02494       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
02495       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
02496       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
02497       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
02498       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
02499       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
02500     {
02501       return poll ((struct pollfd*) fds,
02502                    n_fds,
02503                    timeout_milliseconds);
02504     }
02505   else
02506     {
02507       /* We have to convert the DBusPollFD to an array of
02508        * struct pollfd, poll, and convert back.
02509        */
02510       _dbus_warn ("didn't implement poll() properly for this system yet\n");
02511       return -1;
02512     }
02513 #else /* ! HAVE_POLL */
02514 
02515   fd_set read_set, write_set, err_set;
02516   int max_fd = 0;
02517   int i;
02518   struct timeval tv;
02519   int ready;
02520 
02521   FD_ZERO (&read_set);
02522   FD_ZERO (&write_set);
02523   FD_ZERO (&err_set);
02524 
02525   for (i = 0; i < n_fds; i++)
02526     {
02527       DBusPollFD *fdp = &fds[i];
02528 
02529       if (fdp->events & _DBUS_POLLIN)
02530         FD_SET (fdp->fd, &read_set);
02531 
02532       if (fdp->events & _DBUS_POLLOUT)
02533         FD_SET (fdp->fd, &write_set);
02534 
02535       FD_SET (fdp->fd, &err_set);
02536 
02537       max_fd = MAX (max_fd, fdp->fd);
02538     }
02539 
02540   tv.tv_sec = timeout_milliseconds / 1000;
02541   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02542 
02543   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02544                   timeout_milliseconds < 0 ? NULL : &tv);
02545 
02546   if (ready > 0)
02547     {
02548       for (i = 0; i < n_fds; i++)
02549         {
02550           DBusPollFD *fdp = &fds[i];
02551 
02552           fdp->revents = 0;
02553 
02554           if (FD_ISSET (fdp->fd, &read_set))
02555             fdp->revents |= _DBUS_POLLIN;
02556 
02557           if (FD_ISSET (fdp->fd, &write_set))
02558             fdp->revents |= _DBUS_POLLOUT;
02559 
02560           if (FD_ISSET (fdp->fd, &err_set))
02561             fdp->revents |= _DBUS_POLLERR;
02562         }
02563     }
02564 
02565   return ready;
02566 #endif
02567 }
02568 
02576 void
02577 _dbus_get_current_time (long *tv_sec,
02578                         long *tv_usec)
02579 {
02580   struct timeval t;
02581 
02582 #ifdef HAVE_MONOTONIC_CLOCK
02583   struct timespec ts;
02584   clock_gettime (CLOCK_MONOTONIC, &ts);
02585 
02586   if (tv_sec)
02587     *tv_sec = ts.tv_sec;
02588   if (tv_usec)
02589     *tv_usec = ts.tv_nsec / 1000;
02590 #else
02591   gettimeofday (&t, NULL);
02592 
02593   if (tv_sec)
02594     *tv_sec = t.tv_sec;
02595   if (tv_usec)
02596     *tv_usec = t.tv_usec;
02597 #endif
02598 }
02599 
02608 dbus_bool_t
02609 _dbus_create_directory (const DBusString *filename,
02610                         DBusError        *error)
02611 {
02612   const char *filename_c;
02613 
02614   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02615 
02616   filename_c = _dbus_string_get_const_data (filename);
02617 
02618   if (mkdir (filename_c, 0700) < 0)
02619     {
02620       if (errno == EEXIST)
02621         return TRUE;
02622 
02623       dbus_set_error (error, DBUS_ERROR_FAILED,
02624                       "Failed to create directory %s: %s\n",
02625                       filename_c, _dbus_strerror (errno));
02626       return FALSE;
02627     }
02628   else
02629     return TRUE;
02630 }
02631 
02642 dbus_bool_t
02643 _dbus_concat_dir_and_file (DBusString       *dir,
02644                            const DBusString *next_component)
02645 {
02646   dbus_bool_t dir_ends_in_slash;
02647   dbus_bool_t file_starts_with_slash;
02648 
02649   if (_dbus_string_get_length (dir) == 0 ||
02650       _dbus_string_get_length (next_component) == 0)
02651     return TRUE;
02652 
02653   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02654                                                     _dbus_string_get_length (dir) - 1);
02655 
02656   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02657 
02658   if (dir_ends_in_slash && file_starts_with_slash)
02659     {
02660       _dbus_string_shorten (dir, 1);
02661     }
02662   else if (!(dir_ends_in_slash || file_starts_with_slash))
02663     {
02664       if (!_dbus_string_append_byte (dir, '/'))
02665         return FALSE;
02666     }
02667 
02668   return _dbus_string_copy (next_component, 0, dir,
02669                             _dbus_string_get_length (dir));
02670 }
02671 
02673 #define NANOSECONDS_PER_SECOND       1000000000
02674 
02675 #define MICROSECONDS_PER_SECOND      1000000
02676 
02677 #define MILLISECONDS_PER_SECOND      1000
02678 
02679 #define NANOSECONDS_PER_MILLISECOND  1000000
02680 
02681 #define MICROSECONDS_PER_MILLISECOND 1000
02682 
02687 void
02688 _dbus_sleep_milliseconds (int milliseconds)
02689 {
02690 #ifdef HAVE_NANOSLEEP
02691   struct timespec req;
02692   struct timespec rem;
02693 
02694   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02695   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02696   rem.tv_sec = 0;
02697   rem.tv_nsec = 0;
02698 
02699   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02700     req = rem;
02701 #elif defined (HAVE_USLEEP)
02702   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02703 #else /* ! HAVE_USLEEP */
02704   sleep (MAX (milliseconds / 1000, 1));
02705 #endif
02706 }
02707 
02708 static dbus_bool_t
02709 _dbus_generate_pseudorandom_bytes (DBusString *str,
02710                                    int         n_bytes)
02711 {
02712   int old_len;
02713   char *p;
02714 
02715   old_len = _dbus_string_get_length (str);
02716 
02717   if (!_dbus_string_lengthen (str, n_bytes))
02718     return FALSE;
02719 
02720   p = _dbus_string_get_data_len (str, old_len, n_bytes);
02721 
02722   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02723 
02724   return TRUE;
02725 }
02726 
02735 dbus_bool_t
02736 _dbus_generate_random_bytes (DBusString *str,
02737                              int         n_bytes)
02738 {
02739   int old_len;
02740   int fd;
02741 
02742   /* FALSE return means "no memory", if it could
02743    * mean something else then we'd need to return
02744    * a DBusError. So we always fall back to pseudorandom
02745    * if the I/O fails.
02746    */
02747 
02748   old_len = _dbus_string_get_length (str);
02749   fd = -1;
02750 
02751   /* note, urandom on linux will fall back to pseudorandom */
02752   fd = open ("/dev/urandom", O_RDONLY);
02753   if (fd < 0)
02754     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02755 
02756   _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02757 
02758   if (_dbus_read (fd, str, n_bytes) != n_bytes)
02759     {
02760       _dbus_close (fd, NULL);
02761       _dbus_string_set_length (str, old_len);
02762       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02763     }
02764 
02765   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02766                  n_bytes);
02767 
02768   _dbus_close (fd, NULL);
02769 
02770   return TRUE;
02771 }
02772 
02778 void
02779 _dbus_exit (int code)
02780 {
02781   _exit (code);
02782 }
02783 
02792 const char*
02793 _dbus_strerror (int error_number)
02794 {
02795   const char *msg;
02796 
02797   msg = strerror (error_number);
02798   if (msg == NULL)
02799     msg = "unknown";
02800 
02801   return msg;
02802 }
02803 
02807 void
02808 _dbus_disable_sigpipe (void)
02809 {
02810   signal (SIGPIPE, SIG_IGN);
02811 }
02812 
02820 void
02821 _dbus_fd_set_close_on_exec (intptr_t fd)
02822 {
02823   int val;
02824 
02825   val = fcntl (fd, F_GETFD, 0);
02826 
02827   if (val < 0)
02828     return;
02829 
02830   val |= FD_CLOEXEC;
02831 
02832   fcntl (fd, F_SETFD, val);
02833 }
02834 
02842 dbus_bool_t
02843 _dbus_close (int        fd,
02844              DBusError *error)
02845 {
02846   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02847 
02848  again:
02849   if (close (fd) < 0)
02850     {
02851       if (errno == EINTR)
02852         goto again;
02853 
02854       dbus_set_error (error, _dbus_error_from_errno (errno),
02855                       "Could not close fd %d", fd);
02856       return FALSE;
02857     }
02858 
02859   return TRUE;
02860 }
02861 
02869 int
02870 _dbus_dup(int        fd,
02871           DBusError *error)
02872 {
02873   int new_fd;
02874 
02875 #ifdef F_DUPFD_CLOEXEC
02876   dbus_bool_t cloexec_done;
02877 
02878   new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
02879   cloexec_done = new_fd >= 0;
02880 
02881   if (new_fd < 0 && errno == EINVAL)
02882 #endif
02883     {
02884       new_fd = fcntl(fd, F_DUPFD, 3);
02885     }
02886 
02887   if (new_fd < 0) {
02888 
02889     dbus_set_error (error, _dbus_error_from_errno (errno),
02890                     "Could not duplicate fd %d", fd);
02891     return -1;
02892   }
02893 
02894 #ifdef F_DUPFD_CLOEXEC
02895   if (!cloexec_done)
02896 #endif
02897     {
02898       _dbus_fd_set_close_on_exec(new_fd);
02899     }
02900 
02901   return new_fd;
02902 }
02903 
02911 dbus_bool_t
02912 _dbus_set_fd_nonblocking (int             fd,
02913                           DBusError      *error)
02914 {
02915   int val;
02916 
02917   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02918 
02919   val = fcntl (fd, F_GETFL, 0);
02920   if (val < 0)
02921     {
02922       dbus_set_error (error, _dbus_error_from_errno (errno),
02923                       "Failed to get flags from file descriptor %d: %s",
02924                       fd, _dbus_strerror (errno));
02925       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02926                      _dbus_strerror (errno));
02927       return FALSE;
02928     }
02929 
02930   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02931     {
02932       dbus_set_error (error, _dbus_error_from_errno (errno),
02933                       "Failed to set nonblocking flag of file descriptor %d: %s",
02934                       fd, _dbus_strerror (errno));
02935       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02936                      fd, _dbus_strerror (errno));
02937 
02938       return FALSE;
02939     }
02940 
02941   return TRUE;
02942 }
02943 
02949 void
02950 _dbus_print_backtrace (void)
02951 {
02952 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02953   void *bt[500];
02954   int bt_size;
02955   int i;
02956   char **syms;
02957 
02958   bt_size = backtrace (bt, 500);
02959 
02960   syms = backtrace_symbols (bt, bt_size);
02961 
02962   i = 0;
02963   while (i < bt_size)
02964     {
02965       /* don't use dbus_warn since it can _dbus_abort() */
02966       fprintf (stderr, "  %s\n", syms[i]);
02967       ++i;
02968     }
02969   fflush (stderr);
02970 
02971   free (syms);
02972 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02973   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
02974 #else
02975   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02976 #endif
02977 }
02978 
02996 dbus_bool_t
02997 _dbus_full_duplex_pipe (int        *fd1,
02998                         int        *fd2,
02999                         dbus_bool_t blocking,
03000                         DBusError  *error)
03001 {
03002 #ifdef HAVE_SOCKETPAIR
03003   int fds[2];
03004   int retval;
03005 
03006 #ifdef SOCK_CLOEXEC
03007   dbus_bool_t cloexec_done;
03008 
03009   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
03010   cloexec_done = retval >= 0;
03011 
03012   if (retval < 0 && errno == EINVAL)
03013 #endif
03014     {
03015       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
03016     }
03017 
03018   if (retval < 0)
03019     {
03020       dbus_set_error (error, _dbus_error_from_errno (errno),
03021                       "Could not create full-duplex pipe");
03022       return FALSE;
03023     }
03024 
03025   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03026 
03027 #ifdef SOCK_CLOEXEC
03028   if (!cloexec_done)
03029 #endif
03030     {
03031       _dbus_fd_set_close_on_exec (fds[0]);
03032       _dbus_fd_set_close_on_exec (fds[1]);
03033     }
03034 
03035   if (!blocking &&
03036       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03037        !_dbus_set_fd_nonblocking (fds[1], NULL)))
03038     {
03039       dbus_set_error (error, _dbus_error_from_errno (errno),
03040                       "Could not set full-duplex pipe nonblocking");
03041 
03042       _dbus_close (fds[0], NULL);
03043       _dbus_close (fds[1], NULL);
03044 
03045       return FALSE;
03046     }
03047 
03048   *fd1 = fds[0];
03049   *fd2 = fds[1];
03050 
03051   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03052                  *fd1, *fd2);
03053 
03054   return TRUE;
03055 #else
03056   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
03057   dbus_set_error (error, DBUS_ERROR_FAILED,
03058                   "_dbus_full_duplex_pipe() not implemented on this OS");
03059   return FALSE;
03060 #endif
03061 }
03062 
03071 int
03072 _dbus_printf_string_upper_bound (const char *format,
03073                                  va_list     args)
03074 {
03075   char static_buf[1024];
03076   int bufsize = sizeof (static_buf);
03077   int len;
03078   va_list args_copy;
03079 
03080   DBUS_VA_COPY (args_copy, args);
03081   len = vsnprintf (static_buf, bufsize, format, args_copy);
03082   va_end (args_copy);
03083 
03084   /* If vsnprintf() returned non-negative, then either the string fits in
03085    * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
03086    * returns the number of characters that were needed, or this OS returns the
03087    * truncated length.
03088    *
03089    * We ignore the possibility that snprintf might just ignore the length and
03090    * overrun the buffer (64-bit Solaris 7), because that's pathological.
03091    * If your libc is really that bad, come back when you have a better one. */
03092   if (len == bufsize)
03093     {
03094       /* This could be the truncated length (Tru64 and IRIX have this bug),
03095        * or the real length could be coincidentally the same. Which is it?
03096        * If vsnprintf returns the truncated length, we'll go to the slow
03097        * path. */
03098       DBUS_VA_COPY (args_copy, args);
03099 
03100       if (vsnprintf (static_buf, 1, format, args_copy) == 1)
03101         len = -1;
03102 
03103       va_end (args_copy);
03104     }
03105 
03106   /* If vsnprintf() returned negative, we have to do more work.
03107    * HP-UX returns negative. */
03108   while (len < 0)
03109     {
03110       char *buf;
03111 
03112       bufsize *= 2;
03113 
03114       buf = dbus_malloc (bufsize);
03115 
03116       if (buf == NULL)
03117         return -1;
03118 
03119       DBUS_VA_COPY (args_copy, args);
03120       len = vsnprintf (buf, bufsize, format, args_copy);
03121       va_end (args_copy);
03122 
03123       dbus_free (buf);
03124 
03125       /* If the reported length is exactly the buffer size, round up to the
03126        * next size, in case vsnprintf has been returning the truncated
03127        * length */
03128       if (len == bufsize)
03129         len = -1;
03130     }
03131 
03132   return len;
03133 }
03134 
03141 const char*
03142 _dbus_get_tmpdir(void)
03143 {
03144   static const char* tmpdir = NULL;
03145 
03146   if (tmpdir == NULL)
03147     {
03148       /* TMPDIR is what glibc uses, then
03149        * glibc falls back to the P_tmpdir macro which
03150        * just expands to "/tmp"
03151        */
03152       if (tmpdir == NULL)
03153         tmpdir = getenv("TMPDIR");
03154 
03155       /* These two env variables are probably
03156        * broken, but maybe some OS uses them?
03157        */
03158       if (tmpdir == NULL)
03159         tmpdir = getenv("TMP");
03160       if (tmpdir == NULL)
03161         tmpdir = getenv("TEMP");
03162 
03163       /* And this is the sane fallback. */
03164       if (tmpdir == NULL)
03165         tmpdir = "/tmp";
03166     }
03167 
03168   _dbus_assert(tmpdir != NULL);
03169 
03170   return tmpdir;
03171 }
03172 
03192 static dbus_bool_t
03193 _read_subprocess_line_argv (const char *progpath,
03194                             dbus_bool_t path_fallback,
03195                             char       * const *argv,
03196                             DBusString *result,
03197                             DBusError  *error)
03198 {
03199   int result_pipe[2] = { -1, -1 };
03200   int errors_pipe[2] = { -1, -1 };
03201   pid_t pid;
03202   int ret;
03203   int status;
03204   int orig_len;
03205   int i;
03206 
03207   dbus_bool_t retval;
03208   sigset_t new_set, old_set;
03209 
03210   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03211   retval = FALSE;
03212 
03213   /* We need to block any existing handlers for SIGCHLD temporarily; they
03214    * will cause waitpid() below to fail.
03215    * https://bugs.freedesktop.org/show_bug.cgi?id=21347
03216    */
03217   sigemptyset (&new_set);
03218   sigaddset (&new_set, SIGCHLD);
03219   sigprocmask (SIG_BLOCK, &new_set, &old_set);
03220 
03221   orig_len = _dbus_string_get_length (result);
03222 
03223 #define READ_END        0
03224 #define WRITE_END       1
03225   if (pipe (result_pipe) < 0)
03226     {
03227       dbus_set_error (error, _dbus_error_from_errno (errno),
03228                       "Failed to create a pipe to call %s: %s",
03229                       progpath, _dbus_strerror (errno));
03230       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03231                      progpath, _dbus_strerror (errno));
03232       goto out;
03233     }
03234   if (pipe (errors_pipe) < 0)
03235     {
03236       dbus_set_error (error, _dbus_error_from_errno (errno),
03237                       "Failed to create a pipe to call %s: %s",
03238                       progpath, _dbus_strerror (errno));
03239       _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03240                      progpath, _dbus_strerror (errno));
03241       goto out;
03242     }
03243 
03244   pid = fork ();
03245   if (pid < 0)
03246     {
03247       dbus_set_error (error, _dbus_error_from_errno (errno),
03248                       "Failed to fork() to call %s: %s",
03249                       progpath, _dbus_strerror (errno));
03250       _dbus_verbose ("Failed to fork() to call %s: %s\n",
03251                      progpath, _dbus_strerror (errno));
03252       goto out;
03253     }
03254 
03255   if (pid == 0)
03256     {
03257       /* child process */
03258       int maxfds;
03259       int fd;
03260 
03261       fd = open ("/dev/null", O_RDWR);
03262       if (fd == -1)
03263         /* huh?! can't open /dev/null? */
03264         _exit (1);
03265 
03266       _dbus_verbose ("/dev/null fd %d opened\n", fd);
03267 
03268       /* set-up stdXXX */
03269       close (result_pipe[READ_END]);
03270       close (errors_pipe[READ_END]);
03271       close (0);                /* close stdin */
03272       close (1);                /* close stdout */
03273       close (2);                /* close stderr */
03274 
03275       if (dup2 (fd, 0) == -1)
03276         _exit (1);
03277       if (dup2 (result_pipe[WRITE_END], 1) == -1)
03278         _exit (1);
03279       if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03280         _exit (1);
03281 
03282       maxfds = sysconf (_SC_OPEN_MAX);
03283       /* Pick something reasonable if for some reason sysconf
03284        * says unlimited.
03285        */
03286       if (maxfds < 0)
03287         maxfds = 1024;
03288       /* close all inherited fds */
03289       for (i = 3; i < maxfds; i++)
03290         close (i);
03291 
03292       sigprocmask (SIG_SETMASK, &old_set, NULL);
03293 
03294       /* If it looks fully-qualified, try execv first */
03295       if (progpath[0] == '/')
03296         {
03297           execv (progpath, argv);
03298           /* Ok, that failed.  Now if path_fallback is given, let's
03299            * try unqualified.  This is mostly a hack to work
03300            * around systems which ship dbus-launch in /usr/bin
03301            * but everything else in /bin (because dbus-launch
03302            * depends on X11).
03303            */
03304           if (path_fallback)
03305             /* We must have a slash, because we checked above */
03306             execvp (strrchr (progpath, '/')+1, argv);
03307         }
03308       else
03309         execvp (progpath, argv);
03310 
03311       /* still nothing, we failed */
03312       _exit (1);
03313     }
03314 
03315   /* parent process */
03316   close (result_pipe[WRITE_END]);
03317   close (errors_pipe[WRITE_END]);
03318   result_pipe[WRITE_END] = -1;
03319   errors_pipe[WRITE_END] = -1;
03320 
03321   ret = 0;
03322   do
03323     {
03324       ret = _dbus_read (result_pipe[READ_END], result, 1024);
03325     }
03326   while (ret > 0);
03327 
03328   /* reap the child process to avoid it lingering as zombie */
03329   do
03330     {
03331       ret = waitpid (pid, &status, 0);
03332     }
03333   while (ret == -1 && errno == EINTR);
03334 
03335   /* We succeeded if the process exited with status 0 and
03336      anything was read */
03337   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03338     {
03339       /* The process ended with error */
03340       DBusString error_message;
03341       if (!_dbus_string_init (&error_message))
03342         {
03343           _DBUS_SET_OOM (error);
03344           goto out;
03345         }
03346 
03347       ret = 0;
03348       do
03349         {
03350           ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03351         }
03352       while (ret > 0);
03353 
03354       _dbus_string_set_length (result, orig_len);
03355       if (_dbus_string_get_length (&error_message) > 0)
03356         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03357                         "%s terminated abnormally with the following error: %s",
03358                         progpath, _dbus_string_get_data (&error_message));
03359       else
03360         dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03361                         "%s terminated abnormally without any error message",
03362                         progpath);
03363       goto out;
03364     }
03365 
03366   retval = TRUE;
03367 
03368  out:
03369   sigprocmask (SIG_SETMASK, &old_set, NULL);
03370 
03371   if (retval)
03372     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03373   else
03374     _DBUS_ASSERT_ERROR_IS_SET (error);
03375 
03376   if (result_pipe[0] != -1)
03377     close (result_pipe[0]);
03378   if (result_pipe[1] != -1)
03379     close (result_pipe[1]);
03380   if (errors_pipe[0] != -1)
03381     close (errors_pipe[0]);
03382   if (errors_pipe[1] != -1)
03383     close (errors_pipe[1]);
03384 
03385   return retval;
03386 }
03387 
03399 dbus_bool_t
03400 _dbus_get_autolaunch_address (const char *scope,
03401                               DBusString *address,
03402                               DBusError  *error)
03403 {
03404 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
03405   /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
03406    * but that's done elsewhere, and if it worked, this function wouldn't
03407    * be called.) */
03408   const char *display;
03409   static char *argv[6];
03410   int i;
03411   DBusString uuid;
03412   dbus_bool_t retval;
03413 
03414   if (_dbus_check_setuid ())
03415     {
03416       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03417                             "Unable to autolaunch when setuid");
03418       return FALSE;
03419     }
03420 
03421   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03422   retval = FALSE;
03423 
03424   /* fd.o #19997: if $DISPLAY isn't set to something useful, then
03425    * dbus-launch-x11 is just going to fail. Rather than trying to
03426    * run it, we might as well bail out early with a nice error. */
03427   display = _dbus_getenv ("DISPLAY");
03428 
03429   if (display == NULL || display[0] == '\0')
03430     {
03431       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03432           "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
03433       return FALSE;
03434     }
03435 
03436   if (!_dbus_string_init (&uuid))
03437     {
03438       _DBUS_SET_OOM (error);
03439       return FALSE;
03440     }
03441 
03442   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03443     {
03444       _DBUS_SET_OOM (error);
03445       goto out;
03446     }
03447 
03448   i = 0;
03449   argv[i] = "dbus-launch";
03450   ++i;
03451   argv[i] = "--autolaunch";
03452   ++i;
03453   argv[i] = _dbus_string_get_data (&uuid);
03454   ++i;
03455   argv[i] = "--binary-syntax";
03456   ++i;
03457   argv[i] = "--close-stderr";
03458   ++i;
03459   argv[i] = NULL;
03460   ++i;
03461 
03462   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03463 
03464   retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03465                                        TRUE,
03466                                        argv, address, error);
03467 
03468  out:
03469   _dbus_string_free (&uuid);
03470   return retval;
03471 #else
03472   dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03473       "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
03474       "set your DBUS_SESSION_BUS_ADDRESS instead");
03475   return FALSE;
03476 #endif
03477 }
03478 
03497 dbus_bool_t
03498 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
03499                                dbus_bool_t create_if_not_found,
03500                                DBusError  *error)
03501 {
03502   DBusString filename;
03503   dbus_bool_t b;
03504 
03505   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03506 
03507   b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03508   if (b)
03509     return TRUE;
03510 
03511   dbus_error_free (error);
03512 
03513   /* Fallback to the system machine ID */
03514   _dbus_string_init_const (&filename, "/etc/machine-id");
03515   return _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
03516 }
03517 
03518 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03519 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03520 
03527 dbus_bool_t
03528 _dbus_lookup_launchd_socket (DBusString *socket_path,
03529                              const char *launchd_env_var,
03530                              DBusError  *error)
03531 {
03532 #ifdef DBUS_ENABLE_LAUNCHD
03533   char *argv[4];
03534   int i;
03535 
03536   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03537 
03538   if (_dbus_check_setuid ())
03539     {
03540       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03541                             "Unable to find launchd socket when setuid");
03542       return FALSE;
03543     }
03544 
03545   i = 0;
03546   argv[i] = "launchctl";
03547   ++i;
03548   argv[i] = "getenv";
03549   ++i;
03550   argv[i] = (char*)launchd_env_var;
03551   ++i;
03552   argv[i] = NULL;
03553   ++i;
03554 
03555   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03556 
03557   if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
03558     {
03559       return FALSE;
03560     }
03561 
03562   /* no error, but no result either */
03563   if (_dbus_string_get_length(socket_path) == 0)
03564     {
03565       return FALSE;
03566     }
03567 
03568   /* strip the carriage-return */
03569   _dbus_string_shorten(socket_path, 1);
03570   return TRUE;
03571 #else /* DBUS_ENABLE_LAUNCHD */
03572   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03573                 "can't lookup socket from launchd; launchd support not compiled in");
03574   return FALSE;
03575 #endif
03576 }
03577 
03578 static dbus_bool_t
03579 _dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
03580 {
03581 #ifdef DBUS_ENABLE_LAUNCHD
03582   dbus_bool_t valid_socket;
03583   DBusString socket_path;
03584 
03585   if (_dbus_check_setuid ())
03586     {
03587       dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03588                             "Unable to find launchd socket when setuid");
03589       return FALSE;
03590     }
03591 
03592   if (!_dbus_string_init (&socket_path))
03593     {
03594       _DBUS_SET_OOM (error);
03595       return FALSE;
03596     }
03597 
03598   valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
03599 
03600   if (dbus_error_is_set(error))
03601     {
03602       _dbus_string_free(&socket_path);
03603       return FALSE;
03604     }
03605 
03606   if (!valid_socket)
03607     {
03608       dbus_set_error(error, "no socket path",
03609                 "launchd did not provide a socket path, "
03610                 "verify that org.freedesktop.dbus-session.plist is loaded!");
03611       _dbus_string_free(&socket_path);
03612       return FALSE;
03613     }
03614   if (!_dbus_string_append (address, "unix:path="))
03615     {
03616       _DBUS_SET_OOM (error);
03617       _dbus_string_free(&socket_path);
03618       return FALSE;
03619     }
03620   if (!_dbus_string_copy (&socket_path, 0, address,
03621                           _dbus_string_get_length (address)))
03622     {
03623       _DBUS_SET_OOM (error);
03624       _dbus_string_free(&socket_path);
03625       return FALSE;
03626     }
03627 
03628   _dbus_string_free(&socket_path);
03629   return TRUE;
03630 #else
03631   dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03632                 "can't lookup session address from launchd; launchd support not compiled in");
03633   return FALSE;
03634 #endif
03635 }
03636 
03656 dbus_bool_t
03657 _dbus_lookup_session_address (dbus_bool_t *supported,
03658                               DBusString  *address,
03659                               DBusError   *error)
03660 {
03661 #ifdef DBUS_ENABLE_LAUNCHD
03662   *supported = TRUE;
03663   return _dbus_lookup_session_address_launchd (address, error);
03664 #else
03665   /* On non-Mac Unix platforms, if the session address isn't already
03666    * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
03667    * fall back to the autolaunch: global default; see
03668    * init_session_address in dbus/dbus-bus.c. */
03669   *supported = FALSE;
03670   return TRUE;
03671 #endif
03672 }
03673 
03691 dbus_bool_t
03692 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03693 {
03694   const char *xdg_data_home;
03695   const char *xdg_data_dirs;
03696   DBusString servicedir_path;
03697 
03698   if (!_dbus_string_init (&servicedir_path))
03699     return FALSE;
03700 
03701   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03702   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03703 
03704   if (xdg_data_home != NULL)
03705     {
03706       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03707         goto oom;
03708     }
03709   else
03710     {
03711       const DBusString *homedir;
03712       DBusString local_share;
03713 
03714       if (!_dbus_homedir_from_current_process (&homedir))
03715         goto oom;
03716 
03717       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03718         goto oom;
03719 
03720       _dbus_string_init_const (&local_share, "/.local/share");
03721       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03722         goto oom;
03723     }
03724 
03725   if (!_dbus_string_append (&servicedir_path, ":"))
03726     goto oom;
03727 
03728   if (xdg_data_dirs != NULL)
03729     {
03730       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03731         goto oom;
03732 
03733       if (!_dbus_string_append (&servicedir_path, ":"))
03734         goto oom;
03735     }
03736   else
03737     {
03738       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03739         goto oom;
03740     }
03741 
03742   /*
03743    * add configured datadir to defaults
03744    * this may be the same as an xdg dir
03745    * however the config parser should take
03746    * care of duplicates
03747    */
03748   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
03749     goto oom;
03750 
03751   if (!_dbus_split_paths_and_append (&servicedir_path,
03752                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03753                                      dirs))
03754     goto oom;
03755 
03756   _dbus_string_free (&servicedir_path);
03757   return TRUE;
03758 
03759  oom:
03760   _dbus_string_free (&servicedir_path);
03761   return FALSE;
03762 }
03763 
03764 
03783 dbus_bool_t
03784 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03785 {
03786   const char *xdg_data_dirs;
03787   DBusString servicedir_path;
03788 
03789   if (!_dbus_string_init (&servicedir_path))
03790     return FALSE;
03791 
03792   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03793 
03794   if (xdg_data_dirs != NULL)
03795     {
03796       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03797         goto oom;
03798 
03799       if (!_dbus_string_append (&servicedir_path, ":"))
03800         goto oom;
03801     }
03802   else
03803     {
03804       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03805         goto oom;
03806     }
03807 
03808   /*
03809    * Add configured datadir to defaults. This may be the same as one
03810    * of the XDG directories. However, the config parser should take
03811    * care of the duplicates.
03812    *
03813    * Also, append /lib as counterpart of /usr/share on the root
03814    * directory (the root directory does not know /share), in order to
03815    * facilitate early boot system bus activation where /usr might not
03816    * be available.
03817    */
03818   if (!_dbus_string_append (&servicedir_path,
03819                             DBUS_DATADIR":"
03820                             "/lib:"))
03821         goto oom;
03822 
03823   if (!_dbus_split_paths_and_append (&servicedir_path,
03824                                      DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03825                                      dirs))
03826     goto oom;
03827 
03828   _dbus_string_free (&servicedir_path);
03829   return TRUE;
03830 
03831  oom:
03832   _dbus_string_free (&servicedir_path);
03833   return FALSE;
03834 }
03835 
03844 dbus_bool_t
03845 _dbus_append_system_config_file (DBusString *str)
03846 {
03847   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03848 }
03849 
03856 dbus_bool_t
03857 _dbus_append_session_config_file (DBusString *str)
03858 {
03859   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03860 }
03861 
03869 void
03870 _dbus_flush_caches (void)
03871 {
03872   _dbus_user_database_flush_system ();
03873 }
03874 
03888 dbus_bool_t
03889 _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
03890                                                 DBusCredentials *credentials)
03891 {
03892   DBusString homedir;
03893   DBusString dotdir;
03894   dbus_uid_t uid;
03895 
03896   _dbus_assert (credentials != NULL);
03897   _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03898 
03899   if (!_dbus_string_init (&homedir))
03900     return FALSE;
03901 
03902   uid = _dbus_credentials_get_unix_uid (credentials);
03903   _dbus_assert (uid != DBUS_UID_UNSET);
03904 
03905   if (!_dbus_homedir_from_uid (uid, &homedir))
03906     goto failed;
03907 
03908 #ifdef DBUS_BUILD_TESTS
03909   {
03910     const char *override;
03911 
03912     override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03913     if (override != NULL && *override != '\0')
03914       {
03915         _dbus_string_set_length (&homedir, 0);
03916         if (!_dbus_string_append (&homedir, override))
03917           goto failed;
03918 
03919         _dbus_verbose ("Using fake homedir for testing: %s\n",
03920                        _dbus_string_get_const_data (&homedir));
03921       }
03922     else
03923       {
03924         static dbus_bool_t already_warned = FALSE;
03925         if (!already_warned)
03926           {
03927             _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03928             already_warned = TRUE;
03929           }
03930       }
03931   }
03932 #endif
03933 
03934   _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03935   if (!_dbus_concat_dir_and_file (&homedir,
03936                                   &dotdir))
03937     goto failed;
03938 
03939   if (!_dbus_string_copy (&homedir, 0,
03940                           directory, _dbus_string_get_length (directory))) {
03941     goto failed;
03942   }
03943 
03944   _dbus_string_free (&homedir);
03945   return TRUE;
03946 
03947  failed:
03948   _dbus_string_free (&homedir);
03949   return FALSE;
03950 }
03951 
03952 //PENDING(kdab) docs
03953 dbus_bool_t
03954 _dbus_daemon_publish_session_bus_address (const char* addr,
03955                                           const char *scope)
03956 {
03957   return TRUE;
03958 }
03959 
03960 //PENDING(kdab) docs
03961 void
03962 _dbus_daemon_unpublish_session_bus_address (void)
03963 {
03964 
03965 }
03966 
03973 dbus_bool_t
03974 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03975 {
03976   return errno == EAGAIN || errno == EWOULDBLOCK;
03977 }
03978 
03986 dbus_bool_t
03987 _dbus_delete_directory (const DBusString *filename,
03988                         DBusError        *error)
03989 {
03990   const char *filename_c;
03991 
03992   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03993 
03994   filename_c = _dbus_string_get_const_data (filename);
03995 
03996   if (rmdir (filename_c) != 0)
03997     {
03998       dbus_set_error (error, DBUS_ERROR_FAILED,
03999                       "Failed to remove directory %s: %s\n",
04000                       filename_c, _dbus_strerror (errno));
04001       return FALSE;
04002     }
04003 
04004   return TRUE;
04005 }
04006 
04014 dbus_bool_t
04015 _dbus_socket_can_pass_unix_fd(int fd) {
04016 
04017 #ifdef SCM_RIGHTS
04018   union {
04019     struct sockaddr sa;
04020     struct sockaddr_storage storage;
04021     struct sockaddr_un un;
04022   } sa_buf;
04023 
04024   socklen_t sa_len = sizeof(sa_buf);
04025 
04026   _DBUS_ZERO(sa_buf);
04027 
04028   if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
04029     return FALSE;
04030 
04031   return sa_buf.sa.sa_family == AF_UNIX;
04032 
04033 #else
04034   return FALSE;
04035 
04036 #endif
04037 }
04038 
04039 
04040 /*
04041  * replaces the term DBUS_PREFIX in configure_time_path by the
04042  * current dbus installation directory. On unix this function is a noop
04043  *
04044  * @param configure_time_path
04045  * @return real path
04046  */
04047 const char *
04048 _dbus_replace_install_prefix (const char *configure_time_path)
04049 {
04050   return configure_time_path;
04051 }
04052 
04062 dbus_bool_t
04063 _dbus_check_setuid (void)
04064 {
04065   /* TODO: get __libc_enable_secure exported from glibc.
04066    * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
04067    */
04068 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
04069   {
04070     /* See glibc/include/unistd.h */
04071     extern int __libc_enable_secure;
04072     return __libc_enable_secure;
04073   }
04074 #elif defined(HAVE_ISSETUGID)
04075   /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
04076   return issetugid ();
04077 #else
04078   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
04079   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
04080 
04081   static dbus_bool_t check_setuid_initialised;
04082   static dbus_bool_t is_setuid;
04083 
04084   if (_DBUS_UNLIKELY (!check_setuid_initialised))
04085     {
04086 #ifdef HAVE_GETRESUID
04087       if (getresuid (&ruid, &euid, &suid) != 0 ||
04088           getresgid (&rgid, &egid, &sgid) != 0)
04089 #endif /* HAVE_GETRESUID */
04090         {
04091           suid = ruid = getuid ();
04092           sgid = rgid = getgid ();
04093           euid = geteuid ();
04094           egid = getegid ();
04095         }
04096 
04097       check_setuid_initialised = TRUE;
04098       is_setuid = (ruid != euid || ruid != suid ||
04099                    rgid != egid || rgid != sgid);
04100 
04101     }
04102   return is_setuid;
04103 #endif
04104 }
04105 
04106 /* tests in dbus-sysdeps-util.c */