D-Bus 1.4.14
|
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 static dbus_bool_t 00094 _dbus_open_socket (int *fd_p, 00095 int domain, 00096 int type, 00097 int protocol, 00098 DBusError *error) 00099 { 00100 #ifdef SOCK_CLOEXEC 00101 dbus_bool_t cloexec_done; 00102 00103 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol); 00104 cloexec_done = *fd_p >= 0; 00105 00106 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */ 00107 if (*fd_p < 0 && errno == EINVAL) 00108 #endif 00109 { 00110 *fd_p = socket (domain, type, protocol); 00111 } 00112 00113 if (*fd_p >= 0) 00114 { 00115 #ifdef SOCK_CLOEXEC 00116 if (!cloexec_done) 00117 #endif 00118 { 00119 _dbus_fd_set_close_on_exec(*fd_p); 00120 } 00121 00122 _dbus_verbose ("socket fd %d opened\n", *fd_p); 00123 return TRUE; 00124 } 00125 else 00126 { 00127 dbus_set_error(error, 00128 _dbus_error_from_errno (errno), 00129 "Failed to open socket: %s", 00130 _dbus_strerror (errno)); 00131 return FALSE; 00132 } 00133 } 00134 00135 dbus_bool_t 00136 _dbus_open_tcp_socket (int *fd, 00137 DBusError *error) 00138 { 00139 return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error); 00140 } 00141 00152 dbus_bool_t 00153 _dbus_open_unix_socket (int *fd, 00154 DBusError *error) 00155 { 00156 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error); 00157 } 00158 00167 dbus_bool_t 00168 _dbus_close_socket (int fd, 00169 DBusError *error) 00170 { 00171 return _dbus_close (fd, error); 00172 } 00173 00183 int 00184 _dbus_read_socket (int fd, 00185 DBusString *buffer, 00186 int count) 00187 { 00188 return _dbus_read (fd, buffer, count); 00189 } 00190 00201 int 00202 _dbus_write_socket (int fd, 00203 const DBusString *buffer, 00204 int start, 00205 int len) 00206 { 00207 #if HAVE_DECL_MSG_NOSIGNAL 00208 const char *data; 00209 int bytes_written; 00210 00211 data = _dbus_string_get_const_data_len (buffer, start, len); 00212 00213 again: 00214 00215 bytes_written = send (fd, data, len, MSG_NOSIGNAL); 00216 00217 if (bytes_written < 0 && errno == EINTR) 00218 goto again; 00219 00220 return bytes_written; 00221 00222 #else 00223 return _dbus_write (fd, buffer, start, len); 00224 #endif 00225 } 00226 00239 int 00240 _dbus_read_socket_with_unix_fds (int fd, 00241 DBusString *buffer, 00242 int count, 00243 int *fds, 00244 int *n_fds) { 00245 #ifndef HAVE_UNIX_FD_PASSING 00246 int r; 00247 00248 if ((r = _dbus_read_socket(fd, buffer, count)) < 0) 00249 return r; 00250 00251 *n_fds = 0; 00252 return r; 00253 00254 #else 00255 int bytes_read; 00256 int start; 00257 struct msghdr m; 00258 struct iovec iov; 00259 00260 _dbus_assert (count >= 0); 00261 _dbus_assert (*n_fds >= 0); 00262 00263 start = _dbus_string_get_length (buffer); 00264 00265 if (!_dbus_string_lengthen (buffer, count)) 00266 { 00267 errno = ENOMEM; 00268 return -1; 00269 } 00270 00271 _DBUS_ZERO(iov); 00272 iov.iov_base = _dbus_string_get_data_len (buffer, start, count); 00273 iov.iov_len = count; 00274 00275 _DBUS_ZERO(m); 00276 m.msg_iov = &iov; 00277 m.msg_iovlen = 1; 00278 00279 /* Hmm, we have no clue how long the control data will actually be 00280 that is queued for us. The least we can do is assume that the 00281 caller knows. Hence let's make space for the number of fds that 00282 we shall read at max plus the cmsg header. */ 00283 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int)); 00284 00285 /* It's probably safe to assume that systems with SCM_RIGHTS also 00286 know alloca() */ 00287 m.msg_control = alloca(m.msg_controllen); 00288 memset(m.msg_control, 0, m.msg_controllen); 00289 00290 again: 00291 00292 bytes_read = recvmsg(fd, &m, 0 00293 #ifdef MSG_CMSG_CLOEXEC 00294 |MSG_CMSG_CLOEXEC 00295 #endif 00296 ); 00297 00298 if (bytes_read < 0) 00299 { 00300 if (errno == EINTR) 00301 goto again; 00302 else 00303 { 00304 /* put length back (note that this doesn't actually realloc anything) */ 00305 _dbus_string_set_length (buffer, start); 00306 return -1; 00307 } 00308 } 00309 else 00310 { 00311 struct cmsghdr *cm; 00312 dbus_bool_t found = FALSE; 00313 00314 if (m.msg_flags & MSG_CTRUNC) 00315 { 00316 /* Hmm, apparently the control data was truncated. The bad 00317 thing is that we might have completely lost a couple of fds 00318 without chance to recover them. Hence let's treat this as a 00319 serious error. */ 00320 00321 errno = ENOSPC; 00322 _dbus_string_set_length (buffer, start); 00323 return -1; 00324 } 00325 00326 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) 00327 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) 00328 { 00329 unsigned i; 00330 00331 _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int))); 00332 *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int); 00333 00334 memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int)); 00335 found = TRUE; 00336 00337 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually 00338 worked, hence we need to go through this list and set 00339 CLOEXEC everywhere in any case */ 00340 for (i = 0; i < *n_fds; i++) 00341 _dbus_fd_set_close_on_exec(fds[i]); 00342 00343 break; 00344 } 00345 00346 if (!found) 00347 *n_fds = 0; 00348 00349 /* put length back (doesn't actually realloc) */ 00350 _dbus_string_set_length (buffer, start + bytes_read); 00351 00352 #if 0 00353 if (bytes_read > 0) 00354 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00355 #endif 00356 00357 return bytes_read; 00358 } 00359 #endif 00360 } 00361 00362 int 00363 _dbus_write_socket_with_unix_fds(int fd, 00364 const DBusString *buffer, 00365 int start, 00366 int len, 00367 const int *fds, 00368 int n_fds) { 00369 00370 #ifndef HAVE_UNIX_FD_PASSING 00371 00372 if (n_fds > 0) { 00373 errno = ENOTSUP; 00374 return -1; 00375 } 00376 00377 return _dbus_write_socket(fd, buffer, start, len); 00378 #else 00379 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds); 00380 #endif 00381 } 00382 00383 int 00384 _dbus_write_socket_with_unix_fds_two(int fd, 00385 const DBusString *buffer1, 00386 int start1, 00387 int len1, 00388 const DBusString *buffer2, 00389 int start2, 00390 int len2, 00391 const int *fds, 00392 int n_fds) { 00393 00394 #ifndef HAVE_UNIX_FD_PASSING 00395 00396 if (n_fds > 0) { 00397 errno = ENOTSUP; 00398 return -1; 00399 } 00400 00401 return _dbus_write_socket_two(fd, 00402 buffer1, start1, len1, 00403 buffer2, start2, len2); 00404 #else 00405 00406 struct msghdr m; 00407 struct cmsghdr *cm; 00408 struct iovec iov[2]; 00409 int bytes_written; 00410 00411 _dbus_assert (len1 >= 0); 00412 _dbus_assert (len2 >= 0); 00413 _dbus_assert (n_fds >= 0); 00414 00415 _DBUS_ZERO(iov); 00416 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1); 00417 iov[0].iov_len = len1; 00418 00419 if (buffer2) 00420 { 00421 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2); 00422 iov[1].iov_len = len2; 00423 } 00424 00425 _DBUS_ZERO(m); 00426 m.msg_iov = iov; 00427 m.msg_iovlen = buffer2 ? 2 : 1; 00428 00429 if (n_fds > 0) 00430 { 00431 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int)); 00432 m.msg_control = alloca(m.msg_controllen); 00433 memset(m.msg_control, 0, m.msg_controllen); 00434 00435 cm = CMSG_FIRSTHDR(&m); 00436 cm->cmsg_level = SOL_SOCKET; 00437 cm->cmsg_type = SCM_RIGHTS; 00438 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int)); 00439 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int)); 00440 } 00441 00442 again: 00443 00444 bytes_written = sendmsg (fd, &m, 0 00445 #if HAVE_DECL_MSG_NOSIGNAL 00446 |MSG_NOSIGNAL 00447 #endif 00448 ); 00449 00450 if (bytes_written < 0 && errno == EINTR) 00451 goto again; 00452 00453 #if 0 00454 if (bytes_written > 0) 00455 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00456 #endif 00457 00458 return bytes_written; 00459 #endif 00460 } 00461 00475 int 00476 _dbus_write_socket_two (int fd, 00477 const DBusString *buffer1, 00478 int start1, 00479 int len1, 00480 const DBusString *buffer2, 00481 int start2, 00482 int len2) 00483 { 00484 #if HAVE_DECL_MSG_NOSIGNAL 00485 struct iovec vectors[2]; 00486 const char *data1; 00487 const char *data2; 00488 int bytes_written; 00489 struct msghdr m; 00490 00491 _dbus_assert (buffer1 != NULL); 00492 _dbus_assert (start1 >= 0); 00493 _dbus_assert (start2 >= 0); 00494 _dbus_assert (len1 >= 0); 00495 _dbus_assert (len2 >= 0); 00496 00497 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00498 00499 if (buffer2 != NULL) 00500 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00501 else 00502 { 00503 data2 = NULL; 00504 start2 = 0; 00505 len2 = 0; 00506 } 00507 00508 vectors[0].iov_base = (char*) data1; 00509 vectors[0].iov_len = len1; 00510 vectors[1].iov_base = (char*) data2; 00511 vectors[1].iov_len = len2; 00512 00513 _DBUS_ZERO(m); 00514 m.msg_iov = vectors; 00515 m.msg_iovlen = data2 ? 2 : 1; 00516 00517 again: 00518 00519 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL); 00520 00521 if (bytes_written < 0 && errno == EINTR) 00522 goto again; 00523 00524 return bytes_written; 00525 00526 #else 00527 return _dbus_write_two (fd, buffer1, start1, len1, 00528 buffer2, start2, len2); 00529 #endif 00530 } 00531 00532 dbus_bool_t 00533 _dbus_socket_is_invalid (int fd) 00534 { 00535 return fd < 0 ? TRUE : FALSE; 00536 } 00537 00554 int 00555 _dbus_read (int fd, 00556 DBusString *buffer, 00557 int count) 00558 { 00559 int bytes_read; 00560 int start; 00561 char *data; 00562 00563 _dbus_assert (count >= 0); 00564 00565 start = _dbus_string_get_length (buffer); 00566 00567 if (!_dbus_string_lengthen (buffer, count)) 00568 { 00569 errno = ENOMEM; 00570 return -1; 00571 } 00572 00573 data = _dbus_string_get_data_len (buffer, start, count); 00574 00575 again: 00576 00577 bytes_read = read (fd, data, count); 00578 00579 if (bytes_read < 0) 00580 { 00581 if (errno == EINTR) 00582 goto again; 00583 else 00584 { 00585 /* put length back (note that this doesn't actually realloc anything) */ 00586 _dbus_string_set_length (buffer, start); 00587 return -1; 00588 } 00589 } 00590 else 00591 { 00592 /* put length back (doesn't actually realloc) */ 00593 _dbus_string_set_length (buffer, start + bytes_read); 00594 00595 #if 0 00596 if (bytes_read > 0) 00597 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00598 #endif 00599 00600 return bytes_read; 00601 } 00602 } 00603 00614 int 00615 _dbus_write (int fd, 00616 const DBusString *buffer, 00617 int start, 00618 int len) 00619 { 00620 const char *data; 00621 int bytes_written; 00622 00623 data = _dbus_string_get_const_data_len (buffer, start, len); 00624 00625 again: 00626 00627 bytes_written = write (fd, data, len); 00628 00629 if (bytes_written < 0 && errno == EINTR) 00630 goto again; 00631 00632 #if 0 00633 if (bytes_written > 0) 00634 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00635 #endif 00636 00637 return bytes_written; 00638 } 00639 00660 int 00661 _dbus_write_two (int fd, 00662 const DBusString *buffer1, 00663 int start1, 00664 int len1, 00665 const DBusString *buffer2, 00666 int start2, 00667 int len2) 00668 { 00669 _dbus_assert (buffer1 != NULL); 00670 _dbus_assert (start1 >= 0); 00671 _dbus_assert (start2 >= 0); 00672 _dbus_assert (len1 >= 0); 00673 _dbus_assert (len2 >= 0); 00674 00675 #ifdef HAVE_WRITEV 00676 { 00677 struct iovec vectors[2]; 00678 const char *data1; 00679 const char *data2; 00680 int bytes_written; 00681 00682 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00683 00684 if (buffer2 != NULL) 00685 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00686 else 00687 { 00688 data2 = NULL; 00689 start2 = 0; 00690 len2 = 0; 00691 } 00692 00693 vectors[0].iov_base = (char*) data1; 00694 vectors[0].iov_len = len1; 00695 vectors[1].iov_base = (char*) data2; 00696 vectors[1].iov_len = len2; 00697 00698 again: 00699 00700 bytes_written = writev (fd, 00701 vectors, 00702 data2 ? 2 : 1); 00703 00704 if (bytes_written < 0 && errno == EINTR) 00705 goto again; 00706 00707 return bytes_written; 00708 } 00709 #else /* HAVE_WRITEV */ 00710 { 00711 int ret1; 00712 00713 ret1 = _dbus_write (fd, buffer1, start1, len1); 00714 if (ret1 == len1 && buffer2 != NULL) 00715 { 00716 ret2 = _dbus_write (fd, buffer2, start2, len2); 00717 if (ret2 < 0) 00718 ret2 = 0; /* we can't report an error as the first write was OK */ 00719 00720 return ret1 + ret2; 00721 } 00722 else 00723 return ret1; 00724 } 00725 #endif /* !HAVE_WRITEV */ 00726 } 00727 00728 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00729 00759 int 00760 _dbus_connect_unix_socket (const char *path, 00761 dbus_bool_t abstract, 00762 DBusError *error) 00763 { 00764 int fd; 00765 size_t path_len; 00766 struct sockaddr_un addr; 00767 00768 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00769 00770 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00771 path, abstract); 00772 00773 00774 if (!_dbus_open_unix_socket (&fd, error)) 00775 { 00776 _DBUS_ASSERT_ERROR_IS_SET(error); 00777 return -1; 00778 } 00779 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00780 00781 _DBUS_ZERO (addr); 00782 addr.sun_family = AF_UNIX; 00783 path_len = strlen (path); 00784 00785 if (abstract) 00786 { 00787 #ifdef HAVE_ABSTRACT_SOCKETS 00788 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00789 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00790 00791 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00792 { 00793 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00794 "Abstract socket name too long\n"); 00795 _dbus_close (fd, NULL); 00796 return -1; 00797 } 00798 00799 strncpy (&addr.sun_path[1], path, path_len); 00800 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00801 #else /* HAVE_ABSTRACT_SOCKETS */ 00802 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00803 "Operating system does not support abstract socket namespace\n"); 00804 _dbus_close (fd, NULL); 00805 return -1; 00806 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00807 } 00808 else 00809 { 00810 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00811 { 00812 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00813 "Socket name too long\n"); 00814 _dbus_close (fd, NULL); 00815 return -1; 00816 } 00817 00818 strncpy (addr.sun_path, path, path_len); 00819 } 00820 00821 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00822 { 00823 dbus_set_error (error, 00824 _dbus_error_from_errno (errno), 00825 "Failed to connect to socket %s: %s", 00826 path, _dbus_strerror (errno)); 00827 00828 _dbus_close (fd, NULL); 00829 return -1; 00830 } 00831 00832 if (!_dbus_set_fd_nonblocking (fd, error)) 00833 { 00834 _DBUS_ASSERT_ERROR_IS_SET (error); 00835 00836 _dbus_close (fd, NULL); 00837 return -1; 00838 } 00839 00840 return fd; 00841 } 00842 00852 static dbus_bool_t 00853 _dbus_set_local_creds (int fd, dbus_bool_t on) 00854 { 00855 dbus_bool_t retval = TRUE; 00856 00857 #if defined(HAVE_CMSGCRED) 00858 /* NOOP just to make sure only one codepath is used 00859 * and to prefer CMSGCRED 00860 */ 00861 #elif defined(LOCAL_CREDS) 00862 int val = on ? 1 : 0; 00863 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) 00864 { 00865 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); 00866 retval = FALSE; 00867 } 00868 else 00869 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", 00870 on ? "enabled" : "disabled", fd); 00871 #endif 00872 00873 return retval; 00874 } 00875 00893 int 00894 _dbus_listen_unix_socket (const char *path, 00895 dbus_bool_t abstract, 00896 DBusError *error) 00897 { 00898 int listen_fd; 00899 struct sockaddr_un addr; 00900 size_t path_len; 00901 unsigned int reuseaddr; 00902 00903 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00904 00905 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 00906 path, abstract); 00907 00908 if (!_dbus_open_unix_socket (&listen_fd, error)) 00909 { 00910 _DBUS_ASSERT_ERROR_IS_SET(error); 00911 return -1; 00912 } 00913 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00914 00915 _DBUS_ZERO (addr); 00916 addr.sun_family = AF_UNIX; 00917 path_len = strlen (path); 00918 00919 if (abstract) 00920 { 00921 #ifdef HAVE_ABSTRACT_SOCKETS 00922 /* remember that abstract names aren't nul-terminated so we rely 00923 * on sun_path being filled in with zeroes above. 00924 */ 00925 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00926 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00927 00928 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00929 { 00930 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00931 "Abstract socket name too long\n"); 00932 _dbus_close (listen_fd, NULL); 00933 return -1; 00934 } 00935 00936 strncpy (&addr.sun_path[1], path, path_len); 00937 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00938 #else /* HAVE_ABSTRACT_SOCKETS */ 00939 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00940 "Operating system does not support abstract socket namespace\n"); 00941 _dbus_close (listen_fd, NULL); 00942 return -1; 00943 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00944 } 00945 else 00946 { 00947 /* Discussed security implications of this with Nalin, 00948 * and we couldn't think of where it would kick our ass, but 00949 * it still seems a bit sucky. It also has non-security suckage; 00950 * really we'd prefer to exit if the socket is already in use. 00951 * But there doesn't seem to be a good way to do this. 00952 * 00953 * Just to be extra careful, I threw in the stat() - clearly 00954 * the stat() can't *fix* any security issue, but it at least 00955 * avoids inadvertent/accidental data loss. 00956 */ 00957 { 00958 struct stat sb; 00959 00960 if (stat (path, &sb) == 0 && 00961 S_ISSOCK (sb.st_mode)) 00962 unlink (path); 00963 } 00964 00965 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00966 { 00967 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00968 "Abstract socket name too long\n"); 00969 _dbus_close (listen_fd, NULL); 00970 return -1; 00971 } 00972 00973 strncpy (addr.sun_path, path, path_len); 00974 } 00975 00976 reuseaddr = 1; 00977 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 00978 { 00979 _dbus_warn ("Failed to set socket option\"%s\": %s", 00980 path, _dbus_strerror (errno)); 00981 } 00982 00983 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00984 { 00985 dbus_set_error (error, _dbus_error_from_errno (errno), 00986 "Failed to bind socket \"%s\": %s", 00987 path, _dbus_strerror (errno)); 00988 _dbus_close (listen_fd, NULL); 00989 return -1; 00990 } 00991 00992 if (listen (listen_fd, 30 /* backlog */) < 0) 00993 { 00994 dbus_set_error (error, _dbus_error_from_errno (errno), 00995 "Failed to listen on socket \"%s\": %s", 00996 path, _dbus_strerror (errno)); 00997 _dbus_close (listen_fd, NULL); 00998 return -1; 00999 } 01000 01001 if (!_dbus_set_local_creds (listen_fd, TRUE)) 01002 { 01003 dbus_set_error (error, _dbus_error_from_errno (errno), 01004 "Failed to enable LOCAL_CREDS on socket \"%s\": %s", 01005 path, _dbus_strerror (errno)); 01006 close (listen_fd); 01007 return -1; 01008 } 01009 01010 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01011 { 01012 _DBUS_ASSERT_ERROR_IS_SET (error); 01013 _dbus_close (listen_fd, NULL); 01014 return -1; 01015 } 01016 01017 /* Try opening up the permissions, but if we can't, just go ahead 01018 * and continue, maybe it will be good enough. 01019 */ 01020 if (!abstract && chmod (path, 0777) < 0) 01021 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01022 path); 01023 01024 return listen_fd; 01025 } 01026 01037 int 01038 _dbus_listen_systemd_sockets (int **fds, 01039 DBusError *error) 01040 { 01041 int r, n; 01042 unsigned fd; 01043 int *new_fds; 01044 01045 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01046 01047 n = sd_listen_fds (TRUE); 01048 if (n < 0) 01049 { 01050 dbus_set_error (error, _dbus_error_from_errno (-n), 01051 "Failed to acquire systemd socket: %s", 01052 _dbus_strerror (-n)); 01053 return -1; 01054 } 01055 01056 if (n <= 0) 01057 { 01058 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01059 "No socket received."); 01060 return -1; 01061 } 01062 01063 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01064 { 01065 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01066 if (r < 0) 01067 { 01068 dbus_set_error (error, _dbus_error_from_errno (-r), 01069 "Failed to verify systemd socket type: %s", 01070 _dbus_strerror (-r)); 01071 return -1; 01072 } 01073 01074 if (!r) 01075 { 01076 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01077 "Passed socket has wrong type."); 01078 return -1; 01079 } 01080 } 01081 01082 /* OK, the file descriptors are all good, so let's take posession of 01083 them then. */ 01084 01085 new_fds = dbus_new (int, n); 01086 if (!new_fds) 01087 { 01088 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01089 "Failed to allocate file handle array."); 01090 goto fail; 01091 } 01092 01093 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01094 { 01095 if (!_dbus_set_local_creds (fd, TRUE)) 01096 { 01097 dbus_set_error (error, _dbus_error_from_errno (errno), 01098 "Failed to enable LOCAL_CREDS on systemd socket: %s", 01099 _dbus_strerror (errno)); 01100 goto fail; 01101 } 01102 01103 if (!_dbus_set_fd_nonblocking (fd, error)) 01104 { 01105 _DBUS_ASSERT_ERROR_IS_SET (error); 01106 goto fail; 01107 } 01108 01109 new_fds[fd - SD_LISTEN_FDS_START] = fd; 01110 } 01111 01112 *fds = new_fds; 01113 return n; 01114 01115 fail: 01116 01117 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01118 { 01119 _dbus_close (fd, NULL); 01120 } 01121 01122 dbus_free (new_fds); 01123 return -1; 01124 } 01125 01139 int 01140 _dbus_connect_tcp_socket (const char *host, 01141 const char *port, 01142 const char *family, 01143 DBusError *error) 01144 { 01145 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01146 } 01147 01148 int 01149 _dbus_connect_tcp_socket_with_nonce (const char *host, 01150 const char *port, 01151 const char *family, 01152 const char *noncefile, 01153 DBusError *error) 01154 { 01155 int saved_errno = 0; 01156 int fd = -1, res; 01157 struct addrinfo hints; 01158 struct addrinfo *ai, *tmp; 01159 01160 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01161 01162 _DBUS_ZERO (hints); 01163 01164 if (!family) 01165 hints.ai_family = AF_UNSPEC; 01166 else if (!strcmp(family, "ipv4")) 01167 hints.ai_family = AF_INET; 01168 else if (!strcmp(family, "ipv6")) 01169 hints.ai_family = AF_INET6; 01170 else 01171 { 01172 dbus_set_error (error, 01173 DBUS_ERROR_BAD_ADDRESS, 01174 "Unknown address family %s", family); 01175 return -1; 01176 } 01177 hints.ai_protocol = IPPROTO_TCP; 01178 hints.ai_socktype = SOCK_STREAM; 01179 hints.ai_flags = AI_ADDRCONFIG; 01180 01181 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01182 { 01183 dbus_set_error (error, 01184 _dbus_error_from_errno (errno), 01185 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01186 host, port, gai_strerror(res), res); 01187 _dbus_close (fd, NULL); 01188 return -1; 01189 } 01190 01191 tmp = ai; 01192 while (tmp) 01193 { 01194 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01195 { 01196 freeaddrinfo(ai); 01197 _DBUS_ASSERT_ERROR_IS_SET(error); 01198 return -1; 01199 } 01200 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01201 01202 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01203 { 01204 saved_errno = errno; 01205 _dbus_close(fd, NULL); 01206 fd = -1; 01207 tmp = tmp->ai_next; 01208 continue; 01209 } 01210 01211 break; 01212 } 01213 freeaddrinfo(ai); 01214 01215 if (fd == -1) 01216 { 01217 dbus_set_error (error, 01218 _dbus_error_from_errno (saved_errno), 01219 "Failed to connect to socket \"%s:%s\" %s", 01220 host, port, _dbus_strerror(saved_errno)); 01221 return -1; 01222 } 01223 01224 if (noncefile != NULL) 01225 { 01226 DBusString noncefileStr; 01227 dbus_bool_t ret; 01228 _dbus_string_init_const (&noncefileStr, noncefile); 01229 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01230 _dbus_string_free (&noncefileStr); 01231 01232 if (!ret) 01233 { 01234 _dbus_close (fd, NULL); 01235 return -1; 01236 } 01237 } 01238 01239 if (!_dbus_set_fd_nonblocking (fd, error)) 01240 { 01241 _dbus_close (fd, NULL); 01242 return -1; 01243 } 01244 01245 return fd; 01246 } 01247 01264 int 01265 _dbus_listen_tcp_socket (const char *host, 01266 const char *port, 01267 const char *family, 01268 DBusString *retport, 01269 int **fds_p, 01270 DBusError *error) 01271 { 01272 int saved_errno; 01273 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01274 struct addrinfo hints; 01275 struct addrinfo *ai, *tmp; 01276 unsigned int reuseaddr; 01277 01278 *fds_p = NULL; 01279 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01280 01281 _DBUS_ZERO (hints); 01282 01283 if (!family) 01284 hints.ai_family = AF_UNSPEC; 01285 else if (!strcmp(family, "ipv4")) 01286 hints.ai_family = AF_INET; 01287 else if (!strcmp(family, "ipv6")) 01288 hints.ai_family = AF_INET6; 01289 else 01290 { 01291 dbus_set_error (error, 01292 DBUS_ERROR_BAD_ADDRESS, 01293 "Unknown address family %s", family); 01294 return -1; 01295 } 01296 01297 hints.ai_protocol = IPPROTO_TCP; 01298 hints.ai_socktype = SOCK_STREAM; 01299 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01300 01301 redo_lookup_with_port: 01302 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01303 { 01304 dbus_set_error (error, 01305 _dbus_error_from_errno (errno), 01306 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01307 host ? host : "*", port, gai_strerror(res), res); 01308 return -1; 01309 } 01310 01311 tmp = ai; 01312 while (tmp) 01313 { 01314 int fd = -1, *newlisten_fd; 01315 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01316 { 01317 _DBUS_ASSERT_ERROR_IS_SET(error); 01318 goto failed; 01319 } 01320 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01321 01322 reuseaddr = 1; 01323 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01324 { 01325 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01326 host ? host : "*", port, _dbus_strerror (errno)); 01327 } 01328 01329 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01330 { 01331 saved_errno = errno; 01332 _dbus_close(fd, NULL); 01333 if (saved_errno == EADDRINUSE) 01334 { 01335 /* Depending on kernel policy, it may or may not 01336 be neccessary to bind to both IPv4 & 6 addresses 01337 so ignore EADDRINUSE here */ 01338 tmp = tmp->ai_next; 01339 continue; 01340 } 01341 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01342 "Failed to bind socket \"%s:%s\": %s", 01343 host ? host : "*", port, _dbus_strerror (saved_errno)); 01344 goto failed; 01345 } 01346 01347 if (listen (fd, 30 /* backlog */) < 0) 01348 { 01349 saved_errno = errno; 01350 _dbus_close (fd, NULL); 01351 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01352 "Failed to listen on socket \"%s:%s\": %s", 01353 host ? host : "*", port, _dbus_strerror (saved_errno)); 01354 goto failed; 01355 } 01356 01357 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01358 if (!newlisten_fd) 01359 { 01360 saved_errno = errno; 01361 _dbus_close (fd, NULL); 01362 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01363 "Failed to allocate file handle array: %s", 01364 _dbus_strerror (saved_errno)); 01365 goto failed; 01366 } 01367 listen_fd = newlisten_fd; 01368 listen_fd[nlisten_fd] = fd; 01369 nlisten_fd++; 01370 01371 if (!_dbus_string_get_length(retport)) 01372 { 01373 /* If the user didn't specify a port, or used 0, then 01374 the kernel chooses a port. After the first address 01375 is bound to, we need to force all remaining addresses 01376 to use the same port */ 01377 if (!port || !strcmp(port, "0")) 01378 { 01379 int result; 01380 struct sockaddr_storage addr; 01381 socklen_t addrlen; 01382 char portbuf[50]; 01383 01384 addrlen = sizeof(addr); 01385 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01386 01387 if (result == -1 || 01388 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0, 01389 portbuf, sizeof(portbuf), 01390 NI_NUMERICHOST)) != 0) 01391 { 01392 dbus_set_error (error, _dbus_error_from_errno (errno), 01393 "Failed to resolve port \"%s:%s\": %s (%s)", 01394 host ? host : "*", port, gai_strerror(res), res); 01395 goto failed; 01396 } 01397 if (!_dbus_string_append(retport, portbuf)) 01398 { 01399 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01400 goto failed; 01401 } 01402 01403 /* Release current address list & redo lookup */ 01404 port = _dbus_string_get_const_data(retport); 01405 freeaddrinfo(ai); 01406 goto redo_lookup_with_port; 01407 } 01408 else 01409 { 01410 if (!_dbus_string_append(retport, port)) 01411 { 01412 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01413 goto failed; 01414 } 01415 } 01416 } 01417 01418 tmp = tmp->ai_next; 01419 } 01420 freeaddrinfo(ai); 01421 ai = NULL; 01422 01423 if (!nlisten_fd) 01424 { 01425 errno = EADDRINUSE; 01426 dbus_set_error (error, _dbus_error_from_errno (errno), 01427 "Failed to bind socket \"%s:%s\": %s", 01428 host ? host : "*", port, _dbus_strerror (errno)); 01429 goto failed; 01430 } 01431 01432 for (i = 0 ; i < nlisten_fd ; i++) 01433 { 01434 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01435 { 01436 goto failed; 01437 } 01438 } 01439 01440 *fds_p = listen_fd; 01441 01442 return nlisten_fd; 01443 01444 failed: 01445 if (ai) 01446 freeaddrinfo(ai); 01447 for (i = 0 ; i < nlisten_fd ; i++) 01448 _dbus_close(listen_fd[i], NULL); 01449 dbus_free(listen_fd); 01450 return -1; 01451 } 01452 01453 static dbus_bool_t 01454 write_credentials_byte (int server_fd, 01455 DBusError *error) 01456 { 01457 int bytes_written; 01458 char buf[1] = { '\0' }; 01459 #if defined(HAVE_CMSGCRED) 01460 union { 01461 struct cmsghdr hdr; 01462 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01463 } cmsg; 01464 struct iovec iov; 01465 struct msghdr msg; 01466 iov.iov_base = buf; 01467 iov.iov_len = 1; 01468 01469 _DBUS_ZERO(msg); 01470 msg.msg_iov = &iov; 01471 msg.msg_iovlen = 1; 01472 01473 msg.msg_control = (caddr_t) &cmsg; 01474 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01475 _DBUS_ZERO(cmsg); 01476 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01477 cmsg.hdr.cmsg_level = SOL_SOCKET; 01478 cmsg.hdr.cmsg_type = SCM_CREDS; 01479 #endif 01480 01481 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01482 01483 again: 01484 01485 #if defined(HAVE_CMSGCRED) 01486 bytes_written = sendmsg (server_fd, &msg, 0 01487 #if HAVE_DECL_MSG_NOSIGNAL 01488 |MSG_NOSIGNAL 01489 #endif 01490 ); 01491 #else 01492 bytes_written = send (server_fd, buf, 1, 0 01493 #if HAVE_DECL_MSG_NOSIGNAL 01494 |MSG_NOSIGNAL 01495 #endif 01496 ); 01497 #endif 01498 01499 if (bytes_written < 0 && errno == EINTR) 01500 goto again; 01501 01502 if (bytes_written < 0) 01503 { 01504 dbus_set_error (error, _dbus_error_from_errno (errno), 01505 "Failed to write credentials byte: %s", 01506 _dbus_strerror (errno)); 01507 return FALSE; 01508 } 01509 else if (bytes_written == 0) 01510 { 01511 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01512 "wrote zero bytes writing credentials byte"); 01513 return FALSE; 01514 } 01515 else 01516 { 01517 _dbus_assert (bytes_written == 1); 01518 _dbus_verbose ("wrote credentials byte\n"); 01519 return TRUE; 01520 } 01521 } 01522 01544 dbus_bool_t 01545 _dbus_read_credentials_socket (int client_fd, 01546 DBusCredentials *credentials, 01547 DBusError *error) 01548 { 01549 struct msghdr msg; 01550 struct iovec iov; 01551 char buf; 01552 dbus_uid_t uid_read; 01553 dbus_pid_t pid_read; 01554 int bytes_read; 01555 01556 #ifdef HAVE_CMSGCRED 01557 union { 01558 struct cmsghdr hdr; 01559 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01560 } cmsg; 01561 01562 #elif defined(LOCAL_CREDS) 01563 struct { 01564 struct cmsghdr hdr; 01565 struct sockcred cred; 01566 } cmsg; 01567 #endif 01568 01569 uid_read = DBUS_UID_UNSET; 01570 pid_read = DBUS_PID_UNSET; 01571 01572 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01573 01574 /* The POSIX spec certainly doesn't promise this, but 01575 * we need these assertions to fail as soon as we're wrong about 01576 * it so we can do the porting fixups 01577 */ 01578 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01579 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01580 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01581 01582 _dbus_credentials_clear (credentials); 01583 01584 /* Systems supporting LOCAL_CREDS are configured to have this feature 01585 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01586 * the connection. Therefore, the received message must carry the 01587 * credentials information without doing anything special. 01588 */ 01589 01590 iov.iov_base = &buf; 01591 iov.iov_len = 1; 01592 01593 _DBUS_ZERO(msg); 01594 msg.msg_iov = &iov; 01595 msg.msg_iovlen = 1; 01596 01597 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01598 _DBUS_ZERO(cmsg); 01599 msg.msg_control = (caddr_t) &cmsg; 01600 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01601 #endif 01602 01603 again: 01604 bytes_read = recvmsg (client_fd, &msg, 0); 01605 01606 if (bytes_read < 0) 01607 { 01608 if (errno == EINTR) 01609 goto again; 01610 01611 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01612 * normally only call read_credentials if the socket was ready 01613 * for reading 01614 */ 01615 01616 dbus_set_error (error, _dbus_error_from_errno (errno), 01617 "Failed to read credentials byte: %s", 01618 _dbus_strerror (errno)); 01619 return FALSE; 01620 } 01621 else if (bytes_read == 0) 01622 { 01623 /* this should not happen unless we are using recvmsg wrong, 01624 * so is essentially here for paranoia 01625 */ 01626 dbus_set_error (error, DBUS_ERROR_FAILED, 01627 "Failed to read credentials byte (zero-length read)"); 01628 return FALSE; 01629 } 01630 else if (buf != '\0') 01631 { 01632 dbus_set_error (error, DBUS_ERROR_FAILED, 01633 "Credentials byte was not nul"); 01634 return FALSE; 01635 } 01636 01637 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01638 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01639 || cmsg.hdr.cmsg_type != SCM_CREDS) 01640 { 01641 dbus_set_error (error, DBUS_ERROR_FAILED, 01642 "Message from recvmsg() was not SCM_CREDS"); 01643 return FALSE; 01644 } 01645 #endif 01646 01647 _dbus_verbose ("read credentials byte\n"); 01648 01649 { 01650 #ifdef SO_PEERCRED 01651 #ifdef __OpenBSD__ 01652 struct sockpeercred cr; 01653 #else 01654 struct ucred cr; 01655 #endif 01656 int cr_len = sizeof (cr); 01657 01658 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01659 cr_len == sizeof (cr)) 01660 { 01661 pid_read = cr.pid; 01662 uid_read = cr.uid; 01663 } 01664 else 01665 { 01666 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01667 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01668 } 01669 #elif defined(HAVE_CMSGCRED) 01670 struct cmsgcred *cred; 01671 01672 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01673 pid_read = cred->cmcred_pid; 01674 uid_read = cred->cmcred_euid; 01675 #elif defined(LOCAL_CREDS) 01676 pid_read = DBUS_PID_UNSET; 01677 uid_read = cmsg.cred.sc_uid; 01678 /* Since we have already got the credentials from this socket, we can 01679 * disable its LOCAL_CREDS flag if it was ever set. */ 01680 _dbus_set_local_creds (client_fd, FALSE); 01681 #elif defined(HAVE_GETPEEREID) 01682 uid_t euid; 01683 gid_t egid; 01684 if (getpeereid (client_fd, &euid, &egid) == 0) 01685 { 01686 uid_read = euid; 01687 } 01688 else 01689 { 01690 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01691 } 01692 #elif defined(HAVE_GETPEERUCRED) 01693 ucred_t * ucred = NULL; 01694 if (getpeerucred (client_fd, &ucred) == 0) 01695 { 01696 pid_read = ucred_getpid (ucred); 01697 uid_read = ucred_geteuid (ucred); 01698 #ifdef HAVE_ADT 01699 /* generate audit session data based on socket ucred */ 01700 adt_session_data_t *adth = NULL; 01701 adt_export_data_t *data = NULL; 01702 size_t size = 0; 01703 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01704 { 01705 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01706 } 01707 else 01708 { 01709 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01710 { 01711 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01712 } 01713 else 01714 { 01715 size = adt_export_session_data (adth, &data); 01716 if (size <= 0) 01717 { 01718 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01719 } 01720 else 01721 { 01722 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01723 free (data); 01724 } 01725 } 01726 (void) adt_end_session (adth); 01727 } 01728 #endif /* HAVE_ADT */ 01729 } 01730 else 01731 { 01732 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01733 } 01734 if (ucred != NULL) 01735 ucred_free (ucred); 01736 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01737 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01738 #endif 01739 } 01740 01741 _dbus_verbose ("Credentials:" 01742 " pid "DBUS_PID_FORMAT 01743 " uid "DBUS_UID_FORMAT 01744 "\n", 01745 pid_read, 01746 uid_read); 01747 01748 if (pid_read != DBUS_PID_UNSET) 01749 { 01750 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01751 { 01752 _DBUS_SET_OOM (error); 01753 return FALSE; 01754 } 01755 } 01756 01757 if (uid_read != DBUS_UID_UNSET) 01758 { 01759 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01760 { 01761 _DBUS_SET_OOM (error); 01762 return FALSE; 01763 } 01764 } 01765 01766 return TRUE; 01767 } 01768 01786 dbus_bool_t 01787 _dbus_send_credentials_socket (int server_fd, 01788 DBusError *error) 01789 { 01790 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01791 01792 if (write_credentials_byte (server_fd, error)) 01793 return TRUE; 01794 else 01795 return FALSE; 01796 } 01797 01807 int 01808 _dbus_accept (int listen_fd) 01809 { 01810 int client_fd; 01811 struct sockaddr addr; 01812 socklen_t addrlen; 01813 #ifdef HAVE_ACCEPT4 01814 dbus_bool_t cloexec_done; 01815 #endif 01816 01817 addrlen = sizeof (addr); 01818 01819 retry: 01820 01821 #ifdef HAVE_ACCEPT4 01822 /* We assume that if accept4 is available SOCK_CLOEXEC is too */ 01823 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01824 cloexec_done = client_fd >= 0; 01825 01826 if (client_fd < 0 && errno == ENOSYS) 01827 #endif 01828 { 01829 client_fd = accept (listen_fd, &addr, &addrlen); 01830 } 01831 01832 if (client_fd < 0) 01833 { 01834 if (errno == EINTR) 01835 goto retry; 01836 } 01837 01838 _dbus_verbose ("client fd %d accepted\n", client_fd); 01839 01840 #ifdef HAVE_ACCEPT4 01841 if (!cloexec_done) 01842 #endif 01843 { 01844 _dbus_fd_set_close_on_exec(client_fd); 01845 } 01846 01847 return client_fd; 01848 } 01849 01858 dbus_bool_t 01859 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01860 { 01861 const char *directory; 01862 struct stat sb; 01863 01864 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01865 01866 directory = _dbus_string_get_const_data (dir); 01867 01868 if (stat (directory, &sb) < 0) 01869 { 01870 dbus_set_error (error, _dbus_error_from_errno (errno), 01871 "%s", _dbus_strerror (errno)); 01872 01873 return FALSE; 01874 } 01875 01876 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01877 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01878 { 01879 dbus_set_error (error, DBUS_ERROR_FAILED, 01880 "%s directory is not private to the user", directory); 01881 return FALSE; 01882 } 01883 01884 return TRUE; 01885 } 01886 01887 static dbus_bool_t 01888 fill_user_info_from_passwd (struct passwd *p, 01889 DBusUserInfo *info, 01890 DBusError *error) 01891 { 01892 _dbus_assert (p->pw_name != NULL); 01893 _dbus_assert (p->pw_dir != NULL); 01894 01895 info->uid = p->pw_uid; 01896 info->primary_gid = p->pw_gid; 01897 info->username = _dbus_strdup (p->pw_name); 01898 info->homedir = _dbus_strdup (p->pw_dir); 01899 01900 if (info->username == NULL || 01901 info->homedir == NULL) 01902 { 01903 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01904 return FALSE; 01905 } 01906 01907 return TRUE; 01908 } 01909 01910 static dbus_bool_t 01911 fill_user_info (DBusUserInfo *info, 01912 dbus_uid_t uid, 01913 const DBusString *username, 01914 DBusError *error) 01915 { 01916 const char *username_c; 01917 01918 /* exactly one of username/uid provided */ 01919 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 01920 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 01921 01922 info->uid = DBUS_UID_UNSET; 01923 info->primary_gid = DBUS_GID_UNSET; 01924 info->group_ids = NULL; 01925 info->n_group_ids = 0; 01926 info->username = NULL; 01927 info->homedir = NULL; 01928 01929 if (username != NULL) 01930 username_c = _dbus_string_get_const_data (username); 01931 else 01932 username_c = NULL; 01933 01934 /* For now assuming that the getpwnam() and getpwuid() flavors 01935 * are always symmetrical, if not we have to add more configure 01936 * checks 01937 */ 01938 01939 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 01940 { 01941 struct passwd *p; 01942 int result; 01943 size_t buflen; 01944 char *buf; 01945 struct passwd p_str; 01946 01947 /* retrieve maximum needed size for buf */ 01948 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 01949 01950 /* sysconf actually returns a long, but everything else expects size_t, 01951 * so just recast here. 01952 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 01953 */ 01954 if ((long) buflen <= 0) 01955 buflen = 1024; 01956 01957 result = -1; 01958 while (1) 01959 { 01960 buf = dbus_malloc (buflen); 01961 if (buf == NULL) 01962 { 01963 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01964 return FALSE; 01965 } 01966 01967 p = NULL; 01968 #ifdef HAVE_POSIX_GETPWNAM_R 01969 if (uid != DBUS_UID_UNSET) 01970 result = getpwuid_r (uid, &p_str, buf, buflen, 01971 &p); 01972 else 01973 result = getpwnam_r (username_c, &p_str, buf, buflen, 01974 &p); 01975 #else 01976 if (uid != DBUS_UID_UNSET) 01977 p = getpwuid_r (uid, &p_str, buf, buflen); 01978 else 01979 p = getpwnam_r (username_c, &p_str, buf, buflen); 01980 result = 0; 01981 #endif /* !HAVE_POSIX_GETPWNAM_R */ 01982 //Try a bigger buffer if ERANGE was returned 01983 if (result == ERANGE && buflen < 512 * 1024) 01984 { 01985 dbus_free (buf); 01986 buflen *= 2; 01987 } 01988 else 01989 { 01990 break; 01991 } 01992 } 01993 if (result == 0 && p == &p_str) 01994 { 01995 if (!fill_user_info_from_passwd (p, info, error)) 01996 { 01997 dbus_free (buf); 01998 return FALSE; 01999 } 02000 dbus_free (buf); 02001 } 02002 else 02003 { 02004 dbus_set_error (error, _dbus_error_from_errno (errno), 02005 "User \"%s\" unknown or no memory to allocate password entry\n", 02006 username_c ? username_c : "???"); 02007 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02008 dbus_free (buf); 02009 return FALSE; 02010 } 02011 } 02012 #else /* ! HAVE_GETPWNAM_R */ 02013 { 02014 /* I guess we're screwed on thread safety here */ 02015 struct passwd *p; 02016 02017 if (uid != DBUS_UID_UNSET) 02018 p = getpwuid (uid); 02019 else 02020 p = getpwnam (username_c); 02021 02022 if (p != NULL) 02023 { 02024 if (!fill_user_info_from_passwd (p, info, error)) 02025 { 02026 return FALSE; 02027 } 02028 } 02029 else 02030 { 02031 dbus_set_error (error, _dbus_error_from_errno (errno), 02032 "User \"%s\" unknown or no memory to allocate password entry\n", 02033 username_c ? username_c : "???"); 02034 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02035 return FALSE; 02036 } 02037 } 02038 #endif /* ! HAVE_GETPWNAM_R */ 02039 02040 /* Fill this in so we can use it to get groups */ 02041 username_c = info->username; 02042 02043 #ifdef HAVE_GETGROUPLIST 02044 { 02045 gid_t *buf; 02046 int buf_count; 02047 int i; 02048 int initial_buf_count; 02049 02050 initial_buf_count = 17; 02051 buf_count = initial_buf_count; 02052 buf = dbus_new (gid_t, buf_count); 02053 if (buf == NULL) 02054 { 02055 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02056 goto failed; 02057 } 02058 02059 if (getgrouplist (username_c, 02060 info->primary_gid, 02061 buf, &buf_count) < 0) 02062 { 02063 gid_t *new; 02064 /* Presumed cause of negative return code: buf has insufficient 02065 entries to hold the entire group list. The Linux behavior in this 02066 case is to pass back the actual number of groups in buf_count, but 02067 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02068 So as a hack, try to help out a bit by guessing a larger 02069 number of groups, within reason.. might still fail, of course, 02070 but we can at least print a more informative message. I looked up 02071 the "right way" to do this by downloading Apple's own source code 02072 for the "id" command, and it turns out that they use an 02073 undocumented library function getgrouplist_2 (!) which is not 02074 declared in any header in /usr/include (!!). That did not seem 02075 like the way to go here. 02076 */ 02077 if (buf_count == initial_buf_count) 02078 { 02079 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02080 } 02081 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02082 if (new == NULL) 02083 { 02084 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02085 dbus_free (buf); 02086 goto failed; 02087 } 02088 02089 buf = new; 02090 02091 errno = 0; 02092 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02093 { 02094 if (errno == 0) 02095 { 02096 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02097 username_c, buf_count, buf_count); 02098 } 02099 else 02100 { 02101 dbus_set_error (error, 02102 _dbus_error_from_errno (errno), 02103 "Failed to get groups for username \"%s\" primary GID " 02104 DBUS_GID_FORMAT ": %s\n", 02105 username_c, info->primary_gid, 02106 _dbus_strerror (errno)); 02107 dbus_free (buf); 02108 goto failed; 02109 } 02110 } 02111 } 02112 02113 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02114 if (info->group_ids == NULL) 02115 { 02116 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02117 dbus_free (buf); 02118 goto failed; 02119 } 02120 02121 for (i = 0; i < buf_count; ++i) 02122 info->group_ids[i] = buf[i]; 02123 02124 info->n_group_ids = buf_count; 02125 02126 dbus_free (buf); 02127 } 02128 #else /* HAVE_GETGROUPLIST */ 02129 { 02130 /* We just get the one group ID */ 02131 info->group_ids = dbus_new (dbus_gid_t, 1); 02132 if (info->group_ids == NULL) 02133 { 02134 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02135 goto failed; 02136 } 02137 02138 info->n_group_ids = 1; 02139 02140 (info->group_ids)[0] = info->primary_gid; 02141 } 02142 #endif /* HAVE_GETGROUPLIST */ 02143 02144 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02145 02146 return TRUE; 02147 02148 failed: 02149 _DBUS_ASSERT_ERROR_IS_SET (error); 02150 return FALSE; 02151 } 02152 02161 dbus_bool_t 02162 _dbus_user_info_fill (DBusUserInfo *info, 02163 const DBusString *username, 02164 DBusError *error) 02165 { 02166 return fill_user_info (info, DBUS_UID_UNSET, 02167 username, error); 02168 } 02169 02178 dbus_bool_t 02179 _dbus_user_info_fill_uid (DBusUserInfo *info, 02180 dbus_uid_t uid, 02181 DBusError *error) 02182 { 02183 return fill_user_info (info, uid, 02184 NULL, error); 02185 } 02186 02194 dbus_bool_t 02195 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02196 { 02197 /* The POSIX spec certainly doesn't promise this, but 02198 * we need these assertions to fail as soon as we're wrong about 02199 * it so we can do the porting fixups 02200 */ 02201 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02202 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02203 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02204 02205 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 02206 return FALSE; 02207 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02208 return FALSE; 02209 02210 return TRUE; 02211 } 02212 02224 dbus_bool_t 02225 _dbus_append_user_from_current_process (DBusString *str) 02226 { 02227 return _dbus_string_append_uint (str, 02228 _dbus_geteuid ()); 02229 } 02230 02235 dbus_pid_t 02236 _dbus_getpid (void) 02237 { 02238 return getpid (); 02239 } 02240 02244 dbus_uid_t 02245 _dbus_getuid (void) 02246 { 02247 return getuid (); 02248 } 02249 02253 dbus_uid_t 02254 _dbus_geteuid (void) 02255 { 02256 return geteuid (); 02257 } 02258 02265 unsigned long 02266 _dbus_pid_for_log (void) 02267 { 02268 return getpid (); 02269 } 02270 02278 dbus_bool_t 02279 _dbus_parse_uid (const DBusString *uid_str, 02280 dbus_uid_t *uid) 02281 { 02282 int end; 02283 long val; 02284 02285 if (_dbus_string_get_length (uid_str) == 0) 02286 { 02287 _dbus_verbose ("UID string was zero length\n"); 02288 return FALSE; 02289 } 02290 02291 val = -1; 02292 end = 0; 02293 if (!_dbus_string_parse_int (uid_str, 0, &val, 02294 &end)) 02295 { 02296 _dbus_verbose ("could not parse string as a UID\n"); 02297 return FALSE; 02298 } 02299 02300 if (end != _dbus_string_get_length (uid_str)) 02301 { 02302 _dbus_verbose ("string contained trailing stuff after UID\n"); 02303 return FALSE; 02304 } 02305 02306 *uid = val; 02307 02308 return TRUE; 02309 } 02310 02311 #if !DBUS_USE_SYNC 02312 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02313 #endif 02314 02321 dbus_int32_t 02322 _dbus_atomic_inc (DBusAtomic *atomic) 02323 { 02324 #if DBUS_USE_SYNC 02325 return __sync_add_and_fetch(&atomic->value, 1)-1; 02326 #else 02327 dbus_int32_t res; 02328 _DBUS_LOCK (atomic); 02329 res = atomic->value; 02330 atomic->value += 1; 02331 _DBUS_UNLOCK (atomic); 02332 return res; 02333 #endif 02334 } 02335 02342 dbus_int32_t 02343 _dbus_atomic_dec (DBusAtomic *atomic) 02344 { 02345 #if DBUS_USE_SYNC 02346 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02347 #else 02348 dbus_int32_t res; 02349 02350 _DBUS_LOCK (atomic); 02351 res = atomic->value; 02352 atomic->value -= 1; 02353 _DBUS_UNLOCK (atomic); 02354 return res; 02355 #endif 02356 } 02357 02365 dbus_int32_t 02366 _dbus_atomic_get (DBusAtomic *atomic) 02367 { 02368 #if DBUS_USE_SYNC 02369 __sync_synchronize (); 02370 return atomic->value; 02371 #else 02372 dbus_int32_t res; 02373 02374 _DBUS_LOCK (atomic); 02375 res = atomic->value; 02376 _DBUS_UNLOCK (atomic); 02377 return res; 02378 #endif 02379 } 02380 02381 #ifdef DBUS_BUILD_TESTS 02382 02385 dbus_gid_t 02386 _dbus_getgid (void) 02387 { 02388 return getgid (); 02389 } 02390 #endif 02391 02400 int 02401 _dbus_poll (DBusPollFD *fds, 02402 int n_fds, 02403 int timeout_milliseconds) 02404 { 02405 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02406 /* This big thing is a constant expression and should get optimized 02407 * out of existence. So it's more robust than a configure check at 02408 * no cost. 02409 */ 02410 if (_DBUS_POLLIN == POLLIN && 02411 _DBUS_POLLPRI == POLLPRI && 02412 _DBUS_POLLOUT == POLLOUT && 02413 _DBUS_POLLERR == POLLERR && 02414 _DBUS_POLLHUP == POLLHUP && 02415 _DBUS_POLLNVAL == POLLNVAL && 02416 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02417 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02418 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02419 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02420 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02421 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02422 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02423 { 02424 return poll ((struct pollfd*) fds, 02425 n_fds, 02426 timeout_milliseconds); 02427 } 02428 else 02429 { 02430 /* We have to convert the DBusPollFD to an array of 02431 * struct pollfd, poll, and convert back. 02432 */ 02433 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02434 return -1; 02435 } 02436 #else /* ! HAVE_POLL */ 02437 02438 fd_set read_set, write_set, err_set; 02439 int max_fd = 0; 02440 int i; 02441 struct timeval tv; 02442 int ready; 02443 02444 FD_ZERO (&read_set); 02445 FD_ZERO (&write_set); 02446 FD_ZERO (&err_set); 02447 02448 for (i = 0; i < n_fds; i++) 02449 { 02450 DBusPollFD *fdp = &fds[i]; 02451 02452 if (fdp->events & _DBUS_POLLIN) 02453 FD_SET (fdp->fd, &read_set); 02454 02455 if (fdp->events & _DBUS_POLLOUT) 02456 FD_SET (fdp->fd, &write_set); 02457 02458 FD_SET (fdp->fd, &err_set); 02459 02460 max_fd = MAX (max_fd, fdp->fd); 02461 } 02462 02463 tv.tv_sec = timeout_milliseconds / 1000; 02464 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02465 02466 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02467 timeout_milliseconds < 0 ? NULL : &tv); 02468 02469 if (ready > 0) 02470 { 02471 for (i = 0; i < n_fds; i++) 02472 { 02473 DBusPollFD *fdp = &fds[i]; 02474 02475 fdp->revents = 0; 02476 02477 if (FD_ISSET (fdp->fd, &read_set)) 02478 fdp->revents |= _DBUS_POLLIN; 02479 02480 if (FD_ISSET (fdp->fd, &write_set)) 02481 fdp->revents |= _DBUS_POLLOUT; 02482 02483 if (FD_ISSET (fdp->fd, &err_set)) 02484 fdp->revents |= _DBUS_POLLERR; 02485 } 02486 } 02487 02488 return ready; 02489 #endif 02490 } 02491 02499 void 02500 _dbus_get_current_time (long *tv_sec, 02501 long *tv_usec) 02502 { 02503 struct timeval t; 02504 02505 #ifdef HAVE_MONOTONIC_CLOCK 02506 struct timespec ts; 02507 clock_gettime (CLOCK_MONOTONIC, &ts); 02508 02509 if (tv_sec) 02510 *tv_sec = ts.tv_sec; 02511 if (tv_usec) 02512 *tv_usec = ts.tv_nsec / 1000; 02513 #else 02514 gettimeofday (&t, NULL); 02515 02516 if (tv_sec) 02517 *tv_sec = t.tv_sec; 02518 if (tv_usec) 02519 *tv_usec = t.tv_usec; 02520 #endif 02521 } 02522 02531 dbus_bool_t 02532 _dbus_create_directory (const DBusString *filename, 02533 DBusError *error) 02534 { 02535 const char *filename_c; 02536 02537 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02538 02539 filename_c = _dbus_string_get_const_data (filename); 02540 02541 if (mkdir (filename_c, 0700) < 0) 02542 { 02543 if (errno == EEXIST) 02544 return TRUE; 02545 02546 dbus_set_error (error, DBUS_ERROR_FAILED, 02547 "Failed to create directory %s: %s\n", 02548 filename_c, _dbus_strerror (errno)); 02549 return FALSE; 02550 } 02551 else 02552 return TRUE; 02553 } 02554 02565 dbus_bool_t 02566 _dbus_concat_dir_and_file (DBusString *dir, 02567 const DBusString *next_component) 02568 { 02569 dbus_bool_t dir_ends_in_slash; 02570 dbus_bool_t file_starts_with_slash; 02571 02572 if (_dbus_string_get_length (dir) == 0 || 02573 _dbus_string_get_length (next_component) == 0) 02574 return TRUE; 02575 02576 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02577 _dbus_string_get_length (dir) - 1); 02578 02579 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02580 02581 if (dir_ends_in_slash && file_starts_with_slash) 02582 { 02583 _dbus_string_shorten (dir, 1); 02584 } 02585 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02586 { 02587 if (!_dbus_string_append_byte (dir, '/')) 02588 return FALSE; 02589 } 02590 02591 return _dbus_string_copy (next_component, 0, dir, 02592 _dbus_string_get_length (dir)); 02593 } 02594 02596 #define NANOSECONDS_PER_SECOND 1000000000 02597 02598 #define MICROSECONDS_PER_SECOND 1000000 02599 02600 #define MILLISECONDS_PER_SECOND 1000 02601 02602 #define NANOSECONDS_PER_MILLISECOND 1000000 02603 02604 #define MICROSECONDS_PER_MILLISECOND 1000 02605 02610 void 02611 _dbus_sleep_milliseconds (int milliseconds) 02612 { 02613 #ifdef HAVE_NANOSLEEP 02614 struct timespec req; 02615 struct timespec rem; 02616 02617 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02618 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02619 rem.tv_sec = 0; 02620 rem.tv_nsec = 0; 02621 02622 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02623 req = rem; 02624 #elif defined (HAVE_USLEEP) 02625 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02626 #else /* ! HAVE_USLEEP */ 02627 sleep (MAX (milliseconds / 1000, 1)); 02628 #endif 02629 } 02630 02631 static dbus_bool_t 02632 _dbus_generate_pseudorandom_bytes (DBusString *str, 02633 int n_bytes) 02634 { 02635 int old_len; 02636 char *p; 02637 02638 old_len = _dbus_string_get_length (str); 02639 02640 if (!_dbus_string_lengthen (str, n_bytes)) 02641 return FALSE; 02642 02643 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02644 02645 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02646 02647 return TRUE; 02648 } 02649 02658 dbus_bool_t 02659 _dbus_generate_random_bytes (DBusString *str, 02660 int n_bytes) 02661 { 02662 int old_len; 02663 int fd; 02664 02665 /* FALSE return means "no memory", if it could 02666 * mean something else then we'd need to return 02667 * a DBusError. So we always fall back to pseudorandom 02668 * if the I/O fails. 02669 */ 02670 02671 old_len = _dbus_string_get_length (str); 02672 fd = -1; 02673 02674 /* note, urandom on linux will fall back to pseudorandom */ 02675 fd = open ("/dev/urandom", O_RDONLY); 02676 if (fd < 0) 02677 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02678 02679 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02680 02681 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02682 { 02683 _dbus_close (fd, NULL); 02684 _dbus_string_set_length (str, old_len); 02685 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02686 } 02687 02688 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02689 n_bytes); 02690 02691 _dbus_close (fd, NULL); 02692 02693 return TRUE; 02694 } 02695 02701 void 02702 _dbus_exit (int code) 02703 { 02704 _exit (code); 02705 } 02706 02715 const char* 02716 _dbus_strerror (int error_number) 02717 { 02718 const char *msg; 02719 02720 msg = strerror (error_number); 02721 if (msg == NULL) 02722 msg = "unknown"; 02723 02724 return msg; 02725 } 02726 02730 void 02731 _dbus_disable_sigpipe (void) 02732 { 02733 signal (SIGPIPE, SIG_IGN); 02734 } 02735 02743 void 02744 _dbus_fd_set_close_on_exec (intptr_t fd) 02745 { 02746 int val; 02747 02748 val = fcntl (fd, F_GETFD, 0); 02749 02750 if (val < 0) 02751 return; 02752 02753 val |= FD_CLOEXEC; 02754 02755 fcntl (fd, F_SETFD, val); 02756 } 02757 02765 dbus_bool_t 02766 _dbus_close (int fd, 02767 DBusError *error) 02768 { 02769 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02770 02771 again: 02772 if (close (fd) < 0) 02773 { 02774 if (errno == EINTR) 02775 goto again; 02776 02777 dbus_set_error (error, _dbus_error_from_errno (errno), 02778 "Could not close fd %d", fd); 02779 return FALSE; 02780 } 02781 02782 return TRUE; 02783 } 02784 02792 int 02793 _dbus_dup(int fd, 02794 DBusError *error) 02795 { 02796 int new_fd; 02797 02798 #ifdef F_DUPFD_CLOEXEC 02799 dbus_bool_t cloexec_done; 02800 02801 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02802 cloexec_done = new_fd >= 0; 02803 02804 if (new_fd < 0 && errno == EINVAL) 02805 #endif 02806 { 02807 new_fd = fcntl(fd, F_DUPFD, 3); 02808 } 02809 02810 if (new_fd < 0) { 02811 02812 dbus_set_error (error, _dbus_error_from_errno (errno), 02813 "Could not duplicate fd %d", fd); 02814 return -1; 02815 } 02816 02817 #ifdef F_DUPFD_CLOEXEC 02818 if (!cloexec_done) 02819 #endif 02820 { 02821 _dbus_fd_set_close_on_exec(new_fd); 02822 } 02823 02824 return new_fd; 02825 } 02826 02834 dbus_bool_t 02835 _dbus_set_fd_nonblocking (int fd, 02836 DBusError *error) 02837 { 02838 int val; 02839 02840 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02841 02842 val = fcntl (fd, F_GETFL, 0); 02843 if (val < 0) 02844 { 02845 dbus_set_error (error, _dbus_error_from_errno (errno), 02846 "Failed to get flags from file descriptor %d: %s", 02847 fd, _dbus_strerror (errno)); 02848 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02849 _dbus_strerror (errno)); 02850 return FALSE; 02851 } 02852 02853 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02854 { 02855 dbus_set_error (error, _dbus_error_from_errno (errno), 02856 "Failed to set nonblocking flag of file descriptor %d: %s", 02857 fd, _dbus_strerror (errno)); 02858 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02859 fd, _dbus_strerror (errno)); 02860 02861 return FALSE; 02862 } 02863 02864 return TRUE; 02865 } 02866 02872 void 02873 _dbus_print_backtrace (void) 02874 { 02875 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02876 void *bt[500]; 02877 int bt_size; 02878 int i; 02879 char **syms; 02880 02881 bt_size = backtrace (bt, 500); 02882 02883 syms = backtrace_symbols (bt, bt_size); 02884 02885 i = 0; 02886 while (i < bt_size) 02887 { 02888 /* don't use dbus_warn since it can _dbus_abort() */ 02889 fprintf (stderr, " %s\n", syms[i]); 02890 ++i; 02891 } 02892 fflush (stderr); 02893 02894 free (syms); 02895 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02896 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02897 #else 02898 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02899 #endif 02900 } 02901 02919 dbus_bool_t 02920 _dbus_full_duplex_pipe (int *fd1, 02921 int *fd2, 02922 dbus_bool_t blocking, 02923 DBusError *error) 02924 { 02925 #ifdef HAVE_SOCKETPAIR 02926 int fds[2]; 02927 int retval; 02928 02929 #ifdef SOCK_CLOEXEC 02930 dbus_bool_t cloexec_done; 02931 02932 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 02933 cloexec_done = retval >= 0; 02934 02935 if (retval < 0 && errno == EINVAL) 02936 #endif 02937 { 02938 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 02939 } 02940 02941 if (retval < 0) 02942 { 02943 dbus_set_error (error, _dbus_error_from_errno (errno), 02944 "Could not create full-duplex pipe"); 02945 return FALSE; 02946 } 02947 02948 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02949 02950 #ifdef SOCK_CLOEXEC 02951 if (!cloexec_done) 02952 #endif 02953 { 02954 _dbus_fd_set_close_on_exec (fds[0]); 02955 _dbus_fd_set_close_on_exec (fds[1]); 02956 } 02957 02958 if (!blocking && 02959 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02960 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02961 { 02962 dbus_set_error (error, _dbus_error_from_errno (errno), 02963 "Could not set full-duplex pipe nonblocking"); 02964 02965 _dbus_close (fds[0], NULL); 02966 _dbus_close (fds[1], NULL); 02967 02968 return FALSE; 02969 } 02970 02971 *fd1 = fds[0]; 02972 *fd2 = fds[1]; 02973 02974 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 02975 *fd1, *fd2); 02976 02977 return TRUE; 02978 #else 02979 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 02980 dbus_set_error (error, DBUS_ERROR_FAILED, 02981 "_dbus_full_duplex_pipe() not implemented on this OS"); 02982 return FALSE; 02983 #endif 02984 } 02985 02994 int 02995 _dbus_printf_string_upper_bound (const char *format, 02996 va_list args) 02997 { 02998 char c; 02999 return vsnprintf (&c, 1, format, args); 03000 } 03001 03008 const char* 03009 _dbus_get_tmpdir(void) 03010 { 03011 static const char* tmpdir = NULL; 03012 03013 if (tmpdir == NULL) 03014 { 03015 /* TMPDIR is what glibc uses, then 03016 * glibc falls back to the P_tmpdir macro which 03017 * just expands to "/tmp" 03018 */ 03019 if (tmpdir == NULL) 03020 tmpdir = getenv("TMPDIR"); 03021 03022 /* These two env variables are probably 03023 * broken, but maybe some OS uses them? 03024 */ 03025 if (tmpdir == NULL) 03026 tmpdir = getenv("TMP"); 03027 if (tmpdir == NULL) 03028 tmpdir = getenv("TEMP"); 03029 03030 /* And this is the sane fallback. */ 03031 if (tmpdir == NULL) 03032 tmpdir = "/tmp"; 03033 } 03034 03035 _dbus_assert(tmpdir != NULL); 03036 03037 return tmpdir; 03038 } 03039 03059 static dbus_bool_t 03060 _read_subprocess_line_argv (const char *progpath, 03061 dbus_bool_t path_fallback, 03062 char * const *argv, 03063 DBusString *result, 03064 DBusError *error) 03065 { 03066 int result_pipe[2] = { -1, -1 }; 03067 int errors_pipe[2] = { -1, -1 }; 03068 pid_t pid; 03069 int ret; 03070 int status; 03071 int orig_len; 03072 int i; 03073 03074 dbus_bool_t retval; 03075 sigset_t new_set, old_set; 03076 03077 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03078 retval = FALSE; 03079 03080 /* We need to block any existing handlers for SIGCHLD temporarily; they 03081 * will cause waitpid() below to fail. 03082 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03083 */ 03084 sigemptyset (&new_set); 03085 sigaddset (&new_set, SIGCHLD); 03086 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03087 03088 orig_len = _dbus_string_get_length (result); 03089 03090 #define READ_END 0 03091 #define WRITE_END 1 03092 if (pipe (result_pipe) < 0) 03093 { 03094 dbus_set_error (error, _dbus_error_from_errno (errno), 03095 "Failed to create a pipe to call %s: %s", 03096 progpath, _dbus_strerror (errno)); 03097 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03098 progpath, _dbus_strerror (errno)); 03099 goto out; 03100 } 03101 if (pipe (errors_pipe) < 0) 03102 { 03103 dbus_set_error (error, _dbus_error_from_errno (errno), 03104 "Failed to create a pipe to call %s: %s", 03105 progpath, _dbus_strerror (errno)); 03106 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03107 progpath, _dbus_strerror (errno)); 03108 goto out; 03109 } 03110 03111 pid = fork (); 03112 if (pid < 0) 03113 { 03114 dbus_set_error (error, _dbus_error_from_errno (errno), 03115 "Failed to fork() to call %s: %s", 03116 progpath, _dbus_strerror (errno)); 03117 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03118 progpath, _dbus_strerror (errno)); 03119 goto out; 03120 } 03121 03122 if (pid == 0) 03123 { 03124 /* child process */ 03125 int maxfds; 03126 int fd; 03127 03128 fd = open ("/dev/null", O_RDWR); 03129 if (fd == -1) 03130 /* huh?! can't open /dev/null? */ 03131 _exit (1); 03132 03133 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03134 03135 /* set-up stdXXX */ 03136 close (result_pipe[READ_END]); 03137 close (errors_pipe[READ_END]); 03138 close (0); /* close stdin */ 03139 close (1); /* close stdout */ 03140 close (2); /* close stderr */ 03141 03142 if (dup2 (fd, 0) == -1) 03143 _exit (1); 03144 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03145 _exit (1); 03146 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03147 _exit (1); 03148 03149 maxfds = sysconf (_SC_OPEN_MAX); 03150 /* Pick something reasonable if for some reason sysconf 03151 * says unlimited. 03152 */ 03153 if (maxfds < 0) 03154 maxfds = 1024; 03155 /* close all inherited fds */ 03156 for (i = 3; i < maxfds; i++) 03157 close (i); 03158 03159 sigprocmask (SIG_SETMASK, &old_set, NULL); 03160 03161 /* If it looks fully-qualified, try execv first */ 03162 if (progpath[0] == '/') 03163 { 03164 execv (progpath, argv); 03165 /* Ok, that failed. Now if path_fallback is given, let's 03166 * try unqualified. This is mostly a hack to work 03167 * around systems which ship dbus-launch in /usr/bin 03168 * but everything else in /bin (because dbus-launch 03169 * depends on X11). 03170 */ 03171 if (path_fallback) 03172 /* We must have a slash, because we checked above */ 03173 execvp (strrchr (progpath, '/')+1, argv); 03174 } 03175 else 03176 execvp (progpath, argv); 03177 03178 /* still nothing, we failed */ 03179 _exit (1); 03180 } 03181 03182 /* parent process */ 03183 close (result_pipe[WRITE_END]); 03184 close (errors_pipe[WRITE_END]); 03185 result_pipe[WRITE_END] = -1; 03186 errors_pipe[WRITE_END] = -1; 03187 03188 ret = 0; 03189 do 03190 { 03191 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03192 } 03193 while (ret > 0); 03194 03195 /* reap the child process to avoid it lingering as zombie */ 03196 do 03197 { 03198 ret = waitpid (pid, &status, 0); 03199 } 03200 while (ret == -1 && errno == EINTR); 03201 03202 /* We succeeded if the process exited with status 0 and 03203 anything was read */ 03204 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03205 { 03206 /* The process ended with error */ 03207 DBusString error_message; 03208 if (!_dbus_string_init (&error_message)) 03209 { 03210 _DBUS_SET_OOM (error); 03211 goto out; 03212 } 03213 03214 ret = 0; 03215 do 03216 { 03217 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03218 } 03219 while (ret > 0); 03220 03221 _dbus_string_set_length (result, orig_len); 03222 if (_dbus_string_get_length (&error_message) > 0) 03223 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03224 "%s terminated abnormally with the following error: %s", 03225 progpath, _dbus_string_get_data (&error_message)); 03226 else 03227 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03228 "%s terminated abnormally without any error message", 03229 progpath); 03230 goto out; 03231 } 03232 03233 retval = TRUE; 03234 03235 out: 03236 sigprocmask (SIG_SETMASK, &old_set, NULL); 03237 03238 if (retval) 03239 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03240 else 03241 _DBUS_ASSERT_ERROR_IS_SET (error); 03242 03243 if (result_pipe[0] != -1) 03244 close (result_pipe[0]); 03245 if (result_pipe[1] != -1) 03246 close (result_pipe[1]); 03247 if (errors_pipe[0] != -1) 03248 close (errors_pipe[0]); 03249 if (errors_pipe[1] != -1) 03250 close (errors_pipe[1]); 03251 03252 return retval; 03253 } 03254 03266 dbus_bool_t 03267 _dbus_get_autolaunch_address (const char *scope, 03268 DBusString *address, 03269 DBusError *error) 03270 { 03271 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03272 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03273 * but that's done elsewhere, and if it worked, this function wouldn't 03274 * be called.) */ 03275 const char *display; 03276 static char *argv[6]; 03277 int i; 03278 DBusString uuid; 03279 dbus_bool_t retval; 03280 03281 if (_dbus_check_setuid ()) 03282 { 03283 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03284 "Unable to autolaunch when setuid"); 03285 return FALSE; 03286 } 03287 03288 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03289 retval = FALSE; 03290 03291 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03292 * dbus-launch-x11 is just going to fail. Rather than trying to 03293 * run it, we might as well bail out early with a nice error. */ 03294 display = _dbus_getenv ("DISPLAY"); 03295 03296 if (display == NULL || display[0] == '\0') 03297 { 03298 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03299 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03300 return FALSE; 03301 } 03302 03303 if (!_dbus_string_init (&uuid)) 03304 { 03305 _DBUS_SET_OOM (error); 03306 return FALSE; 03307 } 03308 03309 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03310 { 03311 _DBUS_SET_OOM (error); 03312 goto out; 03313 } 03314 03315 i = 0; 03316 argv[i] = "dbus-launch"; 03317 ++i; 03318 argv[i] = "--autolaunch"; 03319 ++i; 03320 argv[i] = _dbus_string_get_data (&uuid); 03321 ++i; 03322 argv[i] = "--binary-syntax"; 03323 ++i; 03324 argv[i] = "--close-stderr"; 03325 ++i; 03326 argv[i] = NULL; 03327 ++i; 03328 03329 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03330 03331 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03332 TRUE, 03333 argv, address, error); 03334 03335 out: 03336 _dbus_string_free (&uuid); 03337 return retval; 03338 #else 03339 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03340 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03341 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03342 return FALSE; 03343 #endif 03344 } 03345 03364 dbus_bool_t 03365 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03366 dbus_bool_t create_if_not_found, 03367 DBusError *error) 03368 { 03369 DBusString filename; 03370 dbus_bool_t b; 03371 03372 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03373 03374 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03375 if (b) 03376 return TRUE; 03377 03378 dbus_error_free (error); 03379 03380 /* Fallback to the system machine ID */ 03381 _dbus_string_init_const (&filename, "/etc/machine-id"); 03382 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03383 } 03384 03385 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03386 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03387 03394 dbus_bool_t 03395 _dbus_lookup_launchd_socket (DBusString *socket_path, 03396 const char *launchd_env_var, 03397 DBusError *error) 03398 { 03399 #ifdef DBUS_ENABLE_LAUNCHD 03400 char *argv[4]; 03401 int i; 03402 03403 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03404 03405 if (_dbus_check_setuid ()) 03406 { 03407 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03408 "Unable to find launchd socket when setuid"); 03409 return FALSE; 03410 } 03411 03412 i = 0; 03413 argv[i] = "launchctl"; 03414 ++i; 03415 argv[i] = "getenv"; 03416 ++i; 03417 argv[i] = (char*)launchd_env_var; 03418 ++i; 03419 argv[i] = NULL; 03420 ++i; 03421 03422 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03423 03424 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03425 { 03426 return FALSE; 03427 } 03428 03429 /* no error, but no result either */ 03430 if (_dbus_string_get_length(socket_path) == 0) 03431 { 03432 return FALSE; 03433 } 03434 03435 /* strip the carriage-return */ 03436 _dbus_string_shorten(socket_path, 1); 03437 return TRUE; 03438 #else /* DBUS_ENABLE_LAUNCHD */ 03439 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03440 "can't lookup socket from launchd; launchd support not compiled in"); 03441 return FALSE; 03442 #endif 03443 } 03444 03445 static dbus_bool_t 03446 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03447 { 03448 #ifdef DBUS_ENABLE_LAUNCHD 03449 dbus_bool_t valid_socket; 03450 DBusString socket_path; 03451 03452 if (_dbus_check_setuid ()) 03453 { 03454 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03455 "Unable to find launchd socket when setuid"); 03456 return FALSE; 03457 } 03458 03459 if (!_dbus_string_init (&socket_path)) 03460 { 03461 _DBUS_SET_OOM (error); 03462 return FALSE; 03463 } 03464 03465 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03466 03467 if (dbus_error_is_set(error)) 03468 { 03469 _dbus_string_free(&socket_path); 03470 return FALSE; 03471 } 03472 03473 if (!valid_socket) 03474 { 03475 dbus_set_error(error, "no socket path", 03476 "launchd did not provide a socket path, " 03477 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03478 _dbus_string_free(&socket_path); 03479 return FALSE; 03480 } 03481 if (!_dbus_string_append (address, "unix:path=")) 03482 { 03483 _DBUS_SET_OOM (error); 03484 _dbus_string_free(&socket_path); 03485 return FALSE; 03486 } 03487 if (!_dbus_string_copy (&socket_path, 0, address, 03488 _dbus_string_get_length (address))) 03489 { 03490 _DBUS_SET_OOM (error); 03491 _dbus_string_free(&socket_path); 03492 return FALSE; 03493 } 03494 03495 _dbus_string_free(&socket_path); 03496 return TRUE; 03497 #else 03498 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03499 "can't lookup session address from launchd; launchd support not compiled in"); 03500 return FALSE; 03501 #endif 03502 } 03503 03523 dbus_bool_t 03524 _dbus_lookup_session_address (dbus_bool_t *supported, 03525 DBusString *address, 03526 DBusError *error) 03527 { 03528 #ifdef DBUS_ENABLE_LAUNCHD 03529 *supported = TRUE; 03530 return _dbus_lookup_session_address_launchd (address, error); 03531 #else 03532 /* On non-Mac Unix platforms, if the session address isn't already 03533 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03534 * fall back to the autolaunch: global default; see 03535 * init_session_address in dbus/dbus-bus.c. */ 03536 *supported = FALSE; 03537 return TRUE; 03538 #endif 03539 } 03540 03558 dbus_bool_t 03559 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03560 { 03561 const char *xdg_data_home; 03562 const char *xdg_data_dirs; 03563 DBusString servicedir_path; 03564 03565 if (!_dbus_string_init (&servicedir_path)) 03566 return FALSE; 03567 03568 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03569 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03570 03571 if (xdg_data_home != NULL) 03572 { 03573 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03574 goto oom; 03575 } 03576 else 03577 { 03578 const DBusString *homedir; 03579 DBusString local_share; 03580 03581 if (!_dbus_homedir_from_current_process (&homedir)) 03582 goto oom; 03583 03584 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03585 goto oom; 03586 03587 _dbus_string_init_const (&local_share, "/.local/share"); 03588 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03589 goto oom; 03590 } 03591 03592 if (!_dbus_string_append (&servicedir_path, ":")) 03593 goto oom; 03594 03595 if (xdg_data_dirs != NULL) 03596 { 03597 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03598 goto oom; 03599 03600 if (!_dbus_string_append (&servicedir_path, ":")) 03601 goto oom; 03602 } 03603 else 03604 { 03605 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03606 goto oom; 03607 } 03608 03609 /* 03610 * add configured datadir to defaults 03611 * this may be the same as an xdg dir 03612 * however the config parser should take 03613 * care of duplicates 03614 */ 03615 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03616 goto oom; 03617 03618 if (!_dbus_split_paths_and_append (&servicedir_path, 03619 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03620 dirs)) 03621 goto oom; 03622 03623 _dbus_string_free (&servicedir_path); 03624 return TRUE; 03625 03626 oom: 03627 _dbus_string_free (&servicedir_path); 03628 return FALSE; 03629 } 03630 03631 03650 dbus_bool_t 03651 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03652 { 03653 const char *xdg_data_dirs; 03654 DBusString servicedir_path; 03655 03656 if (!_dbus_string_init (&servicedir_path)) 03657 return FALSE; 03658 03659 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03660 03661 if (xdg_data_dirs != NULL) 03662 { 03663 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03664 goto oom; 03665 03666 if (!_dbus_string_append (&servicedir_path, ":")) 03667 goto oom; 03668 } 03669 else 03670 { 03671 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03672 goto oom; 03673 } 03674 03675 /* 03676 * Add configured datadir to defaults. This may be the same as one 03677 * of the XDG directories. However, the config parser should take 03678 * care of the duplicates. 03679 * 03680 * Also, append /lib as counterpart of /usr/share on the root 03681 * directory (the root directory does not know /share), in order to 03682 * facilitate early boot system bus activation where /usr might not 03683 * be available. 03684 */ 03685 if (!_dbus_string_append (&servicedir_path, 03686 DBUS_DATADIR":" 03687 "/lib:")) 03688 goto oom; 03689 03690 if (!_dbus_split_paths_and_append (&servicedir_path, 03691 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03692 dirs)) 03693 goto oom; 03694 03695 _dbus_string_free (&servicedir_path); 03696 return TRUE; 03697 03698 oom: 03699 _dbus_string_free (&servicedir_path); 03700 return FALSE; 03701 } 03702 03711 dbus_bool_t 03712 _dbus_append_system_config_file (DBusString *str) 03713 { 03714 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03715 } 03716 03723 dbus_bool_t 03724 _dbus_append_session_config_file (DBusString *str) 03725 { 03726 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03727 } 03728 03736 void 03737 _dbus_flush_caches (void) 03738 { 03739 _dbus_user_database_flush_system (); 03740 } 03741 03755 dbus_bool_t 03756 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03757 DBusCredentials *credentials) 03758 { 03759 DBusString homedir; 03760 DBusString dotdir; 03761 dbus_uid_t uid; 03762 03763 _dbus_assert (credentials != NULL); 03764 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03765 03766 if (!_dbus_string_init (&homedir)) 03767 return FALSE; 03768 03769 uid = _dbus_credentials_get_unix_uid (credentials); 03770 _dbus_assert (uid != DBUS_UID_UNSET); 03771 03772 if (!_dbus_homedir_from_uid (uid, &homedir)) 03773 goto failed; 03774 03775 #ifdef DBUS_BUILD_TESTS 03776 { 03777 const char *override; 03778 03779 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03780 if (override != NULL && *override != '\0') 03781 { 03782 _dbus_string_set_length (&homedir, 0); 03783 if (!_dbus_string_append (&homedir, override)) 03784 goto failed; 03785 03786 _dbus_verbose ("Using fake homedir for testing: %s\n", 03787 _dbus_string_get_const_data (&homedir)); 03788 } 03789 else 03790 { 03791 static dbus_bool_t already_warned = FALSE; 03792 if (!already_warned) 03793 { 03794 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03795 already_warned = TRUE; 03796 } 03797 } 03798 } 03799 #endif 03800 03801 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03802 if (!_dbus_concat_dir_and_file (&homedir, 03803 &dotdir)) 03804 goto failed; 03805 03806 if (!_dbus_string_copy (&homedir, 0, 03807 directory, _dbus_string_get_length (directory))) { 03808 goto failed; 03809 } 03810 03811 _dbus_string_free (&homedir); 03812 return TRUE; 03813 03814 failed: 03815 _dbus_string_free (&homedir); 03816 return FALSE; 03817 } 03818 03819 //PENDING(kdab) docs 03820 dbus_bool_t 03821 _dbus_daemon_publish_session_bus_address (const char* addr, 03822 const char *scope) 03823 { 03824 return TRUE; 03825 } 03826 03827 //PENDING(kdab) docs 03828 void 03829 _dbus_daemon_unpublish_session_bus_address (void) 03830 { 03831 03832 } 03833 03840 dbus_bool_t 03841 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03842 { 03843 return errno == EAGAIN || errno == EWOULDBLOCK; 03844 } 03845 03853 dbus_bool_t 03854 _dbus_delete_directory (const DBusString *filename, 03855 DBusError *error) 03856 { 03857 const char *filename_c; 03858 03859 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03860 03861 filename_c = _dbus_string_get_const_data (filename); 03862 03863 if (rmdir (filename_c) != 0) 03864 { 03865 dbus_set_error (error, DBUS_ERROR_FAILED, 03866 "Failed to remove directory %s: %s\n", 03867 filename_c, _dbus_strerror (errno)); 03868 return FALSE; 03869 } 03870 03871 return TRUE; 03872 } 03873 03881 dbus_bool_t 03882 _dbus_socket_can_pass_unix_fd(int fd) { 03883 03884 #ifdef SCM_RIGHTS 03885 union { 03886 struct sockaddr sa; 03887 struct sockaddr_storage storage; 03888 struct sockaddr_un un; 03889 } sa_buf; 03890 03891 socklen_t sa_len = sizeof(sa_buf); 03892 03893 _DBUS_ZERO(sa_buf); 03894 03895 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03896 return FALSE; 03897 03898 return sa_buf.sa.sa_family == AF_UNIX; 03899 03900 #else 03901 return FALSE; 03902 03903 #endif 03904 } 03905 03906 03907 /* 03908 * replaces the term DBUS_PREFIX in configure_time_path by the 03909 * current dbus installation directory. On unix this function is a noop 03910 * 03911 * @param configure_time_path 03912 * @return real path 03913 */ 03914 const char * 03915 _dbus_replace_install_prefix (const char *configure_time_path) 03916 { 03917 return configure_time_path; 03918 } 03919 03929 dbus_bool_t 03930 _dbus_check_setuid (void) 03931 { 03932 /* TODO: get __libc_enable_secure exported from glibc. 03933 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1 03934 */ 03935 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE) 03936 { 03937 /* See glibc/include/unistd.h */ 03938 extern int __libc_enable_secure; 03939 return __libc_enable_secure; 03940 } 03941 #elif defined(HAVE_ISSETUGID) 03942 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */ 03943 return issetugid (); 03944 #else 03945 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ 03946 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ 03947 03948 static dbus_bool_t check_setuid_initialised; 03949 static dbus_bool_t is_setuid; 03950 03951 if (_DBUS_UNLIKELY (!check_setuid_initialised)) 03952 { 03953 #ifdef HAVE_GETRESUID 03954 if (getresuid (&ruid, &euid, &suid) != 0 || 03955 getresgid (&rgid, &egid, &sgid) != 0) 03956 #endif /* HAVE_GETRESUID */ 03957 { 03958 suid = ruid = getuid (); 03959 sgid = rgid = getgid (); 03960 euid = geteuid (); 03961 egid = getegid (); 03962 } 03963 03964 check_setuid_initialised = TRUE; 03965 is_setuid = (ruid != euid || ruid != suid || 03966 rgid != egid || rgid != sgid); 03967 03968 } 03969 return is_setuid; 03970 #endif 03971 } 03972 03973 /* tests in dbus-sysdeps-util.c */