D-Bus 1.4.1
|
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 #ifdef 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 #ifdef 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 #ifdef 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 fd = -1; 00830 00831 return -1; 00832 } 00833 00834 if (!_dbus_set_fd_nonblocking (fd, error)) 00835 { 00836 _DBUS_ASSERT_ERROR_IS_SET (error); 00837 00838 _dbus_close (fd, NULL); 00839 fd = -1; 00840 00841 return -1; 00842 } 00843 00844 return fd; 00845 } 00846 00856 static dbus_bool_t 00857 _dbus_set_local_creds (int fd, dbus_bool_t on) 00858 { 00859 dbus_bool_t retval = TRUE; 00860 00861 #if defined(HAVE_CMSGCRED) 00862 /* NOOP just to make sure only one codepath is used 00863 * and to prefer CMSGCRED 00864 */ 00865 #elif defined(LOCAL_CREDS) 00866 int val = on ? 1 : 0; 00867 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) 00868 { 00869 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); 00870 retval = FALSE; 00871 } 00872 else 00873 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", 00874 on ? "enabled" : "disabled", fd); 00875 #endif 00876 00877 return retval; 00878 } 00879 00897 int 00898 _dbus_listen_unix_socket (const char *path, 00899 dbus_bool_t abstract, 00900 DBusError *error) 00901 { 00902 int listen_fd; 00903 struct sockaddr_un addr; 00904 size_t path_len; 00905 unsigned int reuseaddr; 00906 00907 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00908 00909 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 00910 path, abstract); 00911 00912 if (!_dbus_open_unix_socket (&listen_fd, error)) 00913 { 00914 _DBUS_ASSERT_ERROR_IS_SET(error); 00915 return -1; 00916 } 00917 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00918 00919 _DBUS_ZERO (addr); 00920 addr.sun_family = AF_UNIX; 00921 path_len = strlen (path); 00922 00923 if (abstract) 00924 { 00925 #ifdef HAVE_ABSTRACT_SOCKETS 00926 /* remember that abstract names aren't nul-terminated so we rely 00927 * on sun_path being filled in with zeroes above. 00928 */ 00929 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00930 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00931 00932 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00933 { 00934 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00935 "Abstract socket name too long\n"); 00936 _dbus_close (listen_fd, NULL); 00937 return -1; 00938 } 00939 00940 strncpy (&addr.sun_path[1], path, path_len); 00941 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00942 #else /* HAVE_ABSTRACT_SOCKETS */ 00943 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00944 "Operating system does not support abstract socket namespace\n"); 00945 _dbus_close (listen_fd, NULL); 00946 return -1; 00947 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00948 } 00949 else 00950 { 00951 /* Discussed security implications of this with Nalin, 00952 * and we couldn't think of where it would kick our ass, but 00953 * it still seems a bit sucky. It also has non-security suckage; 00954 * really we'd prefer to exit if the socket is already in use. 00955 * But there doesn't seem to be a good way to do this. 00956 * 00957 * Just to be extra careful, I threw in the stat() - clearly 00958 * the stat() can't *fix* any security issue, but it at least 00959 * avoids inadvertent/accidental data loss. 00960 */ 00961 { 00962 struct stat sb; 00963 00964 if (stat (path, &sb) == 0 && 00965 S_ISSOCK (sb.st_mode)) 00966 unlink (path); 00967 } 00968 00969 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00970 { 00971 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00972 "Abstract socket name too long\n"); 00973 _dbus_close (listen_fd, NULL); 00974 return -1; 00975 } 00976 00977 strncpy (addr.sun_path, path, path_len); 00978 } 00979 00980 reuseaddr = 1; 00981 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 00982 { 00983 _dbus_warn ("Failed to set socket option\"%s\": %s", 00984 path, _dbus_strerror (errno)); 00985 } 00986 00987 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00988 { 00989 dbus_set_error (error, _dbus_error_from_errno (errno), 00990 "Failed to bind socket \"%s\": %s", 00991 path, _dbus_strerror (errno)); 00992 _dbus_close (listen_fd, NULL); 00993 return -1; 00994 } 00995 00996 if (listen (listen_fd, 30 /* backlog */) < 0) 00997 { 00998 dbus_set_error (error, _dbus_error_from_errno (errno), 00999 "Failed to listen on socket \"%s\": %s", 01000 path, _dbus_strerror (errno)); 01001 _dbus_close (listen_fd, NULL); 01002 return -1; 01003 } 01004 01005 if (!_dbus_set_local_creds (listen_fd, TRUE)) 01006 { 01007 dbus_set_error (error, _dbus_error_from_errno (errno), 01008 "Failed to enable LOCAL_CREDS on socket \"%s\": %s", 01009 path, _dbus_strerror (errno)); 01010 close (listen_fd); 01011 return -1; 01012 } 01013 01014 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01015 { 01016 _DBUS_ASSERT_ERROR_IS_SET (error); 01017 _dbus_close (listen_fd, NULL); 01018 return -1; 01019 } 01020 01021 /* Try opening up the permissions, but if we can't, just go ahead 01022 * and continue, maybe it will be good enough. 01023 */ 01024 if (!abstract && chmod (path, 0777) < 0) 01025 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01026 path); 01027 01028 return listen_fd; 01029 } 01030 01041 int 01042 _dbus_listen_systemd_sockets (int **fds, 01043 DBusError *error) 01044 { 01045 int r, n; 01046 unsigned fd; 01047 int *new_fds; 01048 01049 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01050 01051 n = sd_listen_fds (TRUE); 01052 if (n < 0) 01053 { 01054 dbus_set_error (error, _dbus_error_from_errno (-n), 01055 "Failed to acquire systemd socket: %s", 01056 _dbus_strerror (-n)); 01057 return -1; 01058 } 01059 01060 if (n <= 0) 01061 { 01062 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01063 "No socket received."); 01064 return -1; 01065 } 01066 01067 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01068 { 01069 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01070 if (r < 0) 01071 { 01072 dbus_set_error (error, _dbus_error_from_errno (-r), 01073 "Failed to verify systemd socket type: %s", 01074 _dbus_strerror (-r)); 01075 return -1; 01076 } 01077 01078 if (!r) 01079 { 01080 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01081 "Passed socket has wrong type."); 01082 return -1; 01083 } 01084 } 01085 01086 /* OK, the file descriptors are all good, so let's take posession of 01087 them then. */ 01088 01089 new_fds = dbus_new (int, n); 01090 if (!new_fds) 01091 { 01092 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01093 "Failed to allocate file handle array."); 01094 goto fail; 01095 } 01096 01097 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01098 { 01099 if (!_dbus_set_local_creds (fd, TRUE)) 01100 { 01101 dbus_set_error (error, _dbus_error_from_errno (errno), 01102 "Failed to enable LOCAL_CREDS on systemd socket: %s", 01103 _dbus_strerror (errno)); 01104 goto fail; 01105 } 01106 01107 if (!_dbus_set_fd_nonblocking (fd, error)) 01108 { 01109 _DBUS_ASSERT_ERROR_IS_SET (error); 01110 goto fail; 01111 } 01112 01113 new_fds[fd - SD_LISTEN_FDS_START] = fd; 01114 } 01115 01116 *fds = new_fds; 01117 return n; 01118 01119 fail: 01120 01121 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01122 { 01123 _dbus_close (fd, NULL); 01124 } 01125 01126 dbus_free (new_fds); 01127 return -1; 01128 } 01129 01143 int 01144 _dbus_connect_tcp_socket (const char *host, 01145 const char *port, 01146 const char *family, 01147 DBusError *error) 01148 { 01149 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01150 } 01151 01152 int 01153 _dbus_connect_tcp_socket_with_nonce (const char *host, 01154 const char *port, 01155 const char *family, 01156 const char *noncefile, 01157 DBusError *error) 01158 { 01159 int saved_errno = 0; 01160 int fd = -1, res; 01161 struct addrinfo hints; 01162 struct addrinfo *ai, *tmp; 01163 01164 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01165 01166 if (!_dbus_open_tcp_socket (&fd, error)) 01167 { 01168 _DBUS_ASSERT_ERROR_IS_SET(error); 01169 return -1; 01170 } 01171 01172 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01173 01174 _DBUS_ZERO (hints); 01175 01176 if (!family) 01177 hints.ai_family = AF_UNSPEC; 01178 else if (!strcmp(family, "ipv4")) 01179 hints.ai_family = AF_INET; 01180 else if (!strcmp(family, "ipv6")) 01181 hints.ai_family = AF_INET6; 01182 else 01183 { 01184 dbus_set_error (error, 01185 DBUS_ERROR_BAD_ADDRESS, 01186 "Unknown address family %s", family); 01187 return -1; 01188 } 01189 hints.ai_protocol = IPPROTO_TCP; 01190 hints.ai_socktype = SOCK_STREAM; 01191 hints.ai_flags = AI_ADDRCONFIG; 01192 01193 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01194 { 01195 dbus_set_error (error, 01196 _dbus_error_from_errno (errno), 01197 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01198 host, port, gai_strerror(res), res); 01199 _dbus_close (fd, NULL); 01200 return -1; 01201 } 01202 01203 tmp = ai; 01204 while (tmp) 01205 { 01206 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01207 { 01208 freeaddrinfo(ai); 01209 _DBUS_ASSERT_ERROR_IS_SET(error); 01210 return -1; 01211 } 01212 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01213 01214 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01215 { 01216 saved_errno = errno; 01217 _dbus_close(fd, NULL); 01218 fd = -1; 01219 tmp = tmp->ai_next; 01220 continue; 01221 } 01222 01223 break; 01224 } 01225 freeaddrinfo(ai); 01226 01227 if (fd == -1) 01228 { 01229 dbus_set_error (error, 01230 _dbus_error_from_errno (saved_errno), 01231 "Failed to connect to socket \"%s:%s\" %s", 01232 host, port, _dbus_strerror(saved_errno)); 01233 return -1; 01234 } 01235 01236 if (noncefile != NULL) 01237 { 01238 DBusString noncefileStr; 01239 dbus_bool_t ret; 01240 _dbus_string_init_const (&noncefileStr, noncefile); 01241 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01242 _dbus_string_free (&noncefileStr); 01243 01244 if (!ret) 01245 { 01246 _dbus_close (fd, NULL); 01247 return -1; 01248 } 01249 } 01250 01251 if (!_dbus_set_fd_nonblocking (fd, error)) 01252 { 01253 _dbus_close (fd, NULL); 01254 return -1; 01255 } 01256 01257 return fd; 01258 } 01259 01276 int 01277 _dbus_listen_tcp_socket (const char *host, 01278 const char *port, 01279 const char *family, 01280 DBusString *retport, 01281 int **fds_p, 01282 DBusError *error) 01283 { 01284 int saved_errno; 01285 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01286 struct addrinfo hints; 01287 struct addrinfo *ai, *tmp; 01288 unsigned int reuseaddr; 01289 01290 *fds_p = NULL; 01291 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01292 01293 _DBUS_ZERO (hints); 01294 01295 if (!family) 01296 hints.ai_family = AF_UNSPEC; 01297 else if (!strcmp(family, "ipv4")) 01298 hints.ai_family = AF_INET; 01299 else if (!strcmp(family, "ipv6")) 01300 hints.ai_family = AF_INET6; 01301 else 01302 { 01303 dbus_set_error (error, 01304 DBUS_ERROR_BAD_ADDRESS, 01305 "Unknown address family %s", family); 01306 return -1; 01307 } 01308 01309 hints.ai_protocol = IPPROTO_TCP; 01310 hints.ai_socktype = SOCK_STREAM; 01311 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01312 01313 redo_lookup_with_port: 01314 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01315 { 01316 dbus_set_error (error, 01317 _dbus_error_from_errno (errno), 01318 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01319 host ? host : "*", port, gai_strerror(res), res); 01320 return -1; 01321 } 01322 01323 tmp = ai; 01324 while (tmp) 01325 { 01326 int fd = -1, *newlisten_fd; 01327 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01328 { 01329 _DBUS_ASSERT_ERROR_IS_SET(error); 01330 goto failed; 01331 } 01332 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01333 01334 reuseaddr = 1; 01335 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01336 { 01337 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01338 host ? host : "*", port, _dbus_strerror (errno)); 01339 } 01340 01341 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01342 { 01343 saved_errno = errno; 01344 _dbus_close(fd, NULL); 01345 if (saved_errno == EADDRINUSE) 01346 { 01347 /* Depending on kernel policy, it may or may not 01348 be neccessary to bind to both IPv4 & 6 addresses 01349 so ignore EADDRINUSE here */ 01350 tmp = tmp->ai_next; 01351 continue; 01352 } 01353 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01354 "Failed to bind socket \"%s:%s\": %s", 01355 host ? host : "*", port, _dbus_strerror (saved_errno)); 01356 goto failed; 01357 } 01358 01359 if (listen (fd, 30 /* backlog */) < 0) 01360 { 01361 saved_errno = errno; 01362 _dbus_close (fd, NULL); 01363 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01364 "Failed to listen on socket \"%s:%s\": %s", 01365 host ? host : "*", port, _dbus_strerror (saved_errno)); 01366 goto failed; 01367 } 01368 01369 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01370 if (!newlisten_fd) 01371 { 01372 saved_errno = errno; 01373 _dbus_close (fd, NULL); 01374 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01375 "Failed to allocate file handle array: %s", 01376 _dbus_strerror (saved_errno)); 01377 goto failed; 01378 } 01379 listen_fd = newlisten_fd; 01380 listen_fd[nlisten_fd] = fd; 01381 nlisten_fd++; 01382 01383 if (!_dbus_string_get_length(retport)) 01384 { 01385 /* If the user didn't specify a port, or used 0, then 01386 the kernel chooses a port. After the first address 01387 is bound to, we need to force all remaining addresses 01388 to use the same port */ 01389 if (!port || !strcmp(port, "0")) 01390 { 01391 struct sockaddr_storage addr; 01392 socklen_t addrlen; 01393 char portbuf[50]; 01394 01395 addrlen = sizeof(addr); 01396 getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01397 01398 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0, 01399 portbuf, sizeof(portbuf), 01400 NI_NUMERICHOST)) != 0) 01401 { 01402 dbus_set_error (error, _dbus_error_from_errno (errno), 01403 "Failed to resolve port \"%s:%s\": %s (%s)", 01404 host ? host : "*", port, gai_strerror(res), res); 01405 goto failed; 01406 } 01407 if (!_dbus_string_append(retport, portbuf)) 01408 { 01409 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01410 goto failed; 01411 } 01412 01413 /* Release current address list & redo lookup */ 01414 port = _dbus_string_get_const_data(retport); 01415 freeaddrinfo(ai); 01416 goto redo_lookup_with_port; 01417 } 01418 else 01419 { 01420 if (!_dbus_string_append(retport, port)) 01421 { 01422 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01423 goto failed; 01424 } 01425 } 01426 } 01427 01428 tmp = tmp->ai_next; 01429 } 01430 freeaddrinfo(ai); 01431 ai = NULL; 01432 01433 if (!nlisten_fd) 01434 { 01435 errno = EADDRINUSE; 01436 dbus_set_error (error, _dbus_error_from_errno (errno), 01437 "Failed to bind socket \"%s:%s\": %s", 01438 host ? host : "*", port, _dbus_strerror (errno)); 01439 return -1; 01440 } 01441 01442 for (i = 0 ; i < nlisten_fd ; i++) 01443 { 01444 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01445 { 01446 goto failed; 01447 } 01448 } 01449 01450 *fds_p = listen_fd; 01451 01452 return nlisten_fd; 01453 01454 failed: 01455 if (ai) 01456 freeaddrinfo(ai); 01457 for (i = 0 ; i < nlisten_fd ; i++) 01458 _dbus_close(listen_fd[i], NULL); 01459 dbus_free(listen_fd); 01460 return -1; 01461 } 01462 01463 static dbus_bool_t 01464 write_credentials_byte (int server_fd, 01465 DBusError *error) 01466 { 01467 int bytes_written; 01468 char buf[1] = { '\0' }; 01469 #if defined(HAVE_CMSGCRED) 01470 union { 01471 struct cmsghdr hdr; 01472 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01473 } cmsg; 01474 struct iovec iov; 01475 struct msghdr msg; 01476 iov.iov_base = buf; 01477 iov.iov_len = 1; 01478 01479 _DBUS_ZERO(msg); 01480 msg.msg_iov = &iov; 01481 msg.msg_iovlen = 1; 01482 01483 msg.msg_control = (caddr_t) &cmsg; 01484 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01485 _DBUS_ZERO(cmsg); 01486 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01487 cmsg.hdr.cmsg_level = SOL_SOCKET; 01488 cmsg.hdr.cmsg_type = SCM_CREDS; 01489 #endif 01490 01491 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01492 01493 again: 01494 01495 #if defined(HAVE_CMSGCRED) 01496 bytes_written = sendmsg (server_fd, &msg, 0 01497 #ifdef HAVE_DECL_MSG_NOSIGNAL 01498 |MSG_NOSIGNAL 01499 #endif 01500 ); 01501 #else 01502 bytes_written = send (server_fd, buf, 1, 0 01503 #ifdef HAVE_DECL_MSG_NOSIGNAL 01504 |MSG_NOSIGNAL 01505 #endif 01506 ); 01507 #endif 01508 01509 if (bytes_written < 0 && errno == EINTR) 01510 goto again; 01511 01512 if (bytes_written < 0) 01513 { 01514 dbus_set_error (error, _dbus_error_from_errno (errno), 01515 "Failed to write credentials byte: %s", 01516 _dbus_strerror (errno)); 01517 return FALSE; 01518 } 01519 else if (bytes_written == 0) 01520 { 01521 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01522 "wrote zero bytes writing credentials byte"); 01523 return FALSE; 01524 } 01525 else 01526 { 01527 _dbus_assert (bytes_written == 1); 01528 _dbus_verbose ("wrote credentials byte\n"); 01529 return TRUE; 01530 } 01531 } 01532 01554 dbus_bool_t 01555 _dbus_read_credentials_socket (int client_fd, 01556 DBusCredentials *credentials, 01557 DBusError *error) 01558 { 01559 struct msghdr msg; 01560 struct iovec iov; 01561 char buf; 01562 dbus_uid_t uid_read; 01563 dbus_pid_t pid_read; 01564 int bytes_read; 01565 01566 #ifdef HAVE_CMSGCRED 01567 union { 01568 struct cmsghdr hdr; 01569 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01570 } cmsg; 01571 01572 #elif defined(LOCAL_CREDS) 01573 struct { 01574 struct cmsghdr hdr; 01575 struct sockcred cred; 01576 } cmsg; 01577 #endif 01578 01579 uid_read = DBUS_UID_UNSET; 01580 pid_read = DBUS_PID_UNSET; 01581 01582 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01583 01584 /* The POSIX spec certainly doesn't promise this, but 01585 * we need these assertions to fail as soon as we're wrong about 01586 * it so we can do the porting fixups 01587 */ 01588 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01589 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01590 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01591 01592 _dbus_credentials_clear (credentials); 01593 01594 /* Systems supporting LOCAL_CREDS are configured to have this feature 01595 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01596 * the connection. Therefore, the received message must carry the 01597 * credentials information without doing anything special. 01598 */ 01599 01600 iov.iov_base = &buf; 01601 iov.iov_len = 1; 01602 01603 _DBUS_ZERO(msg); 01604 msg.msg_iov = &iov; 01605 msg.msg_iovlen = 1; 01606 01607 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01608 _DBUS_ZERO(cmsg); 01609 msg.msg_control = (caddr_t) &cmsg; 01610 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01611 #endif 01612 01613 again: 01614 bytes_read = recvmsg (client_fd, &msg, 0); 01615 01616 if (bytes_read < 0) 01617 { 01618 if (errno == EINTR) 01619 goto again; 01620 01621 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01622 * normally only call read_credentials if the socket was ready 01623 * for reading 01624 */ 01625 01626 dbus_set_error (error, _dbus_error_from_errno (errno), 01627 "Failed to read credentials byte: %s", 01628 _dbus_strerror (errno)); 01629 return FALSE; 01630 } 01631 else if (bytes_read == 0) 01632 { 01633 /* this should not happen unless we are using recvmsg wrong, 01634 * so is essentially here for paranoia 01635 */ 01636 dbus_set_error (error, DBUS_ERROR_FAILED, 01637 "Failed to read credentials byte (zero-length read)"); 01638 return FALSE; 01639 } 01640 else if (buf != '\0') 01641 { 01642 dbus_set_error (error, DBUS_ERROR_FAILED, 01643 "Credentials byte was not nul"); 01644 return FALSE; 01645 } 01646 01647 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01648 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01649 || cmsg.hdr.cmsg_type != SCM_CREDS) 01650 { 01651 dbus_set_error (error, DBUS_ERROR_FAILED, 01652 "Message from recvmsg() was not SCM_CREDS"); 01653 return FALSE; 01654 } 01655 #endif 01656 01657 _dbus_verbose ("read credentials byte\n"); 01658 01659 { 01660 #ifdef SO_PEERCRED 01661 struct ucred cr; 01662 int cr_len = sizeof (cr); 01663 01664 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01665 cr_len == sizeof (cr)) 01666 { 01667 pid_read = cr.pid; 01668 uid_read = cr.uid; 01669 } 01670 else 01671 { 01672 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01673 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01674 } 01675 #elif defined(HAVE_CMSGCRED) 01676 struct cmsgcred *cred; 01677 01678 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01679 pid_read = cred->cmcred_pid; 01680 uid_read = cred->cmcred_euid; 01681 #elif defined(LOCAL_CREDS) 01682 pid_read = DBUS_PID_UNSET; 01683 uid_read = cmsg.cred.sc_uid; 01684 /* Since we have already got the credentials from this socket, we can 01685 * disable its LOCAL_CREDS flag if it was ever set. */ 01686 _dbus_set_local_creds (client_fd, FALSE); 01687 #elif defined(HAVE_GETPEEREID) 01688 uid_t euid; 01689 gid_t egid; 01690 if (getpeereid (client_fd, &euid, &egid) == 0) 01691 { 01692 uid_read = euid; 01693 } 01694 else 01695 { 01696 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01697 } 01698 #elif defined(HAVE_GETPEERUCRED) 01699 ucred_t * ucred = NULL; 01700 if (getpeerucred (client_fd, &ucred) == 0) 01701 { 01702 pid_read = ucred_getpid (ucred); 01703 uid_read = ucred_geteuid (ucred); 01704 #ifdef HAVE_ADT 01705 /* generate audit session data based on socket ucred */ 01706 adt_session_data_t *adth = NULL; 01707 adt_export_data_t *data = NULL; 01708 size_t size = 0; 01709 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01710 { 01711 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01712 } 01713 else 01714 { 01715 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01716 { 01717 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01718 } 01719 else 01720 { 01721 size = adt_export_session_data (adth, &data); 01722 if (size <= 0) 01723 { 01724 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01725 } 01726 else 01727 { 01728 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01729 free (data); 01730 } 01731 } 01732 (void) adt_end_session (adth); 01733 } 01734 #endif /* HAVE_ADT */ 01735 } 01736 else 01737 { 01738 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01739 } 01740 if (ucred != NULL) 01741 ucred_free (ucred); 01742 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01743 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01744 #endif 01745 } 01746 01747 _dbus_verbose ("Credentials:" 01748 " pid "DBUS_PID_FORMAT 01749 " uid "DBUS_UID_FORMAT 01750 "\n", 01751 pid_read, 01752 uid_read); 01753 01754 if (pid_read != DBUS_PID_UNSET) 01755 { 01756 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01757 { 01758 _DBUS_SET_OOM (error); 01759 return FALSE; 01760 } 01761 } 01762 01763 if (uid_read != DBUS_UID_UNSET) 01764 { 01765 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01766 { 01767 _DBUS_SET_OOM (error); 01768 return FALSE; 01769 } 01770 } 01771 01772 return TRUE; 01773 } 01774 01792 dbus_bool_t 01793 _dbus_send_credentials_socket (int server_fd, 01794 DBusError *error) 01795 { 01796 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01797 01798 if (write_credentials_byte (server_fd, error)) 01799 return TRUE; 01800 else 01801 return FALSE; 01802 } 01803 01813 int 01814 _dbus_accept (int listen_fd) 01815 { 01816 int client_fd; 01817 struct sockaddr addr; 01818 socklen_t addrlen; 01819 #ifdef HAVE_ACCEPT4 01820 dbus_bool_t cloexec_done; 01821 #endif 01822 01823 addrlen = sizeof (addr); 01824 01825 retry: 01826 01827 #ifdef HAVE_ACCEPT4 01828 /* We assume that if accept4 is available SOCK_CLOEXEC is too */ 01829 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01830 cloexec_done = client_fd >= 0; 01831 01832 if (client_fd < 0 && errno == ENOSYS) 01833 #endif 01834 { 01835 client_fd = accept (listen_fd, &addr, &addrlen); 01836 } 01837 01838 if (client_fd < 0) 01839 { 01840 if (errno == EINTR) 01841 goto retry; 01842 } 01843 01844 _dbus_verbose ("client fd %d accepted\n", client_fd); 01845 01846 #ifdef HAVE_ACCEPT4 01847 if (!cloexec_done) 01848 #endif 01849 { 01850 _dbus_fd_set_close_on_exec(client_fd); 01851 } 01852 01853 return client_fd; 01854 } 01855 01864 dbus_bool_t 01865 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01866 { 01867 const char *directory; 01868 struct stat sb; 01869 01870 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01871 01872 directory = _dbus_string_get_const_data (dir); 01873 01874 if (stat (directory, &sb) < 0) 01875 { 01876 dbus_set_error (error, _dbus_error_from_errno (errno), 01877 "%s", _dbus_strerror (errno)); 01878 01879 return FALSE; 01880 } 01881 01882 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01883 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01884 { 01885 dbus_set_error (error, DBUS_ERROR_FAILED, 01886 "%s directory is not private to the user", directory); 01887 return FALSE; 01888 } 01889 01890 return TRUE; 01891 } 01892 01893 static dbus_bool_t 01894 fill_user_info_from_passwd (struct passwd *p, 01895 DBusUserInfo *info, 01896 DBusError *error) 01897 { 01898 _dbus_assert (p->pw_name != NULL); 01899 _dbus_assert (p->pw_dir != NULL); 01900 01901 info->uid = p->pw_uid; 01902 info->primary_gid = p->pw_gid; 01903 info->username = _dbus_strdup (p->pw_name); 01904 info->homedir = _dbus_strdup (p->pw_dir); 01905 01906 if (info->username == NULL || 01907 info->homedir == NULL) 01908 { 01909 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01910 return FALSE; 01911 } 01912 01913 return TRUE; 01914 } 01915 01916 static dbus_bool_t 01917 fill_user_info (DBusUserInfo *info, 01918 dbus_uid_t uid, 01919 const DBusString *username, 01920 DBusError *error) 01921 { 01922 const char *username_c; 01923 01924 /* exactly one of username/uid provided */ 01925 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 01926 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 01927 01928 info->uid = DBUS_UID_UNSET; 01929 info->primary_gid = DBUS_GID_UNSET; 01930 info->group_ids = NULL; 01931 info->n_group_ids = 0; 01932 info->username = NULL; 01933 info->homedir = NULL; 01934 01935 if (username != NULL) 01936 username_c = _dbus_string_get_const_data (username); 01937 else 01938 username_c = NULL; 01939 01940 /* For now assuming that the getpwnam() and getpwuid() flavors 01941 * are always symmetrical, if not we have to add more configure 01942 * checks 01943 */ 01944 01945 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 01946 { 01947 struct passwd *p; 01948 int result; 01949 size_t buflen; 01950 char *buf; 01951 struct passwd p_str; 01952 01953 /* retrieve maximum needed size for buf */ 01954 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 01955 01956 /* sysconf actually returns a long, but everything else expects size_t, 01957 * so just recast here. 01958 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 01959 */ 01960 if ((long) buflen <= 0) 01961 buflen = 1024; 01962 01963 result = -1; 01964 while (1) 01965 { 01966 buf = dbus_malloc (buflen); 01967 if (buf == NULL) 01968 { 01969 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01970 return FALSE; 01971 } 01972 01973 p = NULL; 01974 #ifdef HAVE_POSIX_GETPWNAM_R 01975 if (uid != DBUS_UID_UNSET) 01976 result = getpwuid_r (uid, &p_str, buf, buflen, 01977 &p); 01978 else 01979 result = getpwnam_r (username_c, &p_str, buf, buflen, 01980 &p); 01981 #else 01982 if (uid != DBUS_UID_UNSET) 01983 p = getpwuid_r (uid, &p_str, buf, buflen); 01984 else 01985 p = getpwnam_r (username_c, &p_str, buf, buflen); 01986 result = 0; 01987 #endif /* !HAVE_POSIX_GETPWNAM_R */ 01988 //Try a bigger buffer if ERANGE was returned 01989 if (result == ERANGE && buflen < 512 * 1024) 01990 { 01991 dbus_free (buf); 01992 buflen *= 2; 01993 } 01994 else 01995 { 01996 break; 01997 } 01998 } 01999 if (result == 0 && p == &p_str) 02000 { 02001 if (!fill_user_info_from_passwd (p, info, error)) 02002 { 02003 dbus_free (buf); 02004 return FALSE; 02005 } 02006 dbus_free (buf); 02007 } 02008 else 02009 { 02010 dbus_set_error (error, _dbus_error_from_errno (errno), 02011 "User \"%s\" unknown or no memory to allocate password entry\n", 02012 username_c ? username_c : "???"); 02013 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02014 dbus_free (buf); 02015 return FALSE; 02016 } 02017 } 02018 #else /* ! HAVE_GETPWNAM_R */ 02019 { 02020 /* I guess we're screwed on thread safety here */ 02021 struct passwd *p; 02022 02023 if (uid != DBUS_UID_UNSET) 02024 p = getpwuid (uid); 02025 else 02026 p = getpwnam (username_c); 02027 02028 if (p != NULL) 02029 { 02030 if (!fill_user_info_from_passwd (p, info, error)) 02031 { 02032 return FALSE; 02033 } 02034 } 02035 else 02036 { 02037 dbus_set_error (error, _dbus_error_from_errno (errno), 02038 "User \"%s\" unknown or no memory to allocate password entry\n", 02039 username_c ? username_c : "???"); 02040 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02041 return FALSE; 02042 } 02043 } 02044 #endif /* ! HAVE_GETPWNAM_R */ 02045 02046 /* Fill this in so we can use it to get groups */ 02047 username_c = info->username; 02048 02049 #ifdef HAVE_GETGROUPLIST 02050 { 02051 gid_t *buf; 02052 int buf_count; 02053 int i; 02054 int initial_buf_count; 02055 02056 initial_buf_count = 17; 02057 buf_count = initial_buf_count; 02058 buf = dbus_new (gid_t, buf_count); 02059 if (buf == NULL) 02060 { 02061 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02062 goto failed; 02063 } 02064 02065 if (getgrouplist (username_c, 02066 info->primary_gid, 02067 buf, &buf_count) < 0) 02068 { 02069 gid_t *new; 02070 /* Presumed cause of negative return code: buf has insufficient 02071 entries to hold the entire group list. The Linux behavior in this 02072 case is to pass back the actual number of groups in buf_count, but 02073 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02074 So as a hack, try to help out a bit by guessing a larger 02075 number of groups, within reason.. might still fail, of course, 02076 but we can at least print a more informative message. I looked up 02077 the "right way" to do this by downloading Apple's own source code 02078 for the "id" command, and it turns out that they use an 02079 undocumented library function getgrouplist_2 (!) which is not 02080 declared in any header in /usr/include (!!). That did not seem 02081 like the way to go here. 02082 */ 02083 if (buf_count == initial_buf_count) 02084 { 02085 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02086 } 02087 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02088 if (new == NULL) 02089 { 02090 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02091 dbus_free (buf); 02092 goto failed; 02093 } 02094 02095 buf = new; 02096 02097 errno = 0; 02098 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02099 { 02100 if (errno == 0) 02101 { 02102 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02103 username_c, buf_count, buf_count); 02104 } 02105 else 02106 { 02107 dbus_set_error (error, 02108 _dbus_error_from_errno (errno), 02109 "Failed to get groups for username \"%s\" primary GID " 02110 DBUS_GID_FORMAT ": %s\n", 02111 username_c, info->primary_gid, 02112 _dbus_strerror (errno)); 02113 dbus_free (buf); 02114 goto failed; 02115 } 02116 } 02117 } 02118 02119 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02120 if (info->group_ids == NULL) 02121 { 02122 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02123 dbus_free (buf); 02124 goto failed; 02125 } 02126 02127 for (i = 0; i < buf_count; ++i) 02128 info->group_ids[i] = buf[i]; 02129 02130 info->n_group_ids = buf_count; 02131 02132 dbus_free (buf); 02133 } 02134 #else /* HAVE_GETGROUPLIST */ 02135 { 02136 /* We just get the one group ID */ 02137 info->group_ids = dbus_new (dbus_gid_t, 1); 02138 if (info->group_ids == NULL) 02139 { 02140 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02141 goto failed; 02142 } 02143 02144 info->n_group_ids = 1; 02145 02146 (info->group_ids)[0] = info->primary_gid; 02147 } 02148 #endif /* HAVE_GETGROUPLIST */ 02149 02150 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02151 02152 return TRUE; 02153 02154 failed: 02155 _DBUS_ASSERT_ERROR_IS_SET (error); 02156 return FALSE; 02157 } 02158 02167 dbus_bool_t 02168 _dbus_user_info_fill (DBusUserInfo *info, 02169 const DBusString *username, 02170 DBusError *error) 02171 { 02172 return fill_user_info (info, DBUS_UID_UNSET, 02173 username, error); 02174 } 02175 02184 dbus_bool_t 02185 _dbus_user_info_fill_uid (DBusUserInfo *info, 02186 dbus_uid_t uid, 02187 DBusError *error) 02188 { 02189 return fill_user_info (info, uid, 02190 NULL, error); 02191 } 02192 02200 dbus_bool_t 02201 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02202 { 02203 /* The POSIX spec certainly doesn't promise this, but 02204 * we need these assertions to fail as soon as we're wrong about 02205 * it so we can do the porting fixups 02206 */ 02207 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02208 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02209 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02210 02211 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 02212 return FALSE; 02213 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02214 return FALSE; 02215 02216 return TRUE; 02217 } 02218 02230 dbus_bool_t 02231 _dbus_append_user_from_current_process (DBusString *str) 02232 { 02233 return _dbus_string_append_uint (str, 02234 _dbus_geteuid ()); 02235 } 02236 02241 dbus_pid_t 02242 _dbus_getpid (void) 02243 { 02244 return getpid (); 02245 } 02246 02250 dbus_uid_t 02251 _dbus_getuid (void) 02252 { 02253 return getuid (); 02254 } 02255 02259 dbus_uid_t 02260 _dbus_geteuid (void) 02261 { 02262 return geteuid (); 02263 } 02264 02271 unsigned long 02272 _dbus_pid_for_log (void) 02273 { 02274 return getpid (); 02275 } 02276 02284 dbus_bool_t 02285 _dbus_parse_uid (const DBusString *uid_str, 02286 dbus_uid_t *uid) 02287 { 02288 int end; 02289 long val; 02290 02291 if (_dbus_string_get_length (uid_str) == 0) 02292 { 02293 _dbus_verbose ("UID string was zero length\n"); 02294 return FALSE; 02295 } 02296 02297 val = -1; 02298 end = 0; 02299 if (!_dbus_string_parse_int (uid_str, 0, &val, 02300 &end)) 02301 { 02302 _dbus_verbose ("could not parse string as a UID\n"); 02303 return FALSE; 02304 } 02305 02306 if (end != _dbus_string_get_length (uid_str)) 02307 { 02308 _dbus_verbose ("string contained trailing stuff after UID\n"); 02309 return FALSE; 02310 } 02311 02312 *uid = val; 02313 02314 return TRUE; 02315 } 02316 02317 #if !DBUS_USE_SYNC 02318 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02319 #endif 02320 02327 dbus_int32_t 02328 _dbus_atomic_inc (DBusAtomic *atomic) 02329 { 02330 #if DBUS_USE_SYNC 02331 return __sync_add_and_fetch(&atomic->value, 1)-1; 02332 #else 02333 dbus_int32_t res; 02334 _DBUS_LOCK (atomic); 02335 res = atomic->value; 02336 atomic->value += 1; 02337 _DBUS_UNLOCK (atomic); 02338 return res; 02339 #endif 02340 } 02341 02348 dbus_int32_t 02349 _dbus_atomic_dec (DBusAtomic *atomic) 02350 { 02351 #if DBUS_USE_SYNC 02352 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02353 #else 02354 dbus_int32_t res; 02355 02356 _DBUS_LOCK (atomic); 02357 res = atomic->value; 02358 atomic->value -= 1; 02359 _DBUS_UNLOCK (atomic); 02360 return res; 02361 #endif 02362 } 02363 02364 #ifdef DBUS_BUILD_TESTS 02365 02368 dbus_gid_t 02369 _dbus_getgid (void) 02370 { 02371 return getgid (); 02372 } 02373 #endif 02374 02383 int 02384 _dbus_poll (DBusPollFD *fds, 02385 int n_fds, 02386 int timeout_milliseconds) 02387 { 02388 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02389 /* This big thing is a constant expression and should get optimized 02390 * out of existence. So it's more robust than a configure check at 02391 * no cost. 02392 */ 02393 if (_DBUS_POLLIN == POLLIN && 02394 _DBUS_POLLPRI == POLLPRI && 02395 _DBUS_POLLOUT == POLLOUT && 02396 _DBUS_POLLERR == POLLERR && 02397 _DBUS_POLLHUP == POLLHUP && 02398 _DBUS_POLLNVAL == POLLNVAL && 02399 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02400 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02401 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02402 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02403 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02404 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02405 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02406 { 02407 return poll ((struct pollfd*) fds, 02408 n_fds, 02409 timeout_milliseconds); 02410 } 02411 else 02412 { 02413 /* We have to convert the DBusPollFD to an array of 02414 * struct pollfd, poll, and convert back. 02415 */ 02416 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02417 return -1; 02418 } 02419 #else /* ! HAVE_POLL */ 02420 02421 fd_set read_set, write_set, err_set; 02422 int max_fd = 0; 02423 int i; 02424 struct timeval tv; 02425 int ready; 02426 02427 FD_ZERO (&read_set); 02428 FD_ZERO (&write_set); 02429 FD_ZERO (&err_set); 02430 02431 for (i = 0; i < n_fds; i++) 02432 { 02433 DBusPollFD *fdp = &fds[i]; 02434 02435 if (fdp->events & _DBUS_POLLIN) 02436 FD_SET (fdp->fd, &read_set); 02437 02438 if (fdp->events & _DBUS_POLLOUT) 02439 FD_SET (fdp->fd, &write_set); 02440 02441 FD_SET (fdp->fd, &err_set); 02442 02443 max_fd = MAX (max_fd, fdp->fd); 02444 } 02445 02446 tv.tv_sec = timeout_milliseconds / 1000; 02447 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02448 02449 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02450 timeout_milliseconds < 0 ? NULL : &tv); 02451 02452 if (ready > 0) 02453 { 02454 for (i = 0; i < n_fds; i++) 02455 { 02456 DBusPollFD *fdp = &fds[i]; 02457 02458 fdp->revents = 0; 02459 02460 if (FD_ISSET (fdp->fd, &read_set)) 02461 fdp->revents |= _DBUS_POLLIN; 02462 02463 if (FD_ISSET (fdp->fd, &write_set)) 02464 fdp->revents |= _DBUS_POLLOUT; 02465 02466 if (FD_ISSET (fdp->fd, &err_set)) 02467 fdp->revents |= _DBUS_POLLERR; 02468 } 02469 } 02470 02471 return ready; 02472 #endif 02473 } 02474 02482 void 02483 _dbus_get_current_time (long *tv_sec, 02484 long *tv_usec) 02485 { 02486 struct timeval t; 02487 02488 #ifdef HAVE_MONOTONIC_CLOCK 02489 struct timespec ts; 02490 clock_gettime (CLOCK_MONOTONIC, &ts); 02491 02492 if (tv_sec) 02493 *tv_sec = ts.tv_sec; 02494 if (tv_usec) 02495 *tv_usec = ts.tv_nsec / 1000; 02496 #else 02497 gettimeofday (&t, NULL); 02498 02499 if (tv_sec) 02500 *tv_sec = t.tv_sec; 02501 if (tv_usec) 02502 *tv_usec = t.tv_usec; 02503 #endif 02504 } 02505 02514 dbus_bool_t 02515 _dbus_create_directory (const DBusString *filename, 02516 DBusError *error) 02517 { 02518 const char *filename_c; 02519 02520 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02521 02522 filename_c = _dbus_string_get_const_data (filename); 02523 02524 if (mkdir (filename_c, 0700) < 0) 02525 { 02526 if (errno == EEXIST) 02527 return TRUE; 02528 02529 dbus_set_error (error, DBUS_ERROR_FAILED, 02530 "Failed to create directory %s: %s\n", 02531 filename_c, _dbus_strerror (errno)); 02532 return FALSE; 02533 } 02534 else 02535 return TRUE; 02536 } 02537 02548 dbus_bool_t 02549 _dbus_concat_dir_and_file (DBusString *dir, 02550 const DBusString *next_component) 02551 { 02552 dbus_bool_t dir_ends_in_slash; 02553 dbus_bool_t file_starts_with_slash; 02554 02555 if (_dbus_string_get_length (dir) == 0 || 02556 _dbus_string_get_length (next_component) == 0) 02557 return TRUE; 02558 02559 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02560 _dbus_string_get_length (dir) - 1); 02561 02562 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02563 02564 if (dir_ends_in_slash && file_starts_with_slash) 02565 { 02566 _dbus_string_shorten (dir, 1); 02567 } 02568 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02569 { 02570 if (!_dbus_string_append_byte (dir, '/')) 02571 return FALSE; 02572 } 02573 02574 return _dbus_string_copy (next_component, 0, dir, 02575 _dbus_string_get_length (dir)); 02576 } 02577 02579 #define NANOSECONDS_PER_SECOND 1000000000 02580 02581 #define MICROSECONDS_PER_SECOND 1000000 02582 02583 #define MILLISECONDS_PER_SECOND 1000 02584 02585 #define NANOSECONDS_PER_MILLISECOND 1000000 02586 02587 #define MICROSECONDS_PER_MILLISECOND 1000 02588 02593 void 02594 _dbus_sleep_milliseconds (int milliseconds) 02595 { 02596 #ifdef HAVE_NANOSLEEP 02597 struct timespec req; 02598 struct timespec rem; 02599 02600 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02601 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02602 rem.tv_sec = 0; 02603 rem.tv_nsec = 0; 02604 02605 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02606 req = rem; 02607 #elif defined (HAVE_USLEEP) 02608 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02609 #else /* ! HAVE_USLEEP */ 02610 sleep (MAX (milliseconds / 1000, 1)); 02611 #endif 02612 } 02613 02614 static dbus_bool_t 02615 _dbus_generate_pseudorandom_bytes (DBusString *str, 02616 int n_bytes) 02617 { 02618 int old_len; 02619 char *p; 02620 02621 old_len = _dbus_string_get_length (str); 02622 02623 if (!_dbus_string_lengthen (str, n_bytes)) 02624 return FALSE; 02625 02626 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02627 02628 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02629 02630 return TRUE; 02631 } 02632 02641 dbus_bool_t 02642 _dbus_generate_random_bytes (DBusString *str, 02643 int n_bytes) 02644 { 02645 int old_len; 02646 int fd; 02647 02648 /* FALSE return means "no memory", if it could 02649 * mean something else then we'd need to return 02650 * a DBusError. So we always fall back to pseudorandom 02651 * if the I/O fails. 02652 */ 02653 02654 old_len = _dbus_string_get_length (str); 02655 fd = -1; 02656 02657 /* note, urandom on linux will fall back to pseudorandom */ 02658 fd = open ("/dev/urandom", O_RDONLY); 02659 if (fd < 0) 02660 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02661 02662 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02663 02664 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02665 { 02666 _dbus_close (fd, NULL); 02667 _dbus_string_set_length (str, old_len); 02668 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02669 } 02670 02671 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02672 n_bytes); 02673 02674 _dbus_close (fd, NULL); 02675 02676 return TRUE; 02677 } 02678 02684 void 02685 _dbus_exit (int code) 02686 { 02687 _exit (code); 02688 } 02689 02698 const char* 02699 _dbus_strerror (int error_number) 02700 { 02701 const char *msg; 02702 02703 msg = strerror (error_number); 02704 if (msg == NULL) 02705 msg = "unknown"; 02706 02707 return msg; 02708 } 02709 02713 void 02714 _dbus_disable_sigpipe (void) 02715 { 02716 signal (SIGPIPE, SIG_IGN); 02717 } 02718 02726 void 02727 _dbus_fd_set_close_on_exec (intptr_t fd) 02728 { 02729 int val; 02730 02731 val = fcntl (fd, F_GETFD, 0); 02732 02733 if (val < 0) 02734 return; 02735 02736 val |= FD_CLOEXEC; 02737 02738 fcntl (fd, F_SETFD, val); 02739 } 02740 02748 dbus_bool_t 02749 _dbus_close (int fd, 02750 DBusError *error) 02751 { 02752 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02753 02754 again: 02755 if (close (fd) < 0) 02756 { 02757 if (errno == EINTR) 02758 goto again; 02759 02760 dbus_set_error (error, _dbus_error_from_errno (errno), 02761 "Could not close fd %d", fd); 02762 return FALSE; 02763 } 02764 02765 return TRUE; 02766 } 02767 02775 int 02776 _dbus_dup(int fd, 02777 DBusError *error) 02778 { 02779 int new_fd; 02780 02781 #ifdef F_DUPFD_CLOEXEC 02782 dbus_bool_t cloexec_done; 02783 02784 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02785 cloexec_done = new_fd >= 0; 02786 02787 if (new_fd < 0 && errno == EINVAL) 02788 #endif 02789 { 02790 new_fd = fcntl(fd, F_DUPFD, 3); 02791 } 02792 02793 if (new_fd < 0) { 02794 02795 dbus_set_error (error, _dbus_error_from_errno (errno), 02796 "Could not duplicate fd %d", fd); 02797 return -1; 02798 } 02799 02800 #ifdef F_DUPFD_CLOEXEC 02801 if (!cloexec_done) 02802 #endif 02803 { 02804 _dbus_fd_set_close_on_exec(new_fd); 02805 } 02806 02807 return new_fd; 02808 } 02809 02817 dbus_bool_t 02818 _dbus_set_fd_nonblocking (int fd, 02819 DBusError *error) 02820 { 02821 int val; 02822 02823 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02824 02825 val = fcntl (fd, F_GETFL, 0); 02826 if (val < 0) 02827 { 02828 dbus_set_error (error, _dbus_error_from_errno (errno), 02829 "Failed to get flags from file descriptor %d: %s", 02830 fd, _dbus_strerror (errno)); 02831 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02832 _dbus_strerror (errno)); 02833 return FALSE; 02834 } 02835 02836 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02837 { 02838 dbus_set_error (error, _dbus_error_from_errno (errno), 02839 "Failed to set nonblocking flag of file descriptor %d: %s", 02840 fd, _dbus_strerror (errno)); 02841 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02842 fd, _dbus_strerror (errno)); 02843 02844 return FALSE; 02845 } 02846 02847 return TRUE; 02848 } 02849 02855 void 02856 _dbus_print_backtrace (void) 02857 { 02858 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02859 void *bt[500]; 02860 int bt_size; 02861 int i; 02862 char **syms; 02863 02864 bt_size = backtrace (bt, 500); 02865 02866 syms = backtrace_symbols (bt, bt_size); 02867 02868 i = 0; 02869 while (i < bt_size) 02870 { 02871 /* don't use dbus_warn since it can _dbus_abort() */ 02872 fprintf (stderr, " %s\n", syms[i]); 02873 ++i; 02874 } 02875 fflush (stderr); 02876 02877 free (syms); 02878 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02879 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02880 #else 02881 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02882 #endif 02883 } 02884 02902 dbus_bool_t 02903 _dbus_full_duplex_pipe (int *fd1, 02904 int *fd2, 02905 dbus_bool_t blocking, 02906 DBusError *error) 02907 { 02908 #ifdef HAVE_SOCKETPAIR 02909 int fds[2]; 02910 int retval; 02911 02912 #ifdef SOCK_CLOEXEC 02913 dbus_bool_t cloexec_done; 02914 02915 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 02916 cloexec_done = retval >= 0; 02917 02918 if (retval < 0 && errno == EINVAL) 02919 #endif 02920 { 02921 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 02922 } 02923 02924 if (retval < 0) 02925 { 02926 dbus_set_error (error, _dbus_error_from_errno (errno), 02927 "Could not create full-duplex pipe"); 02928 return FALSE; 02929 } 02930 02931 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02932 02933 #ifdef SOCK_CLOEXEC 02934 if (!cloexec_done) 02935 #endif 02936 { 02937 _dbus_fd_set_close_on_exec (fds[0]); 02938 _dbus_fd_set_close_on_exec (fds[1]); 02939 } 02940 02941 if (!blocking && 02942 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02943 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02944 { 02945 dbus_set_error (error, _dbus_error_from_errno (errno), 02946 "Could not set full-duplex pipe nonblocking"); 02947 02948 _dbus_close (fds[0], NULL); 02949 _dbus_close (fds[1], NULL); 02950 02951 return FALSE; 02952 } 02953 02954 *fd1 = fds[0]; 02955 *fd2 = fds[1]; 02956 02957 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 02958 *fd1, *fd2); 02959 02960 return TRUE; 02961 #else 02962 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 02963 dbus_set_error (error, DBUS_ERROR_FAILED, 02964 "_dbus_full_duplex_pipe() not implemented on this OS"); 02965 return FALSE; 02966 #endif 02967 } 02968 02977 int 02978 _dbus_printf_string_upper_bound (const char *format, 02979 va_list args) 02980 { 02981 char c; 02982 return vsnprintf (&c, 1, format, args); 02983 } 02984 02991 const char* 02992 _dbus_get_tmpdir(void) 02993 { 02994 static const char* tmpdir = NULL; 02995 02996 if (tmpdir == NULL) 02997 { 02998 /* TMPDIR is what glibc uses, then 02999 * glibc falls back to the P_tmpdir macro which 03000 * just expands to "/tmp" 03001 */ 03002 if (tmpdir == NULL) 03003 tmpdir = getenv("TMPDIR"); 03004 03005 /* These two env variables are probably 03006 * broken, but maybe some OS uses them? 03007 */ 03008 if (tmpdir == NULL) 03009 tmpdir = getenv("TMP"); 03010 if (tmpdir == NULL) 03011 tmpdir = getenv("TEMP"); 03012 03013 /* And this is the sane fallback. */ 03014 if (tmpdir == NULL) 03015 tmpdir = "/tmp"; 03016 } 03017 03018 _dbus_assert(tmpdir != NULL); 03019 03020 return tmpdir; 03021 } 03022 03042 static dbus_bool_t 03043 _read_subprocess_line_argv (const char *progpath, 03044 dbus_bool_t path_fallback, 03045 char * const *argv, 03046 DBusString *result, 03047 DBusError *error) 03048 { 03049 int result_pipe[2] = { -1, -1 }; 03050 int errors_pipe[2] = { -1, -1 }; 03051 pid_t pid; 03052 int ret; 03053 int status; 03054 int orig_len; 03055 int i; 03056 03057 dbus_bool_t retval; 03058 sigset_t new_set, old_set; 03059 03060 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03061 retval = FALSE; 03062 03063 /* We need to block any existing handlers for SIGCHLD temporarily; they 03064 * will cause waitpid() below to fail. 03065 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03066 */ 03067 sigemptyset (&new_set); 03068 sigaddset (&new_set, SIGCHLD); 03069 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03070 03071 orig_len = _dbus_string_get_length (result); 03072 03073 #define READ_END 0 03074 #define WRITE_END 1 03075 if (pipe (result_pipe) < 0) 03076 { 03077 dbus_set_error (error, _dbus_error_from_errno (errno), 03078 "Failed to create a pipe to call %s: %s", 03079 progpath, _dbus_strerror (errno)); 03080 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03081 progpath, _dbus_strerror (errno)); 03082 goto out; 03083 } 03084 if (pipe (errors_pipe) < 0) 03085 { 03086 dbus_set_error (error, _dbus_error_from_errno (errno), 03087 "Failed to create a pipe to call %s: %s", 03088 progpath, _dbus_strerror (errno)); 03089 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03090 progpath, _dbus_strerror (errno)); 03091 goto out; 03092 } 03093 03094 pid = fork (); 03095 if (pid < 0) 03096 { 03097 dbus_set_error (error, _dbus_error_from_errno (errno), 03098 "Failed to fork() to call %s: %s", 03099 progpath, _dbus_strerror (errno)); 03100 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03101 progpath, _dbus_strerror (errno)); 03102 goto out; 03103 } 03104 03105 if (pid == 0) 03106 { 03107 /* child process */ 03108 int maxfds; 03109 int fd; 03110 03111 fd = open ("/dev/null", O_RDWR); 03112 if (fd == -1) 03113 /* huh?! can't open /dev/null? */ 03114 _exit (1); 03115 03116 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03117 03118 /* set-up stdXXX */ 03119 close (result_pipe[READ_END]); 03120 close (errors_pipe[READ_END]); 03121 close (0); /* close stdin */ 03122 close (1); /* close stdout */ 03123 close (2); /* close stderr */ 03124 03125 if (dup2 (fd, 0) == -1) 03126 _exit (1); 03127 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03128 _exit (1); 03129 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03130 _exit (1); 03131 03132 maxfds = sysconf (_SC_OPEN_MAX); 03133 /* Pick something reasonable if for some reason sysconf 03134 * says unlimited. 03135 */ 03136 if (maxfds < 0) 03137 maxfds = 1024; 03138 /* close all inherited fds */ 03139 for (i = 3; i < maxfds; i++) 03140 close (i); 03141 03142 sigprocmask (SIG_SETMASK, &old_set, NULL); 03143 03144 /* If it looks fully-qualified, try execv first */ 03145 if (progpath[0] == '/') 03146 { 03147 execv (progpath, argv); 03148 /* Ok, that failed. Now if path_fallback is given, let's 03149 * try unqualified. This is mostly a hack to work 03150 * around systems which ship dbus-launch in /usr/bin 03151 * but everything else in /bin (because dbus-launch 03152 * depends on X11). 03153 */ 03154 if (path_fallback) 03155 /* We must have a slash, because we checked above */ 03156 execvp (strrchr (progpath, '/')+1, argv); 03157 } 03158 else 03159 execvp (progpath, argv); 03160 03161 /* still nothing, we failed */ 03162 _exit (1); 03163 } 03164 03165 /* parent process */ 03166 close (result_pipe[WRITE_END]); 03167 close (errors_pipe[WRITE_END]); 03168 result_pipe[WRITE_END] = -1; 03169 errors_pipe[WRITE_END] = -1; 03170 03171 ret = 0; 03172 do 03173 { 03174 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03175 } 03176 while (ret > 0); 03177 03178 /* reap the child process to avoid it lingering as zombie */ 03179 do 03180 { 03181 ret = waitpid (pid, &status, 0); 03182 } 03183 while (ret == -1 && errno == EINTR); 03184 03185 /* We succeeded if the process exited with status 0 and 03186 anything was read */ 03187 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03188 { 03189 /* The process ended with error */ 03190 DBusString error_message; 03191 _dbus_string_init (&error_message); 03192 ret = 0; 03193 do 03194 { 03195 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03196 } 03197 while (ret > 0); 03198 03199 _dbus_string_set_length (result, orig_len); 03200 if (_dbus_string_get_length (&error_message) > 0) 03201 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03202 "%s terminated abnormally with the following error: %s", 03203 progpath, _dbus_string_get_data (&error_message)); 03204 else 03205 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03206 "%s terminated abnormally without any error message", 03207 progpath); 03208 goto out; 03209 } 03210 03211 retval = TRUE; 03212 03213 out: 03214 sigprocmask (SIG_SETMASK, &old_set, NULL); 03215 03216 if (retval) 03217 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03218 else 03219 _DBUS_ASSERT_ERROR_IS_SET (error); 03220 03221 if (result_pipe[0] != -1) 03222 close (result_pipe[0]); 03223 if (result_pipe[1] != -1) 03224 close (result_pipe[1]); 03225 if (errors_pipe[0] != -1) 03226 close (errors_pipe[0]); 03227 if (errors_pipe[1] != -1) 03228 close (errors_pipe[1]); 03229 03230 return retval; 03231 } 03232 03244 dbus_bool_t 03245 _dbus_get_autolaunch_address (const char *scope, 03246 DBusString *address, 03247 DBusError *error) 03248 { 03249 static char *argv[6]; 03250 int i; 03251 DBusString uuid; 03252 dbus_bool_t retval; 03253 03254 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03255 retval = FALSE; 03256 03257 if (!_dbus_string_init (&uuid)) 03258 { 03259 _DBUS_SET_OOM (error); 03260 return FALSE; 03261 } 03262 03263 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03264 { 03265 _DBUS_SET_OOM (error); 03266 goto out; 03267 } 03268 03269 i = 0; 03270 argv[i] = "dbus-launch"; 03271 ++i; 03272 argv[i] = "--autolaunch"; 03273 ++i; 03274 argv[i] = _dbus_string_get_data (&uuid); 03275 ++i; 03276 argv[i] = "--binary-syntax"; 03277 ++i; 03278 argv[i] = "--close-stderr"; 03279 ++i; 03280 argv[i] = NULL; 03281 ++i; 03282 03283 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03284 03285 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03286 TRUE, 03287 argv, address, error); 03288 03289 out: 03290 _dbus_string_free (&uuid); 03291 return retval; 03292 } 03293 03312 dbus_bool_t 03313 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03314 dbus_bool_t create_if_not_found, 03315 DBusError *error) 03316 { 03317 DBusString filename; 03318 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03319 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03320 } 03321 03322 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03323 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03324 03331 dbus_bool_t 03332 _dbus_lookup_launchd_socket (DBusString *socket_path, 03333 const char *launchd_env_var, 03334 DBusError *error) 03335 { 03336 #ifdef DBUS_ENABLE_LAUNCHD 03337 char *argv[4]; 03338 int i; 03339 03340 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03341 03342 i = 0; 03343 argv[i] = "launchctl"; 03344 ++i; 03345 argv[i] = "getenv"; 03346 ++i; 03347 argv[i] = (char*)launchd_env_var; 03348 ++i; 03349 argv[i] = NULL; 03350 ++i; 03351 03352 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03353 03354 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03355 { 03356 return FALSE; 03357 } 03358 03359 /* no error, but no result either */ 03360 if (_dbus_string_get_length(socket_path) == 0) 03361 { 03362 return FALSE; 03363 } 03364 03365 /* strip the carriage-return */ 03366 _dbus_string_shorten(socket_path, 1); 03367 return TRUE; 03368 #else /* DBUS_ENABLE_LAUNCHD */ 03369 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03370 "can't lookup socket from launchd; launchd support not compiled in"); 03371 return FALSE; 03372 #endif 03373 } 03374 03375 static dbus_bool_t 03376 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03377 { 03378 #ifdef DBUS_ENABLE_LAUNCHD 03379 dbus_bool_t valid_socket; 03380 DBusString socket_path; 03381 03382 if (!_dbus_string_init (&socket_path)) 03383 { 03384 _DBUS_SET_OOM (error); 03385 return FALSE; 03386 } 03387 03388 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03389 03390 if (dbus_error_is_set(error)) 03391 { 03392 _dbus_string_free(&socket_path); 03393 return FALSE; 03394 } 03395 03396 if (!valid_socket) 03397 { 03398 dbus_set_error(error, "no socket path", 03399 "launchd did not provide a socket path, " 03400 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03401 _dbus_string_free(&socket_path); 03402 return FALSE; 03403 } 03404 if (!_dbus_string_append (address, "unix:path=")) 03405 { 03406 _DBUS_SET_OOM (error); 03407 _dbus_string_free(&socket_path); 03408 return FALSE; 03409 } 03410 if (!_dbus_string_copy (&socket_path, 0, address, 03411 _dbus_string_get_length (address))) 03412 { 03413 _DBUS_SET_OOM (error); 03414 _dbus_string_free(&socket_path); 03415 return FALSE; 03416 } 03417 03418 _dbus_string_free(&socket_path); 03419 return TRUE; 03420 #else 03421 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03422 "can't lookup session address from launchd; launchd support not compiled in"); 03423 return FALSE; 03424 #endif 03425 } 03426 03446 dbus_bool_t 03447 _dbus_lookup_session_address (dbus_bool_t *supported, 03448 DBusString *address, 03449 DBusError *error) 03450 { 03451 #ifdef DBUS_ENABLE_LAUNCHD 03452 *supported = TRUE; 03453 return _dbus_lookup_session_address_launchd (address, error); 03454 #else 03455 /* On non-Mac Unix platforms, if the session address isn't already 03456 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03457 * fall back to the autolaunch: global default; see 03458 * init_session_address in dbus/dbus-bus.c. */ 03459 *supported = FALSE; 03460 return TRUE; 03461 #endif 03462 } 03463 03481 dbus_bool_t 03482 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03483 { 03484 const char *xdg_data_home; 03485 const char *xdg_data_dirs; 03486 DBusString servicedir_path; 03487 03488 if (!_dbus_string_init (&servicedir_path)) 03489 return FALSE; 03490 03491 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03492 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03493 03494 if (xdg_data_dirs != NULL) 03495 { 03496 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03497 goto oom; 03498 03499 if (!_dbus_string_append (&servicedir_path, ":")) 03500 goto oom; 03501 } 03502 else 03503 { 03504 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03505 goto oom; 03506 } 03507 03508 /* 03509 * add configured datadir to defaults 03510 * this may be the same as an xdg dir 03511 * however the config parser should take 03512 * care of duplicates 03513 */ 03514 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) 03515 goto oom; 03516 03517 if (xdg_data_home != NULL) 03518 { 03519 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03520 goto oom; 03521 } 03522 else 03523 { 03524 const DBusString *homedir; 03525 DBusString local_share; 03526 03527 if (!_dbus_homedir_from_current_process (&homedir)) 03528 goto oom; 03529 03530 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03531 goto oom; 03532 03533 _dbus_string_init_const (&local_share, "/.local/share"); 03534 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03535 goto oom; 03536 } 03537 03538 if (!_dbus_split_paths_and_append (&servicedir_path, 03539 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03540 dirs)) 03541 goto oom; 03542 03543 _dbus_string_free (&servicedir_path); 03544 return TRUE; 03545 03546 oom: 03547 _dbus_string_free (&servicedir_path); 03548 return FALSE; 03549 } 03550 03551 03570 dbus_bool_t 03571 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03572 { 03573 const char *xdg_data_dirs; 03574 DBusString servicedir_path; 03575 03576 if (!_dbus_string_init (&servicedir_path)) 03577 return FALSE; 03578 03579 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03580 03581 if (xdg_data_dirs != NULL) 03582 { 03583 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03584 goto oom; 03585 03586 if (!_dbus_string_append (&servicedir_path, ":")) 03587 goto oom; 03588 } 03589 else 03590 { 03591 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03592 goto oom; 03593 } 03594 03595 /* 03596 * add configured datadir to defaults 03597 * this may be the same as an xdg dir 03598 * however the config parser should take 03599 * care of duplicates 03600 */ 03601 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) 03602 goto oom; 03603 03604 if (!_dbus_split_paths_and_append (&servicedir_path, 03605 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03606 dirs)) 03607 goto oom; 03608 03609 _dbus_string_free (&servicedir_path); 03610 return TRUE; 03611 03612 oom: 03613 _dbus_string_free (&servicedir_path); 03614 return FALSE; 03615 } 03616 03625 dbus_bool_t 03626 _dbus_append_system_config_file (DBusString *str) 03627 { 03628 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03629 } 03630 03637 dbus_bool_t 03638 _dbus_append_session_config_file (DBusString *str) 03639 { 03640 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03641 } 03642 03650 void 03651 _dbus_flush_caches (void) 03652 { 03653 _dbus_user_database_flush_system (); 03654 } 03655 03669 dbus_bool_t 03670 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03671 DBusCredentials *credentials) 03672 { 03673 DBusString homedir; 03674 DBusString dotdir; 03675 dbus_uid_t uid; 03676 03677 _dbus_assert (credentials != NULL); 03678 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03679 03680 if (!_dbus_string_init (&homedir)) 03681 return FALSE; 03682 03683 uid = _dbus_credentials_get_unix_uid (credentials); 03684 _dbus_assert (uid != DBUS_UID_UNSET); 03685 03686 if (!_dbus_homedir_from_uid (uid, &homedir)) 03687 goto failed; 03688 03689 #ifdef DBUS_BUILD_TESTS 03690 { 03691 const char *override; 03692 03693 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03694 if (override != NULL && *override != '\0') 03695 { 03696 _dbus_string_set_length (&homedir, 0); 03697 if (!_dbus_string_append (&homedir, override)) 03698 goto failed; 03699 03700 _dbus_verbose ("Using fake homedir for testing: %s\n", 03701 _dbus_string_get_const_data (&homedir)); 03702 } 03703 else 03704 { 03705 static dbus_bool_t already_warned = FALSE; 03706 if (!already_warned) 03707 { 03708 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03709 already_warned = TRUE; 03710 } 03711 } 03712 } 03713 #endif 03714 03715 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03716 if (!_dbus_concat_dir_and_file (&homedir, 03717 &dotdir)) 03718 goto failed; 03719 03720 if (!_dbus_string_copy (&homedir, 0, 03721 directory, _dbus_string_get_length (directory))) { 03722 goto failed; 03723 } 03724 03725 _dbus_string_free (&homedir); 03726 return TRUE; 03727 03728 failed: 03729 _dbus_string_free (&homedir); 03730 return FALSE; 03731 } 03732 03733 //PENDING(kdab) docs 03734 dbus_bool_t 03735 _dbus_daemon_publish_session_bus_address (const char* addr, 03736 const char *scope) 03737 { 03738 return TRUE; 03739 } 03740 03741 //PENDING(kdab) docs 03742 void 03743 _dbus_daemon_unpublish_session_bus_address (void) 03744 { 03745 03746 } 03747 03754 dbus_bool_t 03755 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03756 { 03757 return errno == EAGAIN || errno == EWOULDBLOCK; 03758 } 03759 03767 dbus_bool_t 03768 _dbus_delete_directory (const DBusString *filename, 03769 DBusError *error) 03770 { 03771 const char *filename_c; 03772 03773 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03774 03775 filename_c = _dbus_string_get_const_data (filename); 03776 03777 if (rmdir (filename_c) != 0) 03778 { 03779 dbus_set_error (error, DBUS_ERROR_FAILED, 03780 "Failed to remove directory %s: %s\n", 03781 filename_c, _dbus_strerror (errno)); 03782 return FALSE; 03783 } 03784 03785 return TRUE; 03786 } 03787 03795 dbus_bool_t 03796 _dbus_socket_can_pass_unix_fd(int fd) { 03797 03798 #ifdef SCM_RIGHTS 03799 union { 03800 struct sockaddr sa; 03801 struct sockaddr_storage storage; 03802 struct sockaddr_un un; 03803 } sa_buf; 03804 03805 socklen_t sa_len = sizeof(sa_buf); 03806 03807 _DBUS_ZERO(sa_buf); 03808 03809 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03810 return FALSE; 03811 03812 return sa_buf.sa.sa_family == AF_UNIX; 03813 03814 #else 03815 return FALSE; 03816 03817 #endif 03818 } 03819 03820 03821 /* 03822 * replaces the term DBUS_PREFIX in configure_time_path by the 03823 * current dbus installation directory. On unix this function is a noop 03824 * 03825 * @param configure_time_path 03826 * @return real path 03827 */ 03828 const char * 03829 _dbus_replace_install_prefix (const char *configure_time_path) 03830 { 03831 return configure_time_path; 03832 } 03833 03834 /* tests in dbus-sysdeps-util.c */