00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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-file.h"
00033 #include "dbus-transport.h"
00034 #include "dbus-string.h"
00035 #include "dbus-userdb.h"
00036 #include "dbus-list.h"
00037 #include "dbus-credentials.h"
00038 #include "dbus-nonce.h"
00039
00040 #include <sys/types.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <signal.h>
00044 #include <unistd.h>
00045 #include <stdio.h>
00046 #include <fcntl.h>
00047 #include <sys/socket.h>
00048 #include <dirent.h>
00049 #include <sys/un.h>
00050 #include <pwd.h>
00051 #include <time.h>
00052 #include <locale.h>
00053 #include <sys/time.h>
00054 #include <sys/stat.h>
00055 #include <sys/wait.h>
00056 #include <netinet/in.h>
00057 #include <netinet/tcp.h>
00058 #include <netdb.h>
00059 #include <grp.h>
00060 #include <arpa/inet.h>
00061
00062 #ifdef HAVE_ERRNO_H
00063 #include <errno.h>
00064 #endif
00065 #ifdef HAVE_WRITEV
00066 #include <sys/uio.h>
00067 #endif
00068 #ifdef HAVE_POLL
00069 #include <sys/poll.h>
00070 #endif
00071 #ifdef HAVE_BACKTRACE
00072 #include <execinfo.h>
00073 #endif
00074 #ifdef HAVE_GETPEERUCRED
00075 #include <ucred.h>
00076 #endif
00077 #ifdef HAVE_ALLOCA_H
00078 #include <alloca.h>
00079 #endif
00080
00081 #ifdef HAVE_ADT
00082 #include <bsm/adt.h>
00083 #endif
00084
00085 #ifdef HAVE_SYSTEMD
00086 #include <systemd/sd-daemon.h>
00087 #endif
00088
00089 #if !DBUS_USE_SYNC
00090 #include <pthread.h>
00091 #endif
00092
00093 #ifndef O_BINARY
00094 #define O_BINARY 0
00095 #endif
00096
00097 #ifndef AI_ADDRCONFIG
00098 #define AI_ADDRCONFIG 0
00099 #endif
00100
00101 #ifndef HAVE_SOCKLEN_T
00102 #define socklen_t int
00103 #endif
00104
00105 #if defined (__sun) || defined (__sun__)
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 # ifndef CMSG_ALIGN
00117 # ifdef __sun__
00118 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
00119 # else
00120
00121 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
00122 ~(sizeof (long) - 1))
00123 # endif
00124 # endif
00125
00126 # ifndef CMSG_SPACE
00127 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
00128 CMSG_ALIGN (len))
00129 # endif
00130
00131 # ifndef CMSG_LEN
00132 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
00133 # endif
00134
00135 #endif
00136
00151 dbus_bool_t
00152 _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
00153 const char **error_str_p)
00154 {
00155 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
00156 DBUS_FORCE_STDOUT_NULL,
00157 DBUS_FORCE_STDERR_NULL };
00158
00159 const char *error_str = "Failed mysteriously";
00160 int devnull = -1;
00161 int saved_errno;
00162
00163 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
00164 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
00165 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
00166 int i;
00167
00168 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
00169 {
00170
00171
00172
00173 if (devnull < i)
00174 devnull = open ("/dev/null", O_RDWR);
00175
00176 if (devnull < 0)
00177 {
00178 error_str = "Failed to open /dev/null";
00179 goto out;
00180 }
00181
00182
00183
00184
00185 _dbus_assert (devnull >= i);
00186
00187 if (devnull != i && (flags & relevant_flag[i]) != 0)
00188 {
00189 if (dup2 (devnull, i) < 0)
00190 {
00191 error_str = "Failed to dup2 /dev/null onto a standard fd";
00192 goto out;
00193 }
00194 }
00195 }
00196
00197 error_str = NULL;
00198
00199 out:
00200 saved_errno = errno;
00201
00202 if (devnull > STDERR_FILENO)
00203 close (devnull);
00204
00205 if (error_str_p != NULL)
00206 *error_str_p = error_str;
00207
00208 errno = saved_errno;
00209 return (error_str == NULL);
00210 }
00211
00212 static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
00213 DBusError *error);
00214
00215 static dbus_bool_t
00216 _dbus_open_socket (int *fd_p,
00217 int domain,
00218 int type,
00219 int protocol,
00220 DBusError *error)
00221 {
00222 #ifdef SOCK_CLOEXEC
00223 dbus_bool_t cloexec_done;
00224
00225 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
00226 cloexec_done = *fd_p >= 0;
00227
00228
00229 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
00230 #endif
00231 {
00232 *fd_p = socket (domain, type, protocol);
00233 }
00234
00235 if (*fd_p >= 0)
00236 {
00237 #ifdef SOCK_CLOEXEC
00238 if (!cloexec_done)
00239 #endif
00240 {
00241 _dbus_fd_set_close_on_exec(*fd_p);
00242 }
00243
00244 _dbus_verbose ("socket fd %d opened\n", *fd_p);
00245 return TRUE;
00246 }
00247 else
00248 {
00249 dbus_set_error(error,
00250 _dbus_error_from_errno (errno),
00251 "Failed to open socket: %s",
00252 _dbus_strerror (errno));
00253 return FALSE;
00254 }
00255 }
00256
00267 static dbus_bool_t
00268 _dbus_open_unix_socket (int *fd,
00269 DBusError *error)
00270 {
00271 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00272 }
00273
00282 dbus_bool_t
00283 _dbus_close_socket (DBusSocket fd,
00284 DBusError *error)
00285 {
00286 return _dbus_close (fd.fd, error);
00287 }
00288
00298 int
00299 _dbus_read_socket (DBusSocket fd,
00300 DBusString *buffer,
00301 int count)
00302 {
00303 return _dbus_read (fd.fd, buffer, count);
00304 }
00305
00316 int
00317 _dbus_write_socket (DBusSocket fd,
00318 const DBusString *buffer,
00319 int start,
00320 int len)
00321 {
00322 #if HAVE_DECL_MSG_NOSIGNAL
00323 const char *data;
00324 int bytes_written;
00325
00326 data = _dbus_string_get_const_data_len (buffer, start, len);
00327
00328 again:
00329
00330 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
00331
00332 if (bytes_written < 0 && errno == EINTR)
00333 goto again;
00334
00335 return bytes_written;
00336
00337 #else
00338 return _dbus_write (fd.fd, buffer, start, len);
00339 #endif
00340 }
00341
00354 int
00355 _dbus_read_socket_with_unix_fds (DBusSocket fd,
00356 DBusString *buffer,
00357 int count,
00358 int *fds,
00359 int *n_fds) {
00360 #ifndef HAVE_UNIX_FD_PASSING
00361 int r;
00362
00363 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
00364 return r;
00365
00366 *n_fds = 0;
00367 return r;
00368
00369 #else
00370 int bytes_read;
00371 int start;
00372 struct msghdr m;
00373 struct iovec iov;
00374
00375 _dbus_assert (count >= 0);
00376 _dbus_assert (*n_fds >= 0);
00377
00378 start = _dbus_string_get_length (buffer);
00379
00380 if (!_dbus_string_lengthen (buffer, count))
00381 {
00382 errno = ENOMEM;
00383 return -1;
00384 }
00385
00386 _DBUS_ZERO(iov);
00387 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
00388 iov.iov_len = count;
00389
00390 _DBUS_ZERO(m);
00391 m.msg_iov = &iov;
00392 m.msg_iovlen = 1;
00393
00394
00395
00396
00397
00398 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
00399
00400
00401
00402 m.msg_control = alloca(m.msg_controllen);
00403 memset(m.msg_control, 0, m.msg_controllen);
00404
00405
00406
00407
00408
00409 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
00410
00411 again:
00412
00413 bytes_read = recvmsg (fd.fd, &m, 0
00414 #ifdef MSG_CMSG_CLOEXEC
00415 |MSG_CMSG_CLOEXEC
00416 #endif
00417 );
00418
00419 if (bytes_read < 0)
00420 {
00421 if (errno == EINTR)
00422 goto again;
00423 else
00424 {
00425
00426 _dbus_string_set_length (buffer, start);
00427 return -1;
00428 }
00429 }
00430 else
00431 {
00432 struct cmsghdr *cm;
00433 dbus_bool_t found = FALSE;
00434
00435 if (m.msg_flags & MSG_CTRUNC)
00436 {
00437
00438
00439
00440
00441
00442 errno = ENOSPC;
00443 _dbus_string_set_length (buffer, start);
00444 return -1;
00445 }
00446
00447 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
00448 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
00449 {
00450 size_t i;
00451 int *payload = (int *) CMSG_DATA (cm);
00452 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
00453 size_t payload_len_fds = payload_len_bytes / sizeof (int);
00454 size_t fds_to_use;
00455
00456
00457
00458
00459 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
00460
00461 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
00462 {
00463
00464 fds_to_use = payload_len_fds;
00465 }
00466 else
00467 {
00468
00469
00470
00471
00472 fds_to_use = (size_t) *n_fds;
00473
00474
00475
00476
00477 for (i = fds_to_use; i < payload_len_fds; i++)
00478 {
00479 close (payload[i]);
00480 }
00481 }
00482
00483 memcpy (fds, payload, fds_to_use * sizeof (int));
00484 found = TRUE;
00485
00486
00487 *n_fds = (int) fds_to_use;
00488
00489
00490
00491
00492 for (i = 0; i < fds_to_use; i++)
00493 _dbus_fd_set_close_on_exec(fds[i]);
00494
00495 break;
00496 }
00497
00498 if (!found)
00499 *n_fds = 0;
00500
00501
00502 _dbus_string_set_length (buffer, start + bytes_read);
00503
00504 #if 0
00505 if (bytes_read > 0)
00506 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00507 #endif
00508
00509 return bytes_read;
00510 }
00511 #endif
00512 }
00513
00514 int
00515 _dbus_write_socket_with_unix_fds(DBusSocket fd,
00516 const DBusString *buffer,
00517 int start,
00518 int len,
00519 const int *fds,
00520 int n_fds) {
00521
00522 #ifndef HAVE_UNIX_FD_PASSING
00523
00524 if (n_fds > 0) {
00525 errno = ENOTSUP;
00526 return -1;
00527 }
00528
00529 return _dbus_write_socket(fd, buffer, start, len);
00530 #else
00531 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
00532 #endif
00533 }
00534
00535 int
00536 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
00537 const DBusString *buffer1,
00538 int start1,
00539 int len1,
00540 const DBusString *buffer2,
00541 int start2,
00542 int len2,
00543 const int *fds,
00544 int n_fds) {
00545
00546 #ifndef HAVE_UNIX_FD_PASSING
00547
00548 if (n_fds > 0) {
00549 errno = ENOTSUP;
00550 return -1;
00551 }
00552
00553 return _dbus_write_socket_two(fd,
00554 buffer1, start1, len1,
00555 buffer2, start2, len2);
00556 #else
00557
00558 struct msghdr m;
00559 struct cmsghdr *cm;
00560 struct iovec iov[2];
00561 int bytes_written;
00562
00563 _dbus_assert (len1 >= 0);
00564 _dbus_assert (len2 >= 0);
00565 _dbus_assert (n_fds >= 0);
00566
00567 _DBUS_ZERO(iov);
00568 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
00569 iov[0].iov_len = len1;
00570
00571 if (buffer2)
00572 {
00573 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
00574 iov[1].iov_len = len2;
00575 }
00576
00577 _DBUS_ZERO(m);
00578 m.msg_iov = iov;
00579 m.msg_iovlen = buffer2 ? 2 : 1;
00580
00581 if (n_fds > 0)
00582 {
00583 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
00584 m.msg_control = alloca(m.msg_controllen);
00585 memset(m.msg_control, 0, m.msg_controllen);
00586
00587 cm = CMSG_FIRSTHDR(&m);
00588 cm->cmsg_level = SOL_SOCKET;
00589 cm->cmsg_type = SCM_RIGHTS;
00590 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
00591 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
00592 }
00593
00594 again:
00595
00596 bytes_written = sendmsg (fd.fd, &m, 0
00597 #if HAVE_DECL_MSG_NOSIGNAL
00598 |MSG_NOSIGNAL
00599 #endif
00600 );
00601
00602 if (bytes_written < 0 && errno == EINTR)
00603 goto again;
00604
00605 #if 0
00606 if (bytes_written > 0)
00607 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00608 #endif
00609
00610 return bytes_written;
00611 #endif
00612 }
00613
00627 int
00628 _dbus_write_socket_two (DBusSocket fd,
00629 const DBusString *buffer1,
00630 int start1,
00631 int len1,
00632 const DBusString *buffer2,
00633 int start2,
00634 int len2)
00635 {
00636 #if HAVE_DECL_MSG_NOSIGNAL
00637 struct iovec vectors[2];
00638 const char *data1;
00639 const char *data2;
00640 int bytes_written;
00641 struct msghdr m;
00642
00643 _dbus_assert (buffer1 != NULL);
00644 _dbus_assert (start1 >= 0);
00645 _dbus_assert (start2 >= 0);
00646 _dbus_assert (len1 >= 0);
00647 _dbus_assert (len2 >= 0);
00648
00649 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00650
00651 if (buffer2 != NULL)
00652 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00653 else
00654 {
00655 data2 = NULL;
00656 start2 = 0;
00657 len2 = 0;
00658 }
00659
00660 vectors[0].iov_base = (char*) data1;
00661 vectors[0].iov_len = len1;
00662 vectors[1].iov_base = (char*) data2;
00663 vectors[1].iov_len = len2;
00664
00665 _DBUS_ZERO(m);
00666 m.msg_iov = vectors;
00667 m.msg_iovlen = data2 ? 2 : 1;
00668
00669 again:
00670
00671 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
00672
00673 if (bytes_written < 0 && errno == EINTR)
00674 goto again;
00675
00676 return bytes_written;
00677
00678 #else
00679 return _dbus_write_two (fd.fd, buffer1, start1, len1,
00680 buffer2, start2, len2);
00681 #endif
00682 }
00683
00700 int
00701 _dbus_read (int fd,
00702 DBusString *buffer,
00703 int count)
00704 {
00705 int bytes_read;
00706 int start;
00707 char *data;
00708
00709 _dbus_assert (count >= 0);
00710
00711 start = _dbus_string_get_length (buffer);
00712
00713 if (!_dbus_string_lengthen (buffer, count))
00714 {
00715 errno = ENOMEM;
00716 return -1;
00717 }
00718
00719 data = _dbus_string_get_data_len (buffer, start, count);
00720
00721 again:
00722
00723 bytes_read = read (fd, data, count);
00724
00725 if (bytes_read < 0)
00726 {
00727 if (errno == EINTR)
00728 goto again;
00729 else
00730 {
00731
00732 _dbus_string_set_length (buffer, start);
00733 return -1;
00734 }
00735 }
00736 else
00737 {
00738
00739 _dbus_string_set_length (buffer, start + bytes_read);
00740
00741 #if 0
00742 if (bytes_read > 0)
00743 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00744 #endif
00745
00746 return bytes_read;
00747 }
00748 }
00749
00760 int
00761 _dbus_write (int fd,
00762 const DBusString *buffer,
00763 int start,
00764 int len)
00765 {
00766 const char *data;
00767 int bytes_written;
00768
00769 data = _dbus_string_get_const_data_len (buffer, start, len);
00770
00771 again:
00772
00773 bytes_written = write (fd, data, len);
00774
00775 if (bytes_written < 0 && errno == EINTR)
00776 goto again;
00777
00778 #if 0
00779 if (bytes_written > 0)
00780 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00781 #endif
00782
00783 return bytes_written;
00784 }
00785
00806 int
00807 _dbus_write_two (int fd,
00808 const DBusString *buffer1,
00809 int start1,
00810 int len1,
00811 const DBusString *buffer2,
00812 int start2,
00813 int len2)
00814 {
00815 _dbus_assert (buffer1 != NULL);
00816 _dbus_assert (start1 >= 0);
00817 _dbus_assert (start2 >= 0);
00818 _dbus_assert (len1 >= 0);
00819 _dbus_assert (len2 >= 0);
00820
00821 #ifdef HAVE_WRITEV
00822 {
00823 struct iovec vectors[2];
00824 const char *data1;
00825 const char *data2;
00826 int bytes_written;
00827
00828 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00829
00830 if (buffer2 != NULL)
00831 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00832 else
00833 {
00834 data2 = NULL;
00835 start2 = 0;
00836 len2 = 0;
00837 }
00838
00839 vectors[0].iov_base = (char*) data1;
00840 vectors[0].iov_len = len1;
00841 vectors[1].iov_base = (char*) data2;
00842 vectors[1].iov_len = len2;
00843
00844 again:
00845
00846 bytes_written = writev (fd,
00847 vectors,
00848 data2 ? 2 : 1);
00849
00850 if (bytes_written < 0 && errno == EINTR)
00851 goto again;
00852
00853 return bytes_written;
00854 }
00855 #else
00856 {
00857 int ret1, ret2;
00858
00859 ret1 = _dbus_write (fd, buffer1, start1, len1);
00860 if (ret1 == len1 && buffer2 != NULL)
00861 {
00862 ret2 = _dbus_write (fd, buffer2, start2, len2);
00863 if (ret2 < 0)
00864 ret2 = 0;
00865
00866 return ret1 + ret2;
00867 }
00868 else
00869 return ret1;
00870 }
00871 #endif
00872 }
00873
00874 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00875
00905 int
00906 _dbus_connect_unix_socket (const char *path,
00907 dbus_bool_t abstract,
00908 DBusError *error)
00909 {
00910 int fd;
00911 size_t path_len;
00912 struct sockaddr_un addr;
00913
00914 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00915
00916 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00917 path, abstract);
00918
00919
00920 if (!_dbus_open_unix_socket (&fd, error))
00921 {
00922 _DBUS_ASSERT_ERROR_IS_SET(error);
00923 return -1;
00924 }
00925 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00926
00927 _DBUS_ZERO (addr);
00928 addr.sun_family = AF_UNIX;
00929 path_len = strlen (path);
00930
00931 if (abstract)
00932 {
00933 #ifdef HAVE_ABSTRACT_SOCKETS
00934 addr.sun_path[0] = '\0';
00935 path_len++;
00936
00937 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00938 {
00939 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00940 "Abstract socket name too long\n");
00941 _dbus_close (fd, NULL);
00942 return -1;
00943 }
00944
00945 strncpy (&addr.sun_path[1], path, path_len);
00946
00947 #else
00948 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00949 "Operating system does not support abstract socket namespace\n");
00950 _dbus_close (fd, NULL);
00951 return -1;
00952 #endif
00953 }
00954 else
00955 {
00956 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00957 {
00958 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00959 "Socket name too long\n");
00960 _dbus_close (fd, NULL);
00961 return -1;
00962 }
00963
00964 strncpy (addr.sun_path, path, path_len);
00965 }
00966
00967 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00968 {
00969 dbus_set_error (error,
00970 _dbus_error_from_errno (errno),
00971 "Failed to connect to socket %s: %s",
00972 path, _dbus_strerror (errno));
00973
00974 _dbus_close (fd, NULL);
00975 return -1;
00976 }
00977
00978 if (!_dbus_set_fd_nonblocking (fd, error))
00979 {
00980 _DBUS_ASSERT_ERROR_IS_SET (error);
00981
00982 _dbus_close (fd, NULL);
00983 return -1;
00984 }
00985
00986 return fd;
00987 }
00988
01001 int
01002 _dbus_connect_exec (const char *path,
01003 char *const argv[],
01004 DBusError *error)
01005 {
01006 int fds[2];
01007 pid_t pid;
01008 int retval;
01009 dbus_bool_t cloexec_done = 0;
01010
01011 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01012
01013 _dbus_verbose ("connecting to process %s\n", path);
01014
01015 #ifdef SOCK_CLOEXEC
01016 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
01017 cloexec_done = (retval >= 0);
01018
01019 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
01020 #endif
01021 {
01022 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
01023 }
01024
01025 if (retval < 0)
01026 {
01027 dbus_set_error (error,
01028 _dbus_error_from_errno (errno),
01029 "Failed to create socket pair: %s",
01030 _dbus_strerror (errno));
01031 return -1;
01032 }
01033
01034 if (!cloexec_done)
01035 {
01036 _dbus_fd_set_close_on_exec (fds[0]);
01037 _dbus_fd_set_close_on_exec (fds[1]);
01038 }
01039
01040 pid = fork ();
01041 if (pid < 0)
01042 {
01043 dbus_set_error (error,
01044 _dbus_error_from_errno (errno),
01045 "Failed to fork() to call %s: %s",
01046 path, _dbus_strerror (errno));
01047 close (fds[0]);
01048 close (fds[1]);
01049 return -1;
01050 }
01051
01052 if (pid == 0)
01053 {
01054
01055 close (fds[0]);
01056
01057 dup2 (fds[1], STDIN_FILENO);
01058 dup2 (fds[1], STDOUT_FILENO);
01059
01060 if (fds[1] != STDIN_FILENO &&
01061 fds[1] != STDOUT_FILENO)
01062 close (fds[1]);
01063
01064
01065
01066
01067 _dbus_close_all ();
01068
01069 execvp (path, argv);
01070
01071 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
01072
01073 _exit(1);
01074 }
01075
01076
01077 close (fds[1]);
01078
01079 if (!_dbus_set_fd_nonblocking (fds[0], error))
01080 {
01081 _DBUS_ASSERT_ERROR_IS_SET (error);
01082
01083 close (fds[0]);
01084 return -1;
01085 }
01086
01087 return fds[0];
01088 }
01089
01107 int
01108 _dbus_listen_unix_socket (const char *path,
01109 dbus_bool_t abstract,
01110 DBusError *error)
01111 {
01112 int listen_fd;
01113 struct sockaddr_un addr;
01114 size_t path_len;
01115
01116 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01117
01118 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
01119 path, abstract);
01120
01121 if (!_dbus_open_unix_socket (&listen_fd, error))
01122 {
01123 _DBUS_ASSERT_ERROR_IS_SET(error);
01124 return -1;
01125 }
01126 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01127
01128 _DBUS_ZERO (addr);
01129 addr.sun_family = AF_UNIX;
01130 path_len = strlen (path);
01131
01132 if (abstract)
01133 {
01134 #ifdef HAVE_ABSTRACT_SOCKETS
01135
01136
01137
01138 addr.sun_path[0] = '\0';
01139 path_len++;
01140
01141 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01142 {
01143 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01144 "Abstract socket name too long\n");
01145 _dbus_close (listen_fd, NULL);
01146 return -1;
01147 }
01148
01149 strncpy (&addr.sun_path[1], path, path_len);
01150
01151 #else
01152 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
01153 "Operating system does not support abstract socket namespace\n");
01154 _dbus_close (listen_fd, NULL);
01155 return -1;
01156 #endif
01157 }
01158 else
01159 {
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 {
01171 struct stat sb;
01172
01173 if (stat (path, &sb) == 0 &&
01174 S_ISSOCK (sb.st_mode))
01175 unlink (path);
01176 }
01177
01178 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
01179 {
01180 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01181 "Socket name too long\n");
01182 _dbus_close (listen_fd, NULL);
01183 return -1;
01184 }
01185
01186 strncpy (addr.sun_path, path, path_len);
01187 }
01188
01189 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
01190 {
01191 dbus_set_error (error, _dbus_error_from_errno (errno),
01192 "Failed to bind socket \"%s\": %s",
01193 path, _dbus_strerror (errno));
01194 _dbus_close (listen_fd, NULL);
01195 return -1;
01196 }
01197
01198 if (listen (listen_fd, 30 ) < 0)
01199 {
01200 dbus_set_error (error, _dbus_error_from_errno (errno),
01201 "Failed to listen on socket \"%s\": %s",
01202 path, _dbus_strerror (errno));
01203 _dbus_close (listen_fd, NULL);
01204 return -1;
01205 }
01206
01207 if (!_dbus_set_fd_nonblocking (listen_fd, error))
01208 {
01209 _DBUS_ASSERT_ERROR_IS_SET (error);
01210 _dbus_close (listen_fd, NULL);
01211 return -1;
01212 }
01213
01214
01215
01216
01217 if (!abstract && chmod (path, 0777) < 0)
01218 _dbus_warn ("Could not set mode 0777 on socket %s\n",
01219 path);
01220
01221 return listen_fd;
01222 }
01223
01234 int
01235 _dbus_listen_systemd_sockets (DBusSocket **fds,
01236 DBusError *error)
01237 {
01238 #ifdef HAVE_SYSTEMD
01239 int r, n;
01240 int fd;
01241 DBusSocket *new_fds;
01242
01243 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01244
01245 n = sd_listen_fds (TRUE);
01246 if (n < 0)
01247 {
01248 dbus_set_error (error, _dbus_error_from_errno (-n),
01249 "Failed to acquire systemd socket: %s",
01250 _dbus_strerror (-n));
01251 return -1;
01252 }
01253
01254 if (n <= 0)
01255 {
01256 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01257 "No socket received.");
01258 return -1;
01259 }
01260
01261 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01262 {
01263 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
01264 if (r < 0)
01265 {
01266 dbus_set_error (error, _dbus_error_from_errno (-r),
01267 "Failed to verify systemd socket type: %s",
01268 _dbus_strerror (-r));
01269 return -1;
01270 }
01271
01272 if (!r)
01273 {
01274 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
01275 "Passed socket has wrong type.");
01276 return -1;
01277 }
01278 }
01279
01280
01281
01282
01283 new_fds = dbus_new (DBusSocket, n);
01284 if (!new_fds)
01285 {
01286 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
01287 "Failed to allocate file handle array.");
01288 goto fail;
01289 }
01290
01291 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01292 {
01293 if (!_dbus_set_fd_nonblocking (fd, error))
01294 {
01295 _DBUS_ASSERT_ERROR_IS_SET (error);
01296 goto fail;
01297 }
01298
01299 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
01300 }
01301
01302 *fds = new_fds;
01303 return n;
01304
01305 fail:
01306
01307 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
01308 {
01309 _dbus_close (fd, NULL);
01310 }
01311
01312 dbus_free (new_fds);
01313 return -1;
01314 #else
01315 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
01316 "dbus was compiled without systemd support");
01317 return -1;
01318 #endif
01319 }
01320
01334 DBusSocket
01335 _dbus_connect_tcp_socket (const char *host,
01336 const char *port,
01337 const char *family,
01338 DBusError *error)
01339 {
01340 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
01341 }
01342
01343 DBusSocket
01344 _dbus_connect_tcp_socket_with_nonce (const char *host,
01345 const char *port,
01346 const char *family,
01347 const char *noncefile,
01348 DBusError *error)
01349 {
01350 int saved_errno = 0;
01351 DBusSocket fd = DBUS_SOCKET_INIT;
01352 int res;
01353 struct addrinfo hints;
01354 struct addrinfo *ai, *tmp;
01355
01356 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01357
01358 _DBUS_ZERO (hints);
01359
01360 if (!family)
01361 hints.ai_family = AF_UNSPEC;
01362 else if (!strcmp(family, "ipv4"))
01363 hints.ai_family = AF_INET;
01364 else if (!strcmp(family, "ipv6"))
01365 hints.ai_family = AF_INET6;
01366 else
01367 {
01368 dbus_set_error (error,
01369 DBUS_ERROR_BAD_ADDRESS,
01370 "Unknown address family %s", family);
01371 return _dbus_socket_get_invalid ();
01372 }
01373 hints.ai_protocol = IPPROTO_TCP;
01374 hints.ai_socktype = SOCK_STREAM;
01375 hints.ai_flags = AI_ADDRCONFIG;
01376
01377 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
01378 {
01379 dbus_set_error (error,
01380 _dbus_error_from_errno (errno),
01381 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01382 host, port, gai_strerror(res), res);
01383 return _dbus_socket_get_invalid ();
01384 }
01385
01386 tmp = ai;
01387 while (tmp)
01388 {
01389 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
01390 {
01391 freeaddrinfo(ai);
01392 _DBUS_ASSERT_ERROR_IS_SET(error);
01393 return _dbus_socket_get_invalid ();
01394 }
01395 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01396
01397 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01398 {
01399 saved_errno = errno;
01400 _dbus_close (fd.fd, NULL);
01401 fd.fd = -1;
01402 tmp = tmp->ai_next;
01403 continue;
01404 }
01405
01406 break;
01407 }
01408 freeaddrinfo(ai);
01409
01410 if (fd.fd == -1)
01411 {
01412 dbus_set_error (error,
01413 _dbus_error_from_errno (saved_errno),
01414 "Failed to connect to socket \"%s:%s\" %s",
01415 host, port, _dbus_strerror(saved_errno));
01416 return _dbus_socket_get_invalid ();
01417 }
01418
01419 if (noncefile != NULL)
01420 {
01421 DBusString noncefileStr;
01422 dbus_bool_t ret;
01423 _dbus_string_init_const (&noncefileStr, noncefile);
01424 ret = _dbus_send_nonce (fd, &noncefileStr, error);
01425 _dbus_string_free (&noncefileStr);
01426
01427 if (!ret)
01428 {
01429 _dbus_close (fd.fd, NULL);
01430 return _dbus_socket_get_invalid ();
01431 }
01432 }
01433
01434 if (!_dbus_set_fd_nonblocking (fd.fd, error))
01435 {
01436 _dbus_close (fd.fd, NULL);
01437 return _dbus_socket_get_invalid ();
01438 }
01439
01440 return fd;
01441 }
01442
01459 int
01460 _dbus_listen_tcp_socket (const char *host,
01461 const char *port,
01462 const char *family,
01463 DBusString *retport,
01464 DBusSocket **fds_p,
01465 DBusError *error)
01466 {
01467 int saved_errno;
01468 int nlisten_fd = 0, res, i;
01469 DBusSocket *listen_fd = NULL;
01470 struct addrinfo hints;
01471 struct addrinfo *ai, *tmp;
01472 unsigned int reuseaddr;
01473
01474 *fds_p = NULL;
01475 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01476
01477 _DBUS_ZERO (hints);
01478
01479 if (!family)
01480 hints.ai_family = AF_UNSPEC;
01481 else if (!strcmp(family, "ipv4"))
01482 hints.ai_family = AF_INET;
01483 else if (!strcmp(family, "ipv6"))
01484 hints.ai_family = AF_INET6;
01485 else
01486 {
01487 dbus_set_error (error,
01488 DBUS_ERROR_BAD_ADDRESS,
01489 "Unknown address family %s", family);
01490 return -1;
01491 }
01492
01493 hints.ai_protocol = IPPROTO_TCP;
01494 hints.ai_socktype = SOCK_STREAM;
01495 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
01496
01497 redo_lookup_with_port:
01498 ai = NULL;
01499 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
01500 {
01501 dbus_set_error (error,
01502 _dbus_error_from_errno (errno),
01503 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
01504 host ? host : "*", port, gai_strerror(res), res);
01505 goto failed;
01506 }
01507
01508 tmp = ai;
01509 while (tmp)
01510 {
01511 int fd = -1, tcp_nodelay_on;
01512 DBusSocket *newlisten_fd;
01513
01514 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
01515 {
01516 _DBUS_ASSERT_ERROR_IS_SET(error);
01517 goto failed;
01518 }
01519 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
01520
01521 reuseaddr = 1;
01522 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
01523 {
01524 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
01525 host ? host : "*", port, _dbus_strerror (errno));
01526 }
01527
01528
01529
01530 tcp_nodelay_on = 1;
01531 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
01532 {
01533 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
01534 host ? host : "*", port, _dbus_strerror (errno));
01535 }
01536
01537 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
01538 {
01539 saved_errno = errno;
01540 _dbus_close(fd, NULL);
01541 if (saved_errno == EADDRINUSE)
01542 {
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555 tmp = tmp->ai_next;
01556 continue;
01557 }
01558 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01559 "Failed to bind socket \"%s:%s\": %s",
01560 host ? host : "*", port, _dbus_strerror (saved_errno));
01561 goto failed;
01562 }
01563
01564 if (listen (fd, 30 ) < 0)
01565 {
01566 saved_errno = errno;
01567 _dbus_close (fd, NULL);
01568 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01569 "Failed to listen on socket \"%s:%s\": %s",
01570 host ? host : "*", port, _dbus_strerror (saved_errno));
01571 goto failed;
01572 }
01573
01574 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
01575 if (!newlisten_fd)
01576 {
01577 saved_errno = errno;
01578 _dbus_close (fd, NULL);
01579 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
01580 "Failed to allocate file handle array: %s",
01581 _dbus_strerror (saved_errno));
01582 goto failed;
01583 }
01584 listen_fd = newlisten_fd;
01585 listen_fd[nlisten_fd].fd = fd;
01586 nlisten_fd++;
01587
01588 if (!_dbus_string_get_length(retport))
01589 {
01590
01591
01592
01593
01594 if (!port || !strcmp(port, "0"))
01595 {
01596 int result;
01597 struct sockaddr_storage addr;
01598 socklen_t addrlen;
01599 char portbuf[50];
01600
01601 addrlen = sizeof(addr);
01602 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
01603
01604 if (result == -1 ||
01605 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
01606 portbuf, sizeof(portbuf),
01607 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
01608 {
01609 dbus_set_error (error, _dbus_error_from_errno (errno),
01610 "Failed to resolve port \"%s:%s\": %s (%s)",
01611 host ? host : "*", port, gai_strerror(res), res);
01612 goto failed;
01613 }
01614 if (!_dbus_string_append(retport, portbuf))
01615 {
01616 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01617 goto failed;
01618 }
01619
01620
01621 port = _dbus_string_get_const_data(retport);
01622 freeaddrinfo(ai);
01623 goto redo_lookup_with_port;
01624 }
01625 else
01626 {
01627 if (!_dbus_string_append(retport, port))
01628 {
01629 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01630 goto failed;
01631 }
01632 }
01633 }
01634
01635 tmp = tmp->ai_next;
01636 }
01637 freeaddrinfo(ai);
01638 ai = NULL;
01639
01640 if (!nlisten_fd)
01641 {
01642 errno = EADDRINUSE;
01643 dbus_set_error (error, _dbus_error_from_errno (errno),
01644 "Failed to bind socket \"%s:%s\": %s",
01645 host ? host : "*", port, _dbus_strerror (errno));
01646 goto failed;
01647 }
01648
01649 for (i = 0 ; i < nlisten_fd ; i++)
01650 {
01651 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
01652 {
01653 goto failed;
01654 }
01655 }
01656
01657 *fds_p = listen_fd;
01658
01659 return nlisten_fd;
01660
01661 failed:
01662 if (ai)
01663 freeaddrinfo(ai);
01664 for (i = 0 ; i < nlisten_fd ; i++)
01665 _dbus_close(listen_fd[i].fd, NULL);
01666 dbus_free(listen_fd);
01667 return -1;
01668 }
01669
01670 static dbus_bool_t
01671 write_credentials_byte (int server_fd,
01672 DBusError *error)
01673 {
01674 int bytes_written;
01675 char buf[1] = { '\0' };
01676 #if defined(HAVE_CMSGCRED)
01677 union {
01678 struct cmsghdr hdr;
01679 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01680 } cmsg;
01681 struct iovec iov;
01682 struct msghdr msg;
01683 iov.iov_base = buf;
01684 iov.iov_len = 1;
01685
01686 _DBUS_ZERO(msg);
01687 msg.msg_iov = &iov;
01688 msg.msg_iovlen = 1;
01689
01690 msg.msg_control = (caddr_t) &cmsg;
01691 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01692 _DBUS_ZERO(cmsg);
01693 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01694 cmsg.hdr.cmsg_level = SOL_SOCKET;
01695 cmsg.hdr.cmsg_type = SCM_CREDS;
01696 #endif
01697
01698 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01699
01700 again:
01701
01702 #if defined(HAVE_CMSGCRED)
01703 bytes_written = sendmsg (server_fd, &msg, 0
01704 #if HAVE_DECL_MSG_NOSIGNAL
01705 |MSG_NOSIGNAL
01706 #endif
01707 );
01708
01709
01710
01711
01712 if (bytes_written < 0 && errno == EINVAL)
01713 #endif
01714 {
01715 bytes_written = send (server_fd, buf, 1, 0
01716 #if HAVE_DECL_MSG_NOSIGNAL
01717 |MSG_NOSIGNAL
01718 #endif
01719 );
01720 }
01721
01722 if (bytes_written < 0 && errno == EINTR)
01723 goto again;
01724
01725 if (bytes_written < 0)
01726 {
01727 dbus_set_error (error, _dbus_error_from_errno (errno),
01728 "Failed to write credentials byte: %s",
01729 _dbus_strerror (errno));
01730 return FALSE;
01731 }
01732 else if (bytes_written == 0)
01733 {
01734 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01735 "wrote zero bytes writing credentials byte");
01736 return FALSE;
01737 }
01738 else
01739 {
01740 _dbus_assert (bytes_written == 1);
01741 _dbus_verbose ("wrote credentials byte\n");
01742 return TRUE;
01743 }
01744 }
01745
01746
01747 static dbus_bool_t
01748 add_linux_security_label_to_credentials (int client_fd,
01749 DBusCredentials *credentials)
01750 {
01751 #if defined(__linux__) && defined(SO_PEERSEC)
01752 DBusString buf;
01753 socklen_t len = 1024;
01754 dbus_bool_t oom = FALSE;
01755
01756 if (!_dbus_string_init_preallocated (&buf, len) ||
01757 !_dbus_string_set_length (&buf, len))
01758 return FALSE;
01759
01760 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
01761 _dbus_string_get_data (&buf), &len) < 0)
01762 {
01763 int e = errno;
01764
01765 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
01766 _dbus_strerror (e), (unsigned long) len);
01767
01768 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
01769 {
01770 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
01771 _dbus_strerror (e));
01772 goto out;
01773 }
01774
01775
01776
01777 if (!_dbus_string_set_length (&buf, len))
01778 {
01779 oom = TRUE;
01780 goto out;
01781 }
01782
01783 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
01784 }
01785
01786 if (len <= 0)
01787 {
01788 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
01789 (unsigned long) len);
01790 goto out;
01791 }
01792
01793 if (len > _dbus_string_get_length_uint (&buf))
01794 {
01795 _dbus_verbose ("%lu > %u", (unsigned long) len,
01796 _dbus_string_get_length_uint (&buf));
01797 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
01798 }
01799
01800 if (_dbus_string_get_byte (&buf, len - 1) == 0)
01801 {
01802
01803
01804 _dbus_verbose ("subtracting trailing \\0\n");
01805 len--;
01806 }
01807
01808 if (!_dbus_string_set_length (&buf, len))
01809 {
01810 _dbus_assert_not_reached ("shortening string should not lead to OOM");
01811 oom = TRUE;
01812 goto out;
01813 }
01814
01815 if (strlen (_dbus_string_get_const_data (&buf)) != len)
01816 {
01817
01818
01819
01820 _dbus_verbose ("security label from kernel had an embedded \\0, "
01821 "ignoring it\n");
01822 goto out;
01823 }
01824
01825 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
01826 (unsigned long) len,
01827 _dbus_string_get_const_data (&buf));
01828
01829 if (!_dbus_credentials_add_linux_security_label (credentials,
01830 _dbus_string_get_const_data (&buf)))
01831 {
01832 oom = TRUE;
01833 goto out;
01834 }
01835
01836 out:
01837 _dbus_string_free (&buf);
01838 return !oom;
01839 #else
01840
01841 return TRUE;
01842 #endif
01843 }
01844
01885 dbus_bool_t
01886 _dbus_read_credentials_socket (DBusSocket client_fd,
01887 DBusCredentials *credentials,
01888 DBusError *error)
01889 {
01890 struct msghdr msg;
01891 struct iovec iov;
01892 char buf;
01893 dbus_uid_t uid_read;
01894 dbus_pid_t pid_read;
01895 int bytes_read;
01896
01897 #ifdef HAVE_CMSGCRED
01898 union {
01899 struct cmsghdr hdr;
01900 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01901 } cmsg;
01902 #endif
01903
01904
01905
01906
01907
01908 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
01909 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
01910 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
01911
01912 uid_read = DBUS_UID_UNSET;
01913 pid_read = DBUS_PID_UNSET;
01914
01915 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01916
01917 _dbus_credentials_clear (credentials);
01918
01919 iov.iov_base = &buf;
01920 iov.iov_len = 1;
01921
01922 _DBUS_ZERO(msg);
01923 msg.msg_iov = &iov;
01924 msg.msg_iovlen = 1;
01925
01926 #if defined(HAVE_CMSGCRED)
01927 _DBUS_ZERO(cmsg);
01928 msg.msg_control = (caddr_t) &cmsg;
01929 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01930 #endif
01931
01932 again:
01933 bytes_read = recvmsg (client_fd.fd, &msg, 0);
01934
01935 if (bytes_read < 0)
01936 {
01937 if (errno == EINTR)
01938 goto again;
01939
01940
01941
01942
01943
01944
01945 dbus_set_error (error, _dbus_error_from_errno (errno),
01946 "Failed to read credentials byte: %s",
01947 _dbus_strerror (errno));
01948 return FALSE;
01949 }
01950 else if (bytes_read == 0)
01951 {
01952
01953
01954
01955 dbus_set_error (error, DBUS_ERROR_FAILED,
01956 "Failed to read credentials byte (zero-length read)");
01957 return FALSE;
01958 }
01959 else if (buf != '\0')
01960 {
01961 dbus_set_error (error, DBUS_ERROR_FAILED,
01962 "Credentials byte was not nul");
01963 return FALSE;
01964 }
01965
01966 _dbus_verbose ("read credentials byte\n");
01967
01968 {
01969 #ifdef SO_PEERCRED
01970
01971
01972
01973
01974
01975
01976
01977
01978 #ifdef __OpenBSD__
01979 struct sockpeercred cr;
01980 #else
01981 struct ucred cr;
01982 #endif
01983 int cr_len = sizeof (cr);
01984
01985 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
01986 {
01987 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
01988 _dbus_strerror (errno));
01989 }
01990 else if (cr_len != sizeof (cr))
01991 {
01992 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
01993 cr_len, (int) sizeof (cr));
01994 }
01995 else
01996 {
01997 pid_read = cr.pid;
01998 uid_read = cr.uid;
01999 }
02000 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
02001
02002
02003 struct unpcbid cr;
02004 socklen_t cr_len = sizeof (cr);
02005
02006 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
02007 {
02008 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
02009 _dbus_strerror (errno));
02010 }
02011 else if (cr_len != sizeof (cr))
02012 {
02013 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
02014 cr_len, (int) sizeof (cr));
02015 }
02016 else
02017 {
02018 pid_read = cr.unp_pid;
02019 uid_read = cr.unp_euid;
02020 }
02021 #elif defined(HAVE_CMSGCRED)
02022
02023
02024
02025
02026
02027
02028
02029
02030 struct cmsgcred *cred;
02031 struct cmsghdr *cmsgp;
02032
02033 for (cmsgp = CMSG_FIRSTHDR (&msg);
02034 cmsgp != NULL;
02035 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
02036 {
02037 if (cmsgp->cmsg_type == SCM_CREDS &&
02038 cmsgp->cmsg_level == SOL_SOCKET &&
02039 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
02040 {
02041 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
02042 pid_read = cred->cmcred_pid;
02043 uid_read = cred->cmcred_euid;
02044 break;
02045 }
02046 }
02047
02048 #elif defined(HAVE_GETPEERUCRED)
02049
02050
02051
02052 ucred_t * ucred = NULL;
02053 if (getpeerucred (client_fd.fd, &ucred) == 0)
02054 {
02055 pid_read = ucred_getpid (ucred);
02056 uid_read = ucred_geteuid (ucred);
02057 #ifdef HAVE_ADT
02058
02059 adt_session_data_t *adth = NULL;
02060 adt_export_data_t *data = NULL;
02061 size_t size = 0;
02062 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
02063 {
02064 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
02065 }
02066 else
02067 {
02068 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
02069 {
02070 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
02071 }
02072 else
02073 {
02074 size = adt_export_session_data (adth, &data);
02075 if (size <= 0)
02076 {
02077 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
02078 }
02079 else
02080 {
02081 _dbus_credentials_add_adt_audit_data (credentials, data, size);
02082 free (data);
02083 }
02084 }
02085 (void) adt_end_session (adth);
02086 }
02087 #endif
02088 }
02089 else
02090 {
02091 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
02092 }
02093 if (ucred != NULL)
02094 ucred_free (ucred);
02095
02096
02097
02098
02099
02100
02101 #elif defined(HAVE_GETPEEREID)
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117 uid_t euid;
02118 gid_t egid;
02119 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
02120 {
02121 uid_read = euid;
02122 }
02123 else
02124 {
02125 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
02126 }
02127 #else
02128
02129 #warning Socket credentials not supported on this Unix OS
02130 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
02131
02132
02133
02134
02135
02136 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
02137 defined(__linux__) || \
02138 defined(__OpenBSD__) || \
02139 defined(__NetBSD__)
02140 # error Credentials passing not working on this OS is a regression!
02141 #endif
02142
02143 _dbus_verbose ("Socket credentials not supported on this OS\n");
02144 #endif
02145 }
02146
02147 _dbus_verbose ("Credentials:"
02148 " pid "DBUS_PID_FORMAT
02149 " uid "DBUS_UID_FORMAT
02150 "\n",
02151 pid_read,
02152 uid_read);
02153
02154 if (pid_read != DBUS_PID_UNSET)
02155 {
02156 if (!_dbus_credentials_add_pid (credentials, pid_read))
02157 {
02158 _DBUS_SET_OOM (error);
02159 return FALSE;
02160 }
02161 }
02162
02163 if (uid_read != DBUS_UID_UNSET)
02164 {
02165 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
02166 {
02167 _DBUS_SET_OOM (error);
02168 return FALSE;
02169 }
02170 }
02171
02172 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
02173 {
02174 _DBUS_SET_OOM (error);
02175 return FALSE;
02176 }
02177
02178 return TRUE;
02179 }
02180
02198 dbus_bool_t
02199 _dbus_send_credentials_socket (DBusSocket server_fd,
02200 DBusError *error)
02201 {
02202 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02203
02204 if (write_credentials_byte (server_fd.fd, error))
02205 return TRUE;
02206 else
02207 return FALSE;
02208 }
02209
02219 DBusSocket
02220 _dbus_accept (DBusSocket listen_fd)
02221 {
02222 DBusSocket client_fd;
02223 struct sockaddr addr;
02224 socklen_t addrlen;
02225 #ifdef HAVE_ACCEPT4
02226 dbus_bool_t cloexec_done;
02227 #endif
02228
02229 addrlen = sizeof (addr);
02230
02231 retry:
02232
02233 #ifdef HAVE_ACCEPT4
02234
02235
02236
02237
02238
02239 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
02240 cloexec_done = client_fd.fd >= 0;
02241
02242 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
02243 #endif
02244 {
02245 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
02246 }
02247
02248 if (client_fd.fd < 0)
02249 {
02250 if (errno == EINTR)
02251 goto retry;
02252 }
02253
02254 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
02255
02256 #ifdef HAVE_ACCEPT4
02257 if (!cloexec_done)
02258 #endif
02259 {
02260 _dbus_fd_set_close_on_exec(client_fd.fd);
02261 }
02262
02263 return client_fd;
02264 }
02265
02274 dbus_bool_t
02275 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
02276 {
02277 const char *directory;
02278 struct stat sb;
02279
02280 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02281
02282 directory = _dbus_string_get_const_data (dir);
02283
02284 if (stat (directory, &sb) < 0)
02285 {
02286 dbus_set_error (error, _dbus_error_from_errno (errno),
02287 "%s", _dbus_strerror (errno));
02288
02289 return FALSE;
02290 }
02291
02292 if (sb.st_uid != geteuid ())
02293 {
02294 dbus_set_error (error, DBUS_ERROR_FAILED,
02295 "%s directory is owned by user %lu, not %lu",
02296 directory,
02297 (unsigned long) sb.st_uid,
02298 (unsigned long) geteuid ());
02299 return FALSE;
02300 }
02301
02302 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
02303 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
02304 {
02305 dbus_set_error (error, DBUS_ERROR_FAILED,
02306 "%s directory is not private to the user", directory);
02307 return FALSE;
02308 }
02309
02310 return TRUE;
02311 }
02312
02313 static dbus_bool_t
02314 fill_user_info_from_passwd (struct passwd *p,
02315 DBusUserInfo *info,
02316 DBusError *error)
02317 {
02318 _dbus_assert (p->pw_name != NULL);
02319 _dbus_assert (p->pw_dir != NULL);
02320
02321 info->uid = p->pw_uid;
02322 info->primary_gid = p->pw_gid;
02323 info->username = _dbus_strdup (p->pw_name);
02324 info->homedir = _dbus_strdup (p->pw_dir);
02325
02326 if (info->username == NULL ||
02327 info->homedir == NULL)
02328 {
02329 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02330 return FALSE;
02331 }
02332
02333 return TRUE;
02334 }
02335
02336 static dbus_bool_t
02337 fill_user_info (DBusUserInfo *info,
02338 dbus_uid_t uid,
02339 const DBusString *username,
02340 DBusError *error)
02341 {
02342 const char *username_c;
02343
02344
02345 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
02346 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
02347
02348 info->uid = DBUS_UID_UNSET;
02349 info->primary_gid = DBUS_GID_UNSET;
02350 info->group_ids = NULL;
02351 info->n_group_ids = 0;
02352 info->username = NULL;
02353 info->homedir = NULL;
02354
02355 if (username != NULL)
02356 username_c = _dbus_string_get_const_data (username);
02357 else
02358 username_c = NULL;
02359
02360
02361
02362
02363
02364
02365 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
02366 {
02367 struct passwd *p;
02368 int result;
02369 size_t buflen;
02370 char *buf;
02371 struct passwd p_str;
02372
02373
02374 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
02375
02376
02377
02378
02379
02380 if ((long) buflen <= 0)
02381 buflen = 1024;
02382
02383 result = -1;
02384 while (1)
02385 {
02386 buf = dbus_malloc (buflen);
02387 if (buf == NULL)
02388 {
02389 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02390 return FALSE;
02391 }
02392
02393 p = NULL;
02394 #ifdef HAVE_POSIX_GETPWNAM_R
02395 if (uid != DBUS_UID_UNSET)
02396 result = getpwuid_r (uid, &p_str, buf, buflen,
02397 &p);
02398 else
02399 result = getpwnam_r (username_c, &p_str, buf, buflen,
02400 &p);
02401 #else
02402 if (uid != DBUS_UID_UNSET)
02403 p = getpwuid_r (uid, &p_str, buf, buflen);
02404 else
02405 p = getpwnam_r (username_c, &p_str, buf, buflen);
02406 result = 0;
02407 #endif
02408
02409 if (result == ERANGE && buflen < 512 * 1024)
02410 {
02411 dbus_free (buf);
02412 buflen *= 2;
02413 }
02414 else
02415 {
02416 break;
02417 }
02418 }
02419 if (result == 0 && p == &p_str)
02420 {
02421 if (!fill_user_info_from_passwd (p, info, error))
02422 {
02423 dbus_free (buf);
02424 return FALSE;
02425 }
02426 dbus_free (buf);
02427 }
02428 else
02429 {
02430 dbus_set_error (error, _dbus_error_from_errno (errno),
02431 "User \"%s\" unknown or no memory to allocate password entry\n",
02432 username_c ? username_c : "???");
02433 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02434 dbus_free (buf);
02435 return FALSE;
02436 }
02437 }
02438 #else
02439 {
02440
02441 struct passwd *p;
02442
02443 if (uid != DBUS_UID_UNSET)
02444 p = getpwuid (uid);
02445 else
02446 p = getpwnam (username_c);
02447
02448 if (p != NULL)
02449 {
02450 if (!fill_user_info_from_passwd (p, info, error))
02451 {
02452 return FALSE;
02453 }
02454 }
02455 else
02456 {
02457 dbus_set_error (error, _dbus_error_from_errno (errno),
02458 "User \"%s\" unknown or no memory to allocate password entry\n",
02459 username_c ? username_c : "???");
02460 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
02461 return FALSE;
02462 }
02463 }
02464 #endif
02465
02466
02467 username_c = info->username;
02468
02469 #ifdef HAVE_GETGROUPLIST
02470 {
02471 gid_t *buf;
02472 int buf_count;
02473 int i;
02474 int initial_buf_count;
02475
02476 initial_buf_count = 17;
02477 buf_count = initial_buf_count;
02478 buf = dbus_new (gid_t, buf_count);
02479 if (buf == NULL)
02480 {
02481 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02482 goto failed;
02483 }
02484
02485 if (getgrouplist (username_c,
02486 info->primary_gid,
02487 buf, &buf_count) < 0)
02488 {
02489 gid_t *new;
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503 if (buf_count == initial_buf_count)
02504 {
02505 buf_count *= 16;
02506 }
02507 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
02508 if (new == NULL)
02509 {
02510 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02511 dbus_free (buf);
02512 goto failed;
02513 }
02514
02515 buf = new;
02516
02517 errno = 0;
02518 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
02519 {
02520 if (errno == 0)
02521 {
02522 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
02523 username_c, buf_count, buf_count);
02524 }
02525 else
02526 {
02527 dbus_set_error (error,
02528 _dbus_error_from_errno (errno),
02529 "Failed to get groups for username \"%s\" primary GID "
02530 DBUS_GID_FORMAT ": %s\n",
02531 username_c, info->primary_gid,
02532 _dbus_strerror (errno));
02533 dbus_free (buf);
02534 goto failed;
02535 }
02536 }
02537 }
02538
02539 info->group_ids = dbus_new (dbus_gid_t, buf_count);
02540 if (info->group_ids == NULL)
02541 {
02542 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02543 dbus_free (buf);
02544 goto failed;
02545 }
02546
02547 for (i = 0; i < buf_count; ++i)
02548 info->group_ids[i] = buf[i];
02549
02550 info->n_group_ids = buf_count;
02551
02552 dbus_free (buf);
02553 }
02554 #else
02555 {
02556
02557 info->group_ids = dbus_new (dbus_gid_t, 1);
02558 if (info->group_ids == NULL)
02559 {
02560 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02561 goto failed;
02562 }
02563
02564 info->n_group_ids = 1;
02565
02566 (info->group_ids)[0] = info->primary_gid;
02567 }
02568 #endif
02569
02570 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02571
02572 return TRUE;
02573
02574 failed:
02575 _DBUS_ASSERT_ERROR_IS_SET (error);
02576 return FALSE;
02577 }
02578
02587 dbus_bool_t
02588 _dbus_user_info_fill (DBusUserInfo *info,
02589 const DBusString *username,
02590 DBusError *error)
02591 {
02592 return fill_user_info (info, DBUS_UID_UNSET,
02593 username, error);
02594 }
02595
02604 dbus_bool_t
02605 _dbus_user_info_fill_uid (DBusUserInfo *info,
02606 dbus_uid_t uid,
02607 DBusError *error)
02608 {
02609 return fill_user_info (info, uid,
02610 NULL, error);
02611 }
02612
02620 dbus_bool_t
02621 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
02622 {
02623
02624
02625
02626
02627 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
02628 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
02629 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
02630
02631 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
02632 return FALSE;
02633 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
02634 return FALSE;
02635
02636 return TRUE;
02637 }
02638
02650 dbus_bool_t
02651 _dbus_append_user_from_current_process (DBusString *str)
02652 {
02653 return _dbus_string_append_uint (str,
02654 _dbus_geteuid ());
02655 }
02656
02661 dbus_pid_t
02662 _dbus_getpid (void)
02663 {
02664 return getpid ();
02665 }
02666
02670 dbus_uid_t
02671 _dbus_getuid (void)
02672 {
02673 return getuid ();
02674 }
02675
02679 dbus_uid_t
02680 _dbus_geteuid (void)
02681 {
02682 return geteuid ();
02683 }
02684
02691 unsigned long
02692 _dbus_pid_for_log (void)
02693 {
02694 return getpid ();
02695 }
02696
02704 dbus_bool_t
02705 _dbus_parse_uid (const DBusString *uid_str,
02706 dbus_uid_t *uid)
02707 {
02708 int end;
02709 long val;
02710
02711 if (_dbus_string_get_length (uid_str) == 0)
02712 {
02713 _dbus_verbose ("UID string was zero length\n");
02714 return FALSE;
02715 }
02716
02717 val = -1;
02718 end = 0;
02719 if (!_dbus_string_parse_int (uid_str, 0, &val,
02720 &end))
02721 {
02722 _dbus_verbose ("could not parse string as a UID\n");
02723 return FALSE;
02724 }
02725
02726 if (end != _dbus_string_get_length (uid_str))
02727 {
02728 _dbus_verbose ("string contained trailing stuff after UID\n");
02729 return FALSE;
02730 }
02731
02732 *uid = val;
02733
02734 return TRUE;
02735 }
02736
02737 #if !DBUS_USE_SYNC
02738
02739
02740
02741
02742
02743 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
02744 #endif
02745
02752 dbus_int32_t
02753 _dbus_atomic_inc (DBusAtomic *atomic)
02754 {
02755 #if DBUS_USE_SYNC
02756 return __sync_add_and_fetch(&atomic->value, 1)-1;
02757 #else
02758 dbus_int32_t res;
02759
02760 pthread_mutex_lock (&atomic_mutex);
02761 res = atomic->value;
02762 atomic->value += 1;
02763 pthread_mutex_unlock (&atomic_mutex);
02764
02765 return res;
02766 #endif
02767 }
02768
02775 dbus_int32_t
02776 _dbus_atomic_dec (DBusAtomic *atomic)
02777 {
02778 #if DBUS_USE_SYNC
02779 return __sync_sub_and_fetch(&atomic->value, 1)+1;
02780 #else
02781 dbus_int32_t res;
02782
02783 pthread_mutex_lock (&atomic_mutex);
02784 res = atomic->value;
02785 atomic->value -= 1;
02786 pthread_mutex_unlock (&atomic_mutex);
02787
02788 return res;
02789 #endif
02790 }
02791
02799 dbus_int32_t
02800 _dbus_atomic_get (DBusAtomic *atomic)
02801 {
02802 #if DBUS_USE_SYNC
02803 __sync_synchronize ();
02804 return atomic->value;
02805 #else
02806 dbus_int32_t res;
02807
02808 pthread_mutex_lock (&atomic_mutex);
02809 res = atomic->value;
02810 pthread_mutex_unlock (&atomic_mutex);
02811
02812 return res;
02813 #endif
02814 }
02815
02824 int
02825 _dbus_poll (DBusPollFD *fds,
02826 int n_fds,
02827 int timeout_milliseconds)
02828 {
02829 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
02830
02831 if (timeout_milliseconds < -1)
02832 {
02833 timeout_milliseconds = -1;
02834 }
02835
02836 return poll (fds,
02837 n_fds,
02838 timeout_milliseconds);
02839 #else
02840
02841 fd_set read_set, write_set, err_set;
02842 int max_fd = 0;
02843 int i;
02844 struct timeval tv;
02845 int ready;
02846
02847 FD_ZERO (&read_set);
02848 FD_ZERO (&write_set);
02849 FD_ZERO (&err_set);
02850
02851 for (i = 0; i < n_fds; i++)
02852 {
02853 DBusPollFD *fdp = &fds[i];
02854
02855 if (fdp->events & _DBUS_POLLIN)
02856 FD_SET (fdp->fd, &read_set);
02857
02858 if (fdp->events & _DBUS_POLLOUT)
02859 FD_SET (fdp->fd, &write_set);
02860
02861 FD_SET (fdp->fd, &err_set);
02862
02863 max_fd = MAX (max_fd, fdp->fd);
02864 }
02865
02866 tv.tv_sec = timeout_milliseconds / 1000;
02867 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02868
02869 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02870 timeout_milliseconds < 0 ? NULL : &tv);
02871
02872 if (ready > 0)
02873 {
02874 for (i = 0; i < n_fds; i++)
02875 {
02876 DBusPollFD *fdp = &fds[i];
02877
02878 fdp->revents = 0;
02879
02880 if (FD_ISSET (fdp->fd, &read_set))
02881 fdp->revents |= _DBUS_POLLIN;
02882
02883 if (FD_ISSET (fdp->fd, &write_set))
02884 fdp->revents |= _DBUS_POLLOUT;
02885
02886 if (FD_ISSET (fdp->fd, &err_set))
02887 fdp->revents |= _DBUS_POLLERR;
02888 }
02889 }
02890
02891 return ready;
02892 #endif
02893 }
02894
02902 void
02903 _dbus_get_monotonic_time (long *tv_sec,
02904 long *tv_usec)
02905 {
02906 #ifdef HAVE_MONOTONIC_CLOCK
02907 struct timespec ts;
02908 clock_gettime (CLOCK_MONOTONIC, &ts);
02909
02910 if (tv_sec)
02911 *tv_sec = ts.tv_sec;
02912 if (tv_usec)
02913 *tv_usec = ts.tv_nsec / 1000;
02914 #else
02915 struct timeval t;
02916
02917 gettimeofday (&t, NULL);
02918
02919 if (tv_sec)
02920 *tv_sec = t.tv_sec;
02921 if (tv_usec)
02922 *tv_usec = t.tv_usec;
02923 #endif
02924 }
02925
02933 void
02934 _dbus_get_real_time (long *tv_sec,
02935 long *tv_usec)
02936 {
02937 struct timeval t;
02938
02939 gettimeofday (&t, NULL);
02940
02941 if (tv_sec)
02942 *tv_sec = t.tv_sec;
02943 if (tv_usec)
02944 *tv_usec = t.tv_usec;
02945 }
02946
02955 dbus_bool_t
02956 _dbus_create_directory (const DBusString *filename,
02957 DBusError *error)
02958 {
02959 const char *filename_c;
02960
02961 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02962
02963 filename_c = _dbus_string_get_const_data (filename);
02964
02965 if (mkdir (filename_c, 0700) < 0)
02966 {
02967 if (errno == EEXIST)
02968 return TRUE;
02969
02970 dbus_set_error (error, DBUS_ERROR_FAILED,
02971 "Failed to create directory %s: %s\n",
02972 filename_c, _dbus_strerror (errno));
02973 return FALSE;
02974 }
02975 else
02976 return TRUE;
02977 }
02978
02989 dbus_bool_t
02990 _dbus_concat_dir_and_file (DBusString *dir,
02991 const DBusString *next_component)
02992 {
02993 dbus_bool_t dir_ends_in_slash;
02994 dbus_bool_t file_starts_with_slash;
02995
02996 if (_dbus_string_get_length (dir) == 0 ||
02997 _dbus_string_get_length (next_component) == 0)
02998 return TRUE;
02999
03000 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
03001 _dbus_string_get_length (dir) - 1);
03002
03003 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
03004
03005 if (dir_ends_in_slash && file_starts_with_slash)
03006 {
03007 _dbus_string_shorten (dir, 1);
03008 }
03009 else if (!(dir_ends_in_slash || file_starts_with_slash))
03010 {
03011 if (!_dbus_string_append_byte (dir, '/'))
03012 return FALSE;
03013 }
03014
03015 return _dbus_string_copy (next_component, 0, dir,
03016 _dbus_string_get_length (dir));
03017 }
03018
03020 #define NANOSECONDS_PER_SECOND 1000000000
03021
03022 #define MICROSECONDS_PER_SECOND 1000000
03023
03024 #define MILLISECONDS_PER_SECOND 1000
03025
03026 #define NANOSECONDS_PER_MILLISECOND 1000000
03027
03028 #define MICROSECONDS_PER_MILLISECOND 1000
03029
03034 void
03035 _dbus_sleep_milliseconds (int milliseconds)
03036 {
03037 #ifdef HAVE_NANOSLEEP
03038 struct timespec req;
03039 struct timespec rem;
03040
03041 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
03042 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
03043 rem.tv_sec = 0;
03044 rem.tv_nsec = 0;
03045
03046 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
03047 req = rem;
03048 #elif defined (HAVE_USLEEP)
03049 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
03050 #else
03051 sleep (MAX (milliseconds / 1000, 1));
03052 #endif
03053 }
03054
03064 dbus_bool_t
03065 _dbus_generate_random_bytes (DBusString *str,
03066 int n_bytes,
03067 DBusError *error)
03068 {
03069 int old_len;
03070 int fd;
03071 int result;
03072
03073 old_len = _dbus_string_get_length (str);
03074 fd = -1;
03075
03076
03077 fd = open ("/dev/urandom", O_RDONLY);
03078
03079 if (fd < 0)
03080 {
03081 dbus_set_error (error, _dbus_error_from_errno (errno),
03082 "Could not open /dev/urandom: %s",
03083 _dbus_strerror (errno));
03084 return FALSE;
03085 }
03086
03087 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
03088
03089 result = _dbus_read (fd, str, n_bytes);
03090
03091 if (result != n_bytes)
03092 {
03093 if (result < 0)
03094 dbus_set_error (error, _dbus_error_from_errno (errno),
03095 "Could not read /dev/urandom: %s",
03096 _dbus_strerror (errno));
03097 else
03098 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
03099 "Short read from /dev/urandom");
03100
03101 _dbus_close (fd, NULL);
03102 _dbus_string_set_length (str, old_len);
03103 return FALSE;
03104 }
03105
03106 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
03107 n_bytes);
03108
03109 _dbus_close (fd, NULL);
03110
03111 return TRUE;
03112 }
03113
03119 void
03120 _dbus_exit (int code)
03121 {
03122 _exit (code);
03123 }
03124
03133 const char*
03134 _dbus_strerror (int error_number)
03135 {
03136 const char *msg;
03137
03138 msg = strerror (error_number);
03139 if (msg == NULL)
03140 msg = "unknown";
03141
03142 return msg;
03143 }
03144
03148 void
03149 _dbus_disable_sigpipe (void)
03150 {
03151 signal (SIGPIPE, SIG_IGN);
03152 }
03153
03161 void
03162 _dbus_fd_set_close_on_exec (int fd)
03163 {
03164 int val;
03165
03166 val = fcntl (fd, F_GETFD, 0);
03167
03168 if (val < 0)
03169 return;
03170
03171 val |= FD_CLOEXEC;
03172
03173 fcntl (fd, F_SETFD, val);
03174 }
03175
03183 dbus_bool_t
03184 _dbus_close (int fd,
03185 DBusError *error)
03186 {
03187 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03188
03189 again:
03190 if (close (fd) < 0)
03191 {
03192 if (errno == EINTR)
03193 goto again;
03194
03195 dbus_set_error (error, _dbus_error_from_errno (errno),
03196 "Could not close fd %d", fd);
03197 return FALSE;
03198 }
03199
03200 return TRUE;
03201 }
03202
03211 int
03212 _dbus_dup(int fd,
03213 DBusError *error)
03214 {
03215 int new_fd;
03216
03217 #ifdef F_DUPFD_CLOEXEC
03218 dbus_bool_t cloexec_done;
03219
03220 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
03221 cloexec_done = new_fd >= 0;
03222
03223 if (new_fd < 0 && errno == EINVAL)
03224 #endif
03225 {
03226 new_fd = fcntl(fd, F_DUPFD, 3);
03227 }
03228
03229 if (new_fd < 0) {
03230
03231 dbus_set_error (error, _dbus_error_from_errno (errno),
03232 "Could not duplicate fd %d", fd);
03233 return -1;
03234 }
03235
03236 #ifdef F_DUPFD_CLOEXEC
03237 if (!cloexec_done)
03238 #endif
03239 {
03240 _dbus_fd_set_close_on_exec(new_fd);
03241 }
03242
03243 return new_fd;
03244 }
03245
03253 dbus_bool_t
03254 _dbus_set_socket_nonblocking (DBusSocket fd,
03255 DBusError *error)
03256 {
03257 return _dbus_set_fd_nonblocking (fd.fd, error);
03258 }
03259
03260 static dbus_bool_t
03261 _dbus_set_fd_nonblocking (int fd,
03262 DBusError *error)
03263 {
03264 int val;
03265
03266 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03267
03268 val = fcntl (fd, F_GETFL, 0);
03269 if (val < 0)
03270 {
03271 dbus_set_error (error, _dbus_error_from_errno (errno),
03272 "Failed to get flags from file descriptor %d: %s",
03273 fd, _dbus_strerror (errno));
03274 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
03275 _dbus_strerror (errno));
03276 return FALSE;
03277 }
03278
03279 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
03280 {
03281 dbus_set_error (error, _dbus_error_from_errno (errno),
03282 "Failed to set nonblocking flag of file descriptor %d: %s",
03283 fd, _dbus_strerror (errno));
03284 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
03285 fd, _dbus_strerror (errno));
03286
03287 return FALSE;
03288 }
03289
03290 return TRUE;
03291 }
03292
03298 void
03299 _dbus_print_backtrace (void)
03300 {
03301 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
03302 void *bt[500];
03303 int bt_size;
03304 int i;
03305 char **syms;
03306
03307 bt_size = backtrace (bt, 500);
03308
03309 syms = backtrace_symbols (bt, bt_size);
03310
03311 i = 0;
03312 while (i < bt_size)
03313 {
03314
03315 fprintf (stderr, " %s\n", syms[i]);
03316 ++i;
03317 }
03318 fflush (stderr);
03319
03320 free (syms);
03321 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
03322 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
03323 #else
03324 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
03325 #endif
03326 }
03327
03340 dbus_bool_t
03341 _dbus_socketpair (DBusSocket *fd1,
03342 DBusSocket *fd2,
03343 dbus_bool_t blocking,
03344 DBusError *error)
03345 {
03346 #ifdef HAVE_SOCKETPAIR
03347 int fds[2];
03348 int retval;
03349
03350 #ifdef SOCK_CLOEXEC
03351 dbus_bool_t cloexec_done;
03352
03353 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
03354 cloexec_done = retval >= 0;
03355
03356 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
03357 #endif
03358 {
03359 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
03360 }
03361
03362 if (retval < 0)
03363 {
03364 dbus_set_error (error, _dbus_error_from_errno (errno),
03365 "Could not create full-duplex pipe");
03366 return FALSE;
03367 }
03368
03369 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03370
03371 #ifdef SOCK_CLOEXEC
03372 if (!cloexec_done)
03373 #endif
03374 {
03375 _dbus_fd_set_close_on_exec (fds[0]);
03376 _dbus_fd_set_close_on_exec (fds[1]);
03377 }
03378
03379 if (!blocking &&
03380 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
03381 !_dbus_set_fd_nonblocking (fds[1], NULL)))
03382 {
03383 dbus_set_error (error, _dbus_error_from_errno (errno),
03384 "Could not set full-duplex pipe nonblocking");
03385
03386 _dbus_close (fds[0], NULL);
03387 _dbus_close (fds[1], NULL);
03388
03389 return FALSE;
03390 }
03391
03392 fd1->fd = fds[0];
03393 fd2->fd = fds[1];
03394
03395 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
03396 fd1->fd, fd2->fd);
03397
03398 return TRUE;
03399 #else
03400 _dbus_warn ("_dbus_socketpair() not implemented on this OS\n");
03401 dbus_set_error (error, DBUS_ERROR_FAILED,
03402 "_dbus_socketpair() not implemented on this OS");
03403 return FALSE;
03404 #endif
03405 }
03406
03415 int
03416 _dbus_printf_string_upper_bound (const char *format,
03417 va_list args)
03418 {
03419 char static_buf[1024];
03420 int bufsize = sizeof (static_buf);
03421 int len;
03422 va_list args_copy;
03423
03424 DBUS_VA_COPY (args_copy, args);
03425 len = vsnprintf (static_buf, bufsize, format, args_copy);
03426 va_end (args_copy);
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436 if (len == bufsize)
03437 {
03438
03439
03440
03441
03442 DBUS_VA_COPY (args_copy, args);
03443
03444 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
03445 len = -1;
03446
03447 va_end (args_copy);
03448 }
03449
03450
03451
03452 while (len < 0)
03453 {
03454 char *buf;
03455
03456 bufsize *= 2;
03457
03458 buf = dbus_malloc (bufsize);
03459
03460 if (buf == NULL)
03461 return -1;
03462
03463 DBUS_VA_COPY (args_copy, args);
03464 len = vsnprintf (buf, bufsize, format, args_copy);
03465 va_end (args_copy);
03466
03467 dbus_free (buf);
03468
03469
03470
03471
03472 if (len == bufsize)
03473 len = -1;
03474 }
03475
03476 return len;
03477 }
03478
03485 const char*
03486 _dbus_get_tmpdir(void)
03487 {
03488
03489 static const char* tmpdir = NULL;
03490
03491 if (!_DBUS_LOCK (sysdeps))
03492 return NULL;
03493
03494 if (tmpdir == NULL)
03495 {
03496
03497
03498
03499
03500 if (tmpdir == NULL)
03501 tmpdir = getenv("TMPDIR");
03502
03503
03504
03505
03506 if (tmpdir == NULL)
03507 tmpdir = getenv("TMP");
03508 if (tmpdir == NULL)
03509 tmpdir = getenv("TEMP");
03510
03511
03512 if (tmpdir == NULL)
03513 tmpdir = "/tmp";
03514 }
03515
03516 _DBUS_UNLOCK (sysdeps);
03517
03518 _dbus_assert(tmpdir != NULL);
03519
03520 return tmpdir;
03521 }
03522
03523 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
03524
03543 static dbus_bool_t
03544 _read_subprocess_line_argv (const char *progpath,
03545 dbus_bool_t path_fallback,
03546 char * const *argv,
03547 DBusString *result,
03548 DBusError *error)
03549 {
03550 int result_pipe[2] = { -1, -1 };
03551 int errors_pipe[2] = { -1, -1 };
03552 pid_t pid;
03553 int ret;
03554 int status;
03555 int orig_len;
03556
03557 dbus_bool_t retval;
03558 sigset_t new_set, old_set;
03559
03560 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03561 retval = FALSE;
03562
03563
03564
03565
03566
03567 sigemptyset (&new_set);
03568 sigaddset (&new_set, SIGCHLD);
03569 sigprocmask (SIG_BLOCK, &new_set, &old_set);
03570
03571 orig_len = _dbus_string_get_length (result);
03572
03573 #define READ_END 0
03574 #define WRITE_END 1
03575 if (pipe (result_pipe) < 0)
03576 {
03577 dbus_set_error (error, _dbus_error_from_errno (errno),
03578 "Failed to create a pipe to call %s: %s",
03579 progpath, _dbus_strerror (errno));
03580 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03581 progpath, _dbus_strerror (errno));
03582 goto out;
03583 }
03584 if (pipe (errors_pipe) < 0)
03585 {
03586 dbus_set_error (error, _dbus_error_from_errno (errno),
03587 "Failed to create a pipe to call %s: %s",
03588 progpath, _dbus_strerror (errno));
03589 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
03590 progpath, _dbus_strerror (errno));
03591 goto out;
03592 }
03593
03594 pid = fork ();
03595 if (pid < 0)
03596 {
03597 dbus_set_error (error, _dbus_error_from_errno (errno),
03598 "Failed to fork() to call %s: %s",
03599 progpath, _dbus_strerror (errno));
03600 _dbus_verbose ("Failed to fork() to call %s: %s\n",
03601 progpath, _dbus_strerror (errno));
03602 goto out;
03603 }
03604
03605 if (pid == 0)
03606 {
03607
03608 int fd;
03609
03610 fd = open ("/dev/null", O_RDWR);
03611 if (fd == -1)
03612
03613 _exit (1);
03614
03615 _dbus_verbose ("/dev/null fd %d opened\n", fd);
03616
03617
03618 close (result_pipe[READ_END]);
03619 close (errors_pipe[READ_END]);
03620
03621 if (dup2 (fd, 0) == -1)
03622 _exit (1);
03623 if (dup2 (result_pipe[WRITE_END], 1) == -1)
03624 _exit (1);
03625 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03626 _exit (1);
03627
03628 _dbus_close_all ();
03629
03630 sigprocmask (SIG_SETMASK, &old_set, NULL);
03631
03632
03633 if (progpath[0] == '/')
03634 {
03635 execv (progpath, argv);
03636
03637
03638
03639
03640
03641
03642 if (path_fallback)
03643
03644 execvp (strrchr (progpath, '/')+1, argv);
03645 }
03646 else
03647 execvp (progpath, argv);
03648
03649
03650 _exit (1);
03651 }
03652
03653
03654 close (result_pipe[WRITE_END]);
03655 close (errors_pipe[WRITE_END]);
03656 result_pipe[WRITE_END] = -1;
03657 errors_pipe[WRITE_END] = -1;
03658
03659 ret = 0;
03660 do
03661 {
03662 ret = _dbus_read (result_pipe[READ_END], result, 1024);
03663 }
03664 while (ret > 0);
03665
03666
03667 do
03668 {
03669 ret = waitpid (pid, &status, 0);
03670 }
03671 while (ret == -1 && errno == EINTR);
03672
03673
03674
03675 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03676 {
03677
03678 DBusString error_message;
03679 if (!_dbus_string_init (&error_message))
03680 {
03681 _DBUS_SET_OOM (error);
03682 goto out;
03683 }
03684
03685 ret = 0;
03686 do
03687 {
03688 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03689 }
03690 while (ret > 0);
03691
03692 _dbus_string_set_length (result, orig_len);
03693 if (_dbus_string_get_length (&error_message) > 0)
03694 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03695 "%s terminated abnormally with the following error: %s",
03696 progpath, _dbus_string_get_data (&error_message));
03697 else
03698 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03699 "%s terminated abnormally without any error message",
03700 progpath);
03701 goto out;
03702 }
03703
03704 retval = TRUE;
03705
03706 out:
03707 sigprocmask (SIG_SETMASK, &old_set, NULL);
03708
03709 if (retval)
03710 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03711 else
03712 _DBUS_ASSERT_ERROR_IS_SET (error);
03713
03714 if (result_pipe[0] != -1)
03715 close (result_pipe[0]);
03716 if (result_pipe[1] != -1)
03717 close (result_pipe[1]);
03718 if (errors_pipe[0] != -1)
03719 close (errors_pipe[0]);
03720 if (errors_pipe[1] != -1)
03721 close (errors_pipe[1]);
03722
03723 return retval;
03724 }
03725 #endif
03726
03739 dbus_bool_t
03740 _dbus_get_autolaunch_address (const char *scope,
03741 DBusString *address,
03742 DBusError *error)
03743 {
03744 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
03745
03746
03747
03748 const char *display;
03749 char *progpath;
03750 char *argv[6];
03751 int i;
03752 DBusString uuid;
03753 dbus_bool_t retval;
03754
03755 if (_dbus_check_setuid ())
03756 {
03757 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03758 "Unable to autolaunch when setuid");
03759 return FALSE;
03760 }
03761
03762 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03763 retval = FALSE;
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773 display = _dbus_getenv ("DISPLAY");
03774
03775 if (display == NULL || display[0] == '\0')
03776 {
03777 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03778 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
03779 return FALSE;
03780 }
03781
03782 if (!_dbus_string_init (&uuid))
03783 {
03784 _DBUS_SET_OOM (error);
03785 return FALSE;
03786 }
03787
03788 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
03789 {
03790 goto out;
03791 }
03792
03793 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
03794 if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL)
03795 progpath = TEST_BUS_LAUNCH_BINARY;
03796 else
03797 #endif
03798 progpath = DBUS_BINDIR "/dbus-launch";
03799
03800
03801
03802
03803
03804 i = 0;
03805 argv[i] = "dbus-launch";
03806 ++i;
03807 argv[i] = "--autolaunch";
03808 ++i;
03809 argv[i] = _dbus_string_get_data (&uuid);
03810 ++i;
03811 argv[i] = "--binary-syntax";
03812 ++i;
03813 argv[i] = "--close-stderr";
03814 ++i;
03815 argv[i] = NULL;
03816 ++i;
03817
03818 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03819
03820 retval = _read_subprocess_line_argv (progpath,
03821 TRUE,
03822 argv, address, error);
03823
03824 out:
03825 _dbus_string_free (&uuid);
03826 return retval;
03827 #else
03828 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03829 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
03830 "set your DBUS_SESSION_BUS_ADDRESS instead");
03831 return FALSE;
03832 #endif
03833 }
03834
03853 dbus_bool_t
03854 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
03855 dbus_bool_t create_if_not_found,
03856 DBusError *error)
03857 {
03858 DBusString filename;
03859 dbus_bool_t b;
03860
03861 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03862
03863 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
03864 if (b)
03865 return TRUE;
03866
03867 dbus_error_free (error);
03868
03869
03870 _dbus_string_init_const (&filename, "/etc/machine-id");
03871 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
03872
03873 if (b)
03874 {
03875
03876
03877 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03878 _dbus_write_uuid_file (&filename, machine_id, NULL);
03879
03880 return TRUE;
03881 }
03882
03883 if (!create_if_not_found)
03884 return FALSE;
03885
03886
03887 dbus_error_free (error);
03888 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03889
03890 if (!_dbus_generate_uuid (machine_id, error))
03891 return FALSE;
03892
03893 return _dbus_write_uuid_file (&filename, machine_id, error);
03894 }
03895
03903 dbus_bool_t
03904 _dbus_lookup_launchd_socket (DBusString *socket_path,
03905 const char *launchd_env_var,
03906 DBusError *error)
03907 {
03908 #ifdef DBUS_ENABLE_LAUNCHD
03909 char *argv[4];
03910 int i;
03911
03912 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03913
03914 if (_dbus_check_setuid ())
03915 {
03916 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03917 "Unable to find launchd socket when setuid");
03918 return FALSE;
03919 }
03920
03921 i = 0;
03922 argv[i] = "launchctl";
03923 ++i;
03924 argv[i] = "getenv";
03925 ++i;
03926 argv[i] = (char*)launchd_env_var;
03927 ++i;
03928 argv[i] = NULL;
03929 ++i;
03930
03931 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03932
03933 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
03934 {
03935 return FALSE;
03936 }
03937
03938
03939 if (_dbus_string_get_length(socket_path) == 0)
03940 {
03941 return FALSE;
03942 }
03943
03944
03945 _dbus_string_shorten(socket_path, 1);
03946 return TRUE;
03947 #else
03948 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
03949 "can't lookup socket from launchd; launchd support not compiled in");
03950 return FALSE;
03951 #endif
03952 }
03953
03954 #ifdef DBUS_ENABLE_LAUNCHD
03955 static dbus_bool_t
03956 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
03957 {
03958 dbus_bool_t valid_socket;
03959 DBusString socket_path;
03960
03961 if (_dbus_check_setuid ())
03962 {
03963 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
03964 "Unable to find launchd socket when setuid");
03965 return FALSE;
03966 }
03967
03968 if (!_dbus_string_init (&socket_path))
03969 {
03970 _DBUS_SET_OOM (error);
03971 return FALSE;
03972 }
03973
03974 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
03975
03976 if (dbus_error_is_set(error))
03977 {
03978 _dbus_string_free(&socket_path);
03979 return FALSE;
03980 }
03981
03982 if (!valid_socket)
03983 {
03984 dbus_set_error(error, "no socket path",
03985 "launchd did not provide a socket path, "
03986 "verify that org.freedesktop.dbus-session.plist is loaded!");
03987 _dbus_string_free(&socket_path);
03988 return FALSE;
03989 }
03990 if (!_dbus_string_append (address, "unix:path="))
03991 {
03992 _DBUS_SET_OOM (error);
03993 _dbus_string_free(&socket_path);
03994 return FALSE;
03995 }
03996 if (!_dbus_string_copy (&socket_path, 0, address,
03997 _dbus_string_get_length (address)))
03998 {
03999 _DBUS_SET_OOM (error);
04000 _dbus_string_free(&socket_path);
04001 return FALSE;
04002 }
04003
04004 _dbus_string_free(&socket_path);
04005 return TRUE;
04006 }
04007 #endif
04008
04009 dbus_bool_t
04010 _dbus_lookup_user_bus (dbus_bool_t *supported,
04011 DBusString *address,
04012 DBusError *error)
04013 {
04014 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
04015 dbus_bool_t ret = FALSE;
04016 struct stat stbuf;
04017 DBusString user_bus_path;
04018
04019 if (runtime_dir == NULL)
04020 {
04021 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
04022 *supported = FALSE;
04023 return TRUE;
04024 }
04025
04026 if (!_dbus_string_init (&user_bus_path))
04027 {
04028 _DBUS_SET_OOM (error);
04029 return FALSE;
04030 }
04031
04032 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
04033 {
04034 _DBUS_SET_OOM (error);
04035 goto out;
04036 }
04037
04038 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
04039 {
04040 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
04041 _dbus_strerror (errno));
04042 *supported = FALSE;
04043 ret = TRUE;
04044 goto out;
04045 }
04046
04047 if (stbuf.st_uid != getuid ())
04048 {
04049 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
04050 (long) stbuf.st_uid, (long) getuid ());
04051 *supported = FALSE;
04052 ret = TRUE;
04053 goto out;
04054 }
04055
04056 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
04057 {
04058 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
04059 (long) stbuf.st_mode);
04060 *supported = FALSE;
04061 ret = TRUE;
04062 goto out;
04063 }
04064
04065 if (!_dbus_string_append (address, "unix:path=") ||
04066 !_dbus_address_append_escaped (address, &user_bus_path))
04067 {
04068 _DBUS_SET_OOM (error);
04069 goto out;
04070 }
04071
04072 *supported = TRUE;
04073 ret = TRUE;
04074
04075 out:
04076 _dbus_string_free (&user_bus_path);
04077 return ret;
04078 }
04079
04099 dbus_bool_t
04100 _dbus_lookup_session_address (dbus_bool_t *supported,
04101 DBusString *address,
04102 DBusError *error)
04103 {
04104 #ifdef DBUS_ENABLE_LAUNCHD
04105 *supported = TRUE;
04106 return _dbus_lookup_session_address_launchd (address, error);
04107 #else
04108 *supported = FALSE;
04109
04110 if (!_dbus_lookup_user_bus (supported, address, error))
04111 return FALSE;
04112 else if (*supported)
04113 return TRUE;
04114
04115
04116
04117
04118
04119
04120 return TRUE;
04121 #endif
04122 }
04123
04131 void
04132 _dbus_flush_caches (void)
04133 {
04134 _dbus_user_database_flush_system ();
04135 }
04136
04150 dbus_bool_t
04151 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
04152 DBusCredentials *credentials)
04153 {
04154 DBusString homedir;
04155 DBusString dotdir;
04156 dbus_uid_t uid;
04157
04158 _dbus_assert (credentials != NULL);
04159 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
04160
04161 if (!_dbus_string_init (&homedir))
04162 return FALSE;
04163
04164 uid = _dbus_credentials_get_unix_uid (credentials);
04165 _dbus_assert (uid != DBUS_UID_UNSET);
04166
04167 if (!_dbus_homedir_from_uid (uid, &homedir))
04168 goto failed;
04169
04170 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
04171 {
04172 const char *override;
04173
04174 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
04175 if (override != NULL && *override != '\0')
04176 {
04177 _dbus_string_set_length (&homedir, 0);
04178 if (!_dbus_string_append (&homedir, override))
04179 goto failed;
04180
04181 _dbus_verbose ("Using fake homedir for testing: %s\n",
04182 _dbus_string_get_const_data (&homedir));
04183 }
04184 else
04185 {
04186
04187
04188 static dbus_bool_t already_warned = FALSE;
04189 if (!already_warned)
04190 {
04191 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
04192 already_warned = TRUE;
04193 }
04194 }
04195 }
04196 #endif
04197
04198 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
04199 if (!_dbus_concat_dir_and_file (&homedir,
04200 &dotdir))
04201 goto failed;
04202
04203 if (!_dbus_string_copy (&homedir, 0,
04204 directory, _dbus_string_get_length (directory))) {
04205 goto failed;
04206 }
04207
04208 _dbus_string_free (&homedir);
04209 return TRUE;
04210
04211 failed:
04212 _dbus_string_free (&homedir);
04213 return FALSE;
04214 }
04215
04216
04217 dbus_bool_t
04218 _dbus_daemon_publish_session_bus_address (const char* addr,
04219 const char *scope)
04220 {
04221 return TRUE;
04222 }
04223
04224
04225 void
04226 _dbus_daemon_unpublish_session_bus_address (void)
04227 {
04228
04229 }
04230
04237 dbus_bool_t
04238 _dbus_get_is_errno_eagain_or_ewouldblock (int e)
04239 {
04240 return e == EAGAIN || e == EWOULDBLOCK;
04241 }
04242
04250 dbus_bool_t
04251 _dbus_delete_directory (const DBusString *filename,
04252 DBusError *error)
04253 {
04254 const char *filename_c;
04255
04256 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
04257
04258 filename_c = _dbus_string_get_const_data (filename);
04259
04260 if (rmdir (filename_c) != 0)
04261 {
04262 dbus_set_error (error, DBUS_ERROR_FAILED,
04263 "Failed to remove directory %s: %s\n",
04264 filename_c, _dbus_strerror (errno));
04265 return FALSE;
04266 }
04267
04268 return TRUE;
04269 }
04270
04278 dbus_bool_t
04279 _dbus_socket_can_pass_unix_fd (DBusSocket fd)
04280 {
04281 #ifdef SCM_RIGHTS
04282 union {
04283 struct sockaddr sa;
04284 struct sockaddr_storage storage;
04285 struct sockaddr_un un;
04286 } sa_buf;
04287
04288 socklen_t sa_len = sizeof(sa_buf);
04289
04290 _DBUS_ZERO(sa_buf);
04291
04292 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
04293 return FALSE;
04294
04295 return sa_buf.sa.sa_family == AF_UNIX;
04296
04297 #else
04298 return FALSE;
04299
04300 #endif
04301 }
04302
04307 void
04308 _dbus_close_all (void)
04309 {
04310 int maxfds, i;
04311
04312 #ifdef __linux__
04313 DIR *d;
04314
04315
04316
04317
04318 d = opendir ("/proc/self/fd");
04319 if (d)
04320 {
04321 for (;;)
04322 {
04323 struct dirent buf, *de;
04324 int k, fd;
04325 long l;
04326 char *e = NULL;
04327
04328 k = readdir_r (d, &buf, &de);
04329 if (k != 0 || !de)
04330 break;
04331
04332 if (de->d_name[0] == '.')
04333 continue;
04334
04335 errno = 0;
04336 l = strtol (de->d_name, &e, 10);
04337 if (errno != 0 || e == NULL || *e != '\0')
04338 continue;
04339
04340 fd = (int) l;
04341 if (fd < 3)
04342 continue;
04343
04344 if (fd == dirfd (d))
04345 continue;
04346
04347 close (fd);
04348 }
04349
04350 closedir (d);
04351 return;
04352 }
04353 #endif
04354
04355 maxfds = sysconf (_SC_OPEN_MAX);
04356
04357
04358
04359
04360 if (maxfds < 0)
04361 maxfds = 1024;
04362
04363
04364 for (i = 3; i < maxfds; i++)
04365 close (i);
04366 }
04367
04377 dbus_bool_t
04378 _dbus_check_setuid (void)
04379 {
04380
04381
04382
04383 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
04384 {
04385
04386 extern int __libc_enable_secure;
04387 return __libc_enable_secure;
04388 }
04389 #elif defined(HAVE_ISSETUGID)
04390
04391 return issetugid ();
04392 #else
04393 uid_t ruid, euid, suid;
04394 gid_t rgid, egid, sgid;
04395
04396
04397
04398 static dbus_bool_t check_setuid_initialised;
04399 static dbus_bool_t is_setuid;
04400
04401 if (_DBUS_UNLIKELY (!check_setuid_initialised))
04402 {
04403 #ifdef HAVE_GETRESUID
04404 if (getresuid (&ruid, &euid, &suid) != 0 ||
04405 getresgid (&rgid, &egid, &sgid) != 0)
04406 #endif
04407 {
04408 suid = ruid = getuid ();
04409 sgid = rgid = getgid ();
04410 euid = geteuid ();
04411 egid = getegid ();
04412 }
04413
04414 check_setuid_initialised = TRUE;
04415 is_setuid = (ruid != euid || ruid != suid ||
04416 rgid != egid || rgid != sgid);
04417
04418 }
04419 return is_setuid;
04420 #endif
04421 }
04422
04430 dbus_bool_t
04431 _dbus_append_address_from_socket (DBusSocket fd,
04432 DBusString *address,
04433 DBusError *error)
04434 {
04435 union {
04436 struct sockaddr sa;
04437 struct sockaddr_storage storage;
04438 struct sockaddr_un un;
04439 struct sockaddr_in ipv4;
04440 struct sockaddr_in6 ipv6;
04441 } socket;
04442 char hostip[INET6_ADDRSTRLEN];
04443 int size = sizeof (socket);
04444 DBusString path_str;
04445
04446 if (getsockname (fd.fd, &socket.sa, &size))
04447 goto err;
04448
04449 switch (socket.sa.sa_family)
04450 {
04451 case AF_UNIX:
04452 if (socket.un.sun_path[0]=='\0')
04453 {
04454 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
04455 if (_dbus_string_append (address, "unix:abstract=") &&
04456 _dbus_address_append_escaped (address, &path_str))
04457 return TRUE;
04458 }
04459 else
04460 {
04461 _dbus_string_init_const (&path_str, socket.un.sun_path);
04462 if (_dbus_string_append (address, "unix:path=") &&
04463 _dbus_address_append_escaped (address, &path_str))
04464 return TRUE;
04465 }
04466 break;
04467 case AF_INET:
04468 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
04469 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
04470 hostip, ntohs (socket.ipv4.sin_port)))
04471 return TRUE;
04472 break;
04473 #ifdef AF_INET6
04474 case AF_INET6:
04475 _dbus_string_init_const (&path_str, hostip);
04476 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
04477 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
04478 ntohs (socket.ipv6.sin6_port)) &&
04479 _dbus_address_append_escaped (address, &path_str))
04480 return TRUE;
04481 break;
04482 #endif
04483 default:
04484 dbus_set_error (error,
04485 _dbus_error_from_errno (EINVAL),
04486 "Failed to read address from socket: Unknown socket type.");
04487 return FALSE;
04488 }
04489 err:
04490 dbus_set_error (error,
04491 _dbus_error_from_errno (errno),
04492 "Failed to open socket: %s",
04493 _dbus_strerror (errno));
04494 return FALSE;
04495 }
04496
04497 int
04498 _dbus_save_socket_errno (void)
04499 {
04500 return errno;
04501 }
04502
04503 void
04504 _dbus_restore_socket_errno (int saved_errno)
04505 {
04506 errno = saved_errno;
04507 }
04508
04509