D-Bus 1.4.0
|
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 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 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 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 #else 01498 bytes_written = write (server_fd, buf, 1); 01499 #endif 01500 01501 if (bytes_written < 0 && errno == EINTR) 01502 goto again; 01503 01504 if (bytes_written < 0) 01505 { 01506 dbus_set_error (error, _dbus_error_from_errno (errno), 01507 "Failed to write credentials byte: %s", 01508 _dbus_strerror (errno)); 01509 return FALSE; 01510 } 01511 else if (bytes_written == 0) 01512 { 01513 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01514 "wrote zero bytes writing credentials byte"); 01515 return FALSE; 01516 } 01517 else 01518 { 01519 _dbus_assert (bytes_written == 1); 01520 _dbus_verbose ("wrote credentials byte\n"); 01521 return TRUE; 01522 } 01523 } 01524 01546 dbus_bool_t 01547 _dbus_read_credentials_socket (int client_fd, 01548 DBusCredentials *credentials, 01549 DBusError *error) 01550 { 01551 struct msghdr msg; 01552 struct iovec iov; 01553 char buf; 01554 dbus_uid_t uid_read; 01555 dbus_pid_t pid_read; 01556 int bytes_read; 01557 01558 #ifdef HAVE_CMSGCRED 01559 union { 01560 struct cmsghdr hdr; 01561 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01562 } cmsg; 01563 01564 #elif defined(LOCAL_CREDS) 01565 struct { 01566 struct cmsghdr hdr; 01567 struct sockcred cred; 01568 } cmsg; 01569 #endif 01570 01571 uid_read = DBUS_UID_UNSET; 01572 pid_read = DBUS_PID_UNSET; 01573 01574 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01575 01576 /* The POSIX spec certainly doesn't promise this, but 01577 * we need these assertions to fail as soon as we're wrong about 01578 * it so we can do the porting fixups 01579 */ 01580 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01581 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01582 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01583 01584 _dbus_credentials_clear (credentials); 01585 01586 /* Systems supporting LOCAL_CREDS are configured to have this feature 01587 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01588 * the connection. Therefore, the received message must carry the 01589 * credentials information without doing anything special. 01590 */ 01591 01592 iov.iov_base = &buf; 01593 iov.iov_len = 1; 01594 01595 _DBUS_ZERO(msg); 01596 msg.msg_iov = &iov; 01597 msg.msg_iovlen = 1; 01598 01599 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01600 _DBUS_ZERO(cmsg); 01601 msg.msg_control = (caddr_t) &cmsg; 01602 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01603 #endif 01604 01605 again: 01606 bytes_read = recvmsg (client_fd, &msg, 0); 01607 01608 if (bytes_read < 0) 01609 { 01610 if (errno == EINTR) 01611 goto again; 01612 01613 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01614 * normally only call read_credentials if the socket was ready 01615 * for reading 01616 */ 01617 01618 dbus_set_error (error, _dbus_error_from_errno (errno), 01619 "Failed to read credentials byte: %s", 01620 _dbus_strerror (errno)); 01621 return FALSE; 01622 } 01623 else if (bytes_read == 0) 01624 { 01625 /* this should not happen unless we are using recvmsg wrong, 01626 * so is essentially here for paranoia 01627 */ 01628 dbus_set_error (error, DBUS_ERROR_FAILED, 01629 "Failed to read credentials byte (zero-length read)"); 01630 return FALSE; 01631 } 01632 else if (buf != '\0') 01633 { 01634 dbus_set_error (error, DBUS_ERROR_FAILED, 01635 "Credentials byte was not nul"); 01636 return FALSE; 01637 } 01638 01639 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01640 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01641 || cmsg.hdr.cmsg_type != SCM_CREDS) 01642 { 01643 dbus_set_error (error, DBUS_ERROR_FAILED, 01644 "Message from recvmsg() was not SCM_CREDS"); 01645 return FALSE; 01646 } 01647 #endif 01648 01649 _dbus_verbose ("read credentials byte\n"); 01650 01651 { 01652 #ifdef SO_PEERCRED 01653 struct ucred cr; 01654 int cr_len = sizeof (cr); 01655 01656 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01657 cr_len == sizeof (cr)) 01658 { 01659 pid_read = cr.pid; 01660 uid_read = cr.uid; 01661 } 01662 else 01663 { 01664 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01665 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01666 } 01667 #elif defined(HAVE_CMSGCRED) 01668 struct cmsgcred *cred; 01669 01670 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01671 pid_read = cred->cmcred_pid; 01672 uid_read = cred->cmcred_euid; 01673 #elif defined(LOCAL_CREDS) 01674 pid_read = DBUS_PID_UNSET; 01675 uid_read = cmsg.cred.sc_uid; 01676 /* Since we have already got the credentials from this socket, we can 01677 * disable its LOCAL_CREDS flag if it was ever set. */ 01678 _dbus_set_local_creds (client_fd, FALSE); 01679 #elif defined(HAVE_GETPEEREID) 01680 uid_t euid; 01681 gid_t egid; 01682 if (getpeereid (client_fd, &euid, &egid) == 0) 01683 { 01684 uid_read = euid; 01685 } 01686 else 01687 { 01688 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01689 } 01690 #elif defined(HAVE_GETPEERUCRED) 01691 ucred_t * ucred = NULL; 01692 if (getpeerucred (client_fd, &ucred) == 0) 01693 { 01694 pid_read = ucred_getpid (ucred); 01695 uid_read = ucred_geteuid (ucred); 01696 #ifdef HAVE_ADT 01697 /* generate audit session data based on socket ucred */ 01698 adt_session_data_t *adth = NULL; 01699 adt_export_data_t *data = NULL; 01700 size_t size = 0; 01701 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01702 { 01703 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01704 } 01705 else 01706 { 01707 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01708 { 01709 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01710 } 01711 else 01712 { 01713 size = adt_export_session_data (adth, &data); 01714 if (size <= 0) 01715 { 01716 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01717 } 01718 else 01719 { 01720 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01721 free (data); 01722 } 01723 } 01724 (void) adt_end_session (adth); 01725 } 01726 #endif /* HAVE_ADT */ 01727 } 01728 else 01729 { 01730 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01731 } 01732 if (ucred != NULL) 01733 ucred_free (ucred); 01734 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01735 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01736 #endif 01737 } 01738 01739 _dbus_verbose ("Credentials:" 01740 " pid "DBUS_PID_FORMAT 01741 " uid "DBUS_UID_FORMAT 01742 "\n", 01743 pid_read, 01744 uid_read); 01745 01746 if (pid_read != DBUS_PID_UNSET) 01747 { 01748 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01749 { 01750 _DBUS_SET_OOM (error); 01751 return FALSE; 01752 } 01753 } 01754 01755 if (uid_read != DBUS_UID_UNSET) 01756 { 01757 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01758 { 01759 _DBUS_SET_OOM (error); 01760 return FALSE; 01761 } 01762 } 01763 01764 return TRUE; 01765 } 01766 01784 dbus_bool_t 01785 _dbus_send_credentials_socket (int server_fd, 01786 DBusError *error) 01787 { 01788 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01789 01790 if (write_credentials_byte (server_fd, error)) 01791 return TRUE; 01792 else 01793 return FALSE; 01794 } 01795 01805 int 01806 _dbus_accept (int listen_fd) 01807 { 01808 int client_fd; 01809 struct sockaddr addr; 01810 socklen_t addrlen; 01811 #ifdef HAVE_ACCEPT4 01812 dbus_bool_t cloexec_done; 01813 #endif 01814 01815 addrlen = sizeof (addr); 01816 01817 retry: 01818 01819 #ifdef HAVE_ACCEPT4 01820 /* We assume that if accept4 is available SOCK_CLOEXEC is too */ 01821 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01822 cloexec_done = client_fd >= 0; 01823 01824 if (client_fd < 0 && errno == ENOSYS) 01825 #endif 01826 { 01827 client_fd = accept (listen_fd, &addr, &addrlen); 01828 } 01829 01830 if (client_fd < 0) 01831 { 01832 if (errno == EINTR) 01833 goto retry; 01834 } 01835 01836 _dbus_verbose ("client fd %d accepted\n", client_fd); 01837 01838 #ifdef HAVE_ACCEPT4 01839 if (!cloexec_done) 01840 #endif 01841 { 01842 _dbus_fd_set_close_on_exec(client_fd); 01843 } 01844 01845 return client_fd; 01846 } 01847 01856 dbus_bool_t 01857 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01858 { 01859 const char *directory; 01860 struct stat sb; 01861 01862 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01863 01864 directory = _dbus_string_get_const_data (dir); 01865 01866 if (stat (directory, &sb) < 0) 01867 { 01868 dbus_set_error (error, _dbus_error_from_errno (errno), 01869 "%s", _dbus_strerror (errno)); 01870 01871 return FALSE; 01872 } 01873 01874 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01875 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01876 { 01877 dbus_set_error (error, DBUS_ERROR_FAILED, 01878 "%s directory is not private to the user", directory); 01879 return FALSE; 01880 } 01881 01882 return TRUE; 01883 } 01884 01885 static dbus_bool_t 01886 fill_user_info_from_passwd (struct passwd *p, 01887 DBusUserInfo *info, 01888 DBusError *error) 01889 { 01890 _dbus_assert (p->pw_name != NULL); 01891 _dbus_assert (p->pw_dir != NULL); 01892 01893 info->uid = p->pw_uid; 01894 info->primary_gid = p->pw_gid; 01895 info->username = _dbus_strdup (p->pw_name); 01896 info->homedir = _dbus_strdup (p->pw_dir); 01897 01898 if (info->username == NULL || 01899 info->homedir == NULL) 01900 { 01901 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01902 return FALSE; 01903 } 01904 01905 return TRUE; 01906 } 01907 01908 static dbus_bool_t 01909 fill_user_info (DBusUserInfo *info, 01910 dbus_uid_t uid, 01911 const DBusString *username, 01912 DBusError *error) 01913 { 01914 const char *username_c; 01915 01916 /* exactly one of username/uid provided */ 01917 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 01918 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 01919 01920 info->uid = DBUS_UID_UNSET; 01921 info->primary_gid = DBUS_GID_UNSET; 01922 info->group_ids = NULL; 01923 info->n_group_ids = 0; 01924 info->username = NULL; 01925 info->homedir = NULL; 01926 01927 if (username != NULL) 01928 username_c = _dbus_string_get_const_data (username); 01929 else 01930 username_c = NULL; 01931 01932 /* For now assuming that the getpwnam() and getpwuid() flavors 01933 * are always symmetrical, if not we have to add more configure 01934 * checks 01935 */ 01936 01937 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 01938 { 01939 struct passwd *p; 01940 int result; 01941 size_t buflen; 01942 char *buf; 01943 struct passwd p_str; 01944 01945 /* retrieve maximum needed size for buf */ 01946 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 01947 01948 /* sysconf actually returns a long, but everything else expects size_t, 01949 * so just recast here. 01950 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 01951 */ 01952 if ((long) buflen <= 0) 01953 buflen = 1024; 01954 01955 result = -1; 01956 while (1) 01957 { 01958 buf = dbus_malloc (buflen); 01959 if (buf == NULL) 01960 { 01961 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01962 return FALSE; 01963 } 01964 01965 p = NULL; 01966 #ifdef HAVE_POSIX_GETPWNAM_R 01967 if (uid != DBUS_UID_UNSET) 01968 result = getpwuid_r (uid, &p_str, buf, buflen, 01969 &p); 01970 else 01971 result = getpwnam_r (username_c, &p_str, buf, buflen, 01972 &p); 01973 #else 01974 if (uid != DBUS_UID_UNSET) 01975 p = getpwuid_r (uid, &p_str, buf, buflen); 01976 else 01977 p = getpwnam_r (username_c, &p_str, buf, buflen); 01978 result = 0; 01979 #endif /* !HAVE_POSIX_GETPWNAM_R */ 01980 //Try a bigger buffer if ERANGE was returned 01981 if (result == ERANGE && buflen < 512 * 1024) 01982 { 01983 dbus_free (buf); 01984 buflen *= 2; 01985 } 01986 else 01987 { 01988 break; 01989 } 01990 } 01991 if (result == 0 && p == &p_str) 01992 { 01993 if (!fill_user_info_from_passwd (p, info, error)) 01994 { 01995 dbus_free (buf); 01996 return FALSE; 01997 } 01998 dbus_free (buf); 01999 } 02000 else 02001 { 02002 dbus_set_error (error, _dbus_error_from_errno (errno), 02003 "User \"%s\" unknown or no memory to allocate password entry\n", 02004 username_c ? username_c : "???"); 02005 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02006 dbus_free (buf); 02007 return FALSE; 02008 } 02009 } 02010 #else /* ! HAVE_GETPWNAM_R */ 02011 { 02012 /* I guess we're screwed on thread safety here */ 02013 struct passwd *p; 02014 02015 if (uid != DBUS_UID_UNSET) 02016 p = getpwuid (uid); 02017 else 02018 p = getpwnam (username_c); 02019 02020 if (p != NULL) 02021 { 02022 if (!fill_user_info_from_passwd (p, info, error)) 02023 { 02024 return FALSE; 02025 } 02026 } 02027 else 02028 { 02029 dbus_set_error (error, _dbus_error_from_errno (errno), 02030 "User \"%s\" unknown or no memory to allocate password entry\n", 02031 username_c ? username_c : "???"); 02032 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02033 return FALSE; 02034 } 02035 } 02036 #endif /* ! HAVE_GETPWNAM_R */ 02037 02038 /* Fill this in so we can use it to get groups */ 02039 username_c = info->username; 02040 02041 #ifdef HAVE_GETGROUPLIST 02042 { 02043 gid_t *buf; 02044 int buf_count; 02045 int i; 02046 int initial_buf_count; 02047 02048 initial_buf_count = 17; 02049 buf_count = initial_buf_count; 02050 buf = dbus_new (gid_t, buf_count); 02051 if (buf == NULL) 02052 { 02053 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02054 goto failed; 02055 } 02056 02057 if (getgrouplist (username_c, 02058 info->primary_gid, 02059 buf, &buf_count) < 0) 02060 { 02061 gid_t *new; 02062 /* Presumed cause of negative return code: buf has insufficient 02063 entries to hold the entire group list. The Linux behavior in this 02064 case is to pass back the actual number of groups in buf_count, but 02065 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02066 So as a hack, try to help out a bit by guessing a larger 02067 number of groups, within reason.. might still fail, of course, 02068 but we can at least print a more informative message. I looked up 02069 the "right way" to do this by downloading Apple's own source code 02070 for the "id" command, and it turns out that they use an 02071 undocumented library function getgrouplist_2 (!) which is not 02072 declared in any header in /usr/include (!!). That did not seem 02073 like the way to go here. 02074 */ 02075 if (buf_count == initial_buf_count) 02076 { 02077 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02078 } 02079 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02080 if (new == NULL) 02081 { 02082 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02083 dbus_free (buf); 02084 goto failed; 02085 } 02086 02087 buf = new; 02088 02089 errno = 0; 02090 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02091 { 02092 if (errno == 0) 02093 { 02094 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02095 username_c, buf_count, buf_count); 02096 } 02097 else 02098 { 02099 dbus_set_error (error, 02100 _dbus_error_from_errno (errno), 02101 "Failed to get groups for username \"%s\" primary GID " 02102 DBUS_GID_FORMAT ": %s\n", 02103 username_c, info->primary_gid, 02104 _dbus_strerror (errno)); 02105 dbus_free (buf); 02106 goto failed; 02107 } 02108 } 02109 } 02110 02111 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02112 if (info->group_ids == NULL) 02113 { 02114 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02115 dbus_free (buf); 02116 goto failed; 02117 } 02118 02119 for (i = 0; i < buf_count; ++i) 02120 info->group_ids[i] = buf[i]; 02121 02122 info->n_group_ids = buf_count; 02123 02124 dbus_free (buf); 02125 } 02126 #else /* HAVE_GETGROUPLIST */ 02127 { 02128 /* We just get the one group ID */ 02129 info->group_ids = dbus_new (dbus_gid_t, 1); 02130 if (info->group_ids == NULL) 02131 { 02132 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02133 goto failed; 02134 } 02135 02136 info->n_group_ids = 1; 02137 02138 (info->group_ids)[0] = info->primary_gid; 02139 } 02140 #endif /* HAVE_GETGROUPLIST */ 02141 02142 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02143 02144 return TRUE; 02145 02146 failed: 02147 _DBUS_ASSERT_ERROR_IS_SET (error); 02148 return FALSE; 02149 } 02150 02159 dbus_bool_t 02160 _dbus_user_info_fill (DBusUserInfo *info, 02161 const DBusString *username, 02162 DBusError *error) 02163 { 02164 return fill_user_info (info, DBUS_UID_UNSET, 02165 username, error); 02166 } 02167 02176 dbus_bool_t 02177 _dbus_user_info_fill_uid (DBusUserInfo *info, 02178 dbus_uid_t uid, 02179 DBusError *error) 02180 { 02181 return fill_user_info (info, uid, 02182 NULL, error); 02183 } 02184 02192 dbus_bool_t 02193 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02194 { 02195 /* The POSIX spec certainly doesn't promise this, but 02196 * we need these assertions to fail as soon as we're wrong about 02197 * it so we can do the porting fixups 02198 */ 02199 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02200 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02201 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02202 02203 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 02204 return FALSE; 02205 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02206 return FALSE; 02207 02208 return TRUE; 02209 } 02210 02222 dbus_bool_t 02223 _dbus_append_user_from_current_process (DBusString *str) 02224 { 02225 return _dbus_string_append_uint (str, 02226 _dbus_geteuid ()); 02227 } 02228 02233 dbus_pid_t 02234 _dbus_getpid (void) 02235 { 02236 return getpid (); 02237 } 02238 02242 dbus_uid_t 02243 _dbus_getuid (void) 02244 { 02245 return getuid (); 02246 } 02247 02251 dbus_uid_t 02252 _dbus_geteuid (void) 02253 { 02254 return geteuid (); 02255 } 02256 02263 unsigned long 02264 _dbus_pid_for_log (void) 02265 { 02266 return getpid (); 02267 } 02268 02276 dbus_bool_t 02277 _dbus_parse_uid (const DBusString *uid_str, 02278 dbus_uid_t *uid) 02279 { 02280 int end; 02281 long val; 02282 02283 if (_dbus_string_get_length (uid_str) == 0) 02284 { 02285 _dbus_verbose ("UID string was zero length\n"); 02286 return FALSE; 02287 } 02288 02289 val = -1; 02290 end = 0; 02291 if (!_dbus_string_parse_int (uid_str, 0, &val, 02292 &end)) 02293 { 02294 _dbus_verbose ("could not parse string as a UID\n"); 02295 return FALSE; 02296 } 02297 02298 if (end != _dbus_string_get_length (uid_str)) 02299 { 02300 _dbus_verbose ("string contained trailing stuff after UID\n"); 02301 return FALSE; 02302 } 02303 02304 *uid = val; 02305 02306 return TRUE; 02307 } 02308 02309 #if !DBUS_USE_SYNC 02310 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02311 #endif 02312 02319 dbus_int32_t 02320 _dbus_atomic_inc (DBusAtomic *atomic) 02321 { 02322 #if DBUS_USE_SYNC 02323 return __sync_add_and_fetch(&atomic->value, 1)-1; 02324 #else 02325 dbus_int32_t res; 02326 _DBUS_LOCK (atomic); 02327 res = atomic->value; 02328 atomic->value += 1; 02329 _DBUS_UNLOCK (atomic); 02330 return res; 02331 #endif 02332 } 02333 02340 dbus_int32_t 02341 _dbus_atomic_dec (DBusAtomic *atomic) 02342 { 02343 #if DBUS_USE_SYNC 02344 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02345 #else 02346 dbus_int32_t res; 02347 02348 _DBUS_LOCK (atomic); 02349 res = atomic->value; 02350 atomic->value -= 1; 02351 _DBUS_UNLOCK (atomic); 02352 return res; 02353 #endif 02354 } 02355 02356 #ifdef DBUS_BUILD_TESTS 02357 02360 dbus_gid_t 02361 _dbus_getgid (void) 02362 { 02363 return getgid (); 02364 } 02365 #endif 02366 02375 int 02376 _dbus_poll (DBusPollFD *fds, 02377 int n_fds, 02378 int timeout_milliseconds) 02379 { 02380 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02381 /* This big thing is a constant expression and should get optimized 02382 * out of existence. So it's more robust than a configure check at 02383 * no cost. 02384 */ 02385 if (_DBUS_POLLIN == POLLIN && 02386 _DBUS_POLLPRI == POLLPRI && 02387 _DBUS_POLLOUT == POLLOUT && 02388 _DBUS_POLLERR == POLLERR && 02389 _DBUS_POLLHUP == POLLHUP && 02390 _DBUS_POLLNVAL == POLLNVAL && 02391 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02392 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02393 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02394 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02395 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02396 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02397 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02398 { 02399 return poll ((struct pollfd*) fds, 02400 n_fds, 02401 timeout_milliseconds); 02402 } 02403 else 02404 { 02405 /* We have to convert the DBusPollFD to an array of 02406 * struct pollfd, poll, and convert back. 02407 */ 02408 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02409 return -1; 02410 } 02411 #else /* ! HAVE_POLL */ 02412 02413 fd_set read_set, write_set, err_set; 02414 int max_fd = 0; 02415 int i; 02416 struct timeval tv; 02417 int ready; 02418 02419 FD_ZERO (&read_set); 02420 FD_ZERO (&write_set); 02421 FD_ZERO (&err_set); 02422 02423 for (i = 0; i < n_fds; i++) 02424 { 02425 DBusPollFD *fdp = &fds[i]; 02426 02427 if (fdp->events & _DBUS_POLLIN) 02428 FD_SET (fdp->fd, &read_set); 02429 02430 if (fdp->events & _DBUS_POLLOUT) 02431 FD_SET (fdp->fd, &write_set); 02432 02433 FD_SET (fdp->fd, &err_set); 02434 02435 max_fd = MAX (max_fd, fdp->fd); 02436 } 02437 02438 tv.tv_sec = timeout_milliseconds / 1000; 02439 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02440 02441 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02442 timeout_milliseconds < 0 ? NULL : &tv); 02443 02444 if (ready > 0) 02445 { 02446 for (i = 0; i < n_fds; i++) 02447 { 02448 DBusPollFD *fdp = &fds[i]; 02449 02450 fdp->revents = 0; 02451 02452 if (FD_ISSET (fdp->fd, &read_set)) 02453 fdp->revents |= _DBUS_POLLIN; 02454 02455 if (FD_ISSET (fdp->fd, &write_set)) 02456 fdp->revents |= _DBUS_POLLOUT; 02457 02458 if (FD_ISSET (fdp->fd, &err_set)) 02459 fdp->revents |= _DBUS_POLLERR; 02460 } 02461 } 02462 02463 return ready; 02464 #endif 02465 } 02466 02474 void 02475 _dbus_get_current_time (long *tv_sec, 02476 long *tv_usec) 02477 { 02478 struct timeval t; 02479 02480 #ifdef HAVE_MONOTONIC_CLOCK 02481 struct timespec ts; 02482 clock_gettime (CLOCK_MONOTONIC, &ts); 02483 02484 if (tv_sec) 02485 *tv_sec = ts.tv_sec; 02486 if (tv_usec) 02487 *tv_usec = ts.tv_nsec / 1000; 02488 #else 02489 gettimeofday (&t, NULL); 02490 02491 if (tv_sec) 02492 *tv_sec = t.tv_sec; 02493 if (tv_usec) 02494 *tv_usec = t.tv_usec; 02495 #endif 02496 } 02497 02506 dbus_bool_t 02507 _dbus_create_directory (const DBusString *filename, 02508 DBusError *error) 02509 { 02510 const char *filename_c; 02511 02512 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02513 02514 filename_c = _dbus_string_get_const_data (filename); 02515 02516 if (mkdir (filename_c, 0700) < 0) 02517 { 02518 if (errno == EEXIST) 02519 return TRUE; 02520 02521 dbus_set_error (error, DBUS_ERROR_FAILED, 02522 "Failed to create directory %s: %s\n", 02523 filename_c, _dbus_strerror (errno)); 02524 return FALSE; 02525 } 02526 else 02527 return TRUE; 02528 } 02529 02540 dbus_bool_t 02541 _dbus_concat_dir_and_file (DBusString *dir, 02542 const DBusString *next_component) 02543 { 02544 dbus_bool_t dir_ends_in_slash; 02545 dbus_bool_t file_starts_with_slash; 02546 02547 if (_dbus_string_get_length (dir) == 0 || 02548 _dbus_string_get_length (next_component) == 0) 02549 return TRUE; 02550 02551 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02552 _dbus_string_get_length (dir) - 1); 02553 02554 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02555 02556 if (dir_ends_in_slash && file_starts_with_slash) 02557 { 02558 _dbus_string_shorten (dir, 1); 02559 } 02560 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02561 { 02562 if (!_dbus_string_append_byte (dir, '/')) 02563 return FALSE; 02564 } 02565 02566 return _dbus_string_copy (next_component, 0, dir, 02567 _dbus_string_get_length (dir)); 02568 } 02569 02571 #define NANOSECONDS_PER_SECOND 1000000000 02572 02573 #define MICROSECONDS_PER_SECOND 1000000 02574 02575 #define MILLISECONDS_PER_SECOND 1000 02576 02577 #define NANOSECONDS_PER_MILLISECOND 1000000 02578 02579 #define MICROSECONDS_PER_MILLISECOND 1000 02580 02585 void 02586 _dbus_sleep_milliseconds (int milliseconds) 02587 { 02588 #ifdef HAVE_NANOSLEEP 02589 struct timespec req; 02590 struct timespec rem; 02591 02592 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02593 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02594 rem.tv_sec = 0; 02595 rem.tv_nsec = 0; 02596 02597 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02598 req = rem; 02599 #elif defined (HAVE_USLEEP) 02600 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02601 #else /* ! HAVE_USLEEP */ 02602 sleep (MAX (milliseconds / 1000, 1)); 02603 #endif 02604 } 02605 02606 static dbus_bool_t 02607 _dbus_generate_pseudorandom_bytes (DBusString *str, 02608 int n_bytes) 02609 { 02610 int old_len; 02611 char *p; 02612 02613 old_len = _dbus_string_get_length (str); 02614 02615 if (!_dbus_string_lengthen (str, n_bytes)) 02616 return FALSE; 02617 02618 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02619 02620 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02621 02622 return TRUE; 02623 } 02624 02633 dbus_bool_t 02634 _dbus_generate_random_bytes (DBusString *str, 02635 int n_bytes) 02636 { 02637 int old_len; 02638 int fd; 02639 02640 /* FALSE return means "no memory", if it could 02641 * mean something else then we'd need to return 02642 * a DBusError. So we always fall back to pseudorandom 02643 * if the I/O fails. 02644 */ 02645 02646 old_len = _dbus_string_get_length (str); 02647 fd = -1; 02648 02649 /* note, urandom on linux will fall back to pseudorandom */ 02650 fd = open ("/dev/urandom", O_RDONLY); 02651 if (fd < 0) 02652 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02653 02654 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02655 02656 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02657 { 02658 _dbus_close (fd, NULL); 02659 _dbus_string_set_length (str, old_len); 02660 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02661 } 02662 02663 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02664 n_bytes); 02665 02666 _dbus_close (fd, NULL); 02667 02668 return TRUE; 02669 } 02670 02676 void 02677 _dbus_exit (int code) 02678 { 02679 _exit (code); 02680 } 02681 02690 const char* 02691 _dbus_strerror (int error_number) 02692 { 02693 const char *msg; 02694 02695 msg = strerror (error_number); 02696 if (msg == NULL) 02697 msg = "unknown"; 02698 02699 return msg; 02700 } 02701 02705 void 02706 _dbus_disable_sigpipe (void) 02707 { 02708 signal (SIGPIPE, SIG_IGN); 02709 } 02710 02718 void 02719 _dbus_fd_set_close_on_exec (intptr_t fd) 02720 { 02721 int val; 02722 02723 val = fcntl (fd, F_GETFD, 0); 02724 02725 if (val < 0) 02726 return; 02727 02728 val |= FD_CLOEXEC; 02729 02730 fcntl (fd, F_SETFD, val); 02731 } 02732 02740 dbus_bool_t 02741 _dbus_close (int fd, 02742 DBusError *error) 02743 { 02744 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02745 02746 again: 02747 if (close (fd) < 0) 02748 { 02749 if (errno == EINTR) 02750 goto again; 02751 02752 dbus_set_error (error, _dbus_error_from_errno (errno), 02753 "Could not close fd %d", fd); 02754 return FALSE; 02755 } 02756 02757 return TRUE; 02758 } 02759 02767 int 02768 _dbus_dup(int fd, 02769 DBusError *error) 02770 { 02771 int new_fd; 02772 02773 #ifdef F_DUPFD_CLOEXEC 02774 dbus_bool_t cloexec_done; 02775 02776 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02777 cloexec_done = new_fd >= 0; 02778 02779 if (new_fd < 0 && errno == EINVAL) 02780 #endif 02781 { 02782 new_fd = fcntl(fd, F_DUPFD, 3); 02783 } 02784 02785 if (new_fd < 0) { 02786 02787 dbus_set_error (error, _dbus_error_from_errno (errno), 02788 "Could not duplicate fd %d", fd); 02789 return -1; 02790 } 02791 02792 #ifdef F_DUPFD_CLOEXEC 02793 if (!cloexec_done) 02794 #endif 02795 { 02796 _dbus_fd_set_close_on_exec(new_fd); 02797 } 02798 02799 return new_fd; 02800 } 02801 02809 dbus_bool_t 02810 _dbus_set_fd_nonblocking (int fd, 02811 DBusError *error) 02812 { 02813 int val; 02814 02815 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02816 02817 val = fcntl (fd, F_GETFL, 0); 02818 if (val < 0) 02819 { 02820 dbus_set_error (error, _dbus_error_from_errno (errno), 02821 "Failed to get flags from file descriptor %d: %s", 02822 fd, _dbus_strerror (errno)); 02823 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02824 _dbus_strerror (errno)); 02825 return FALSE; 02826 } 02827 02828 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02829 { 02830 dbus_set_error (error, _dbus_error_from_errno (errno), 02831 "Failed to set nonblocking flag of file descriptor %d: %s", 02832 fd, _dbus_strerror (errno)); 02833 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02834 fd, _dbus_strerror (errno)); 02835 02836 return FALSE; 02837 } 02838 02839 return TRUE; 02840 } 02841 02847 void 02848 _dbus_print_backtrace (void) 02849 { 02850 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02851 void *bt[500]; 02852 int bt_size; 02853 int i; 02854 char **syms; 02855 02856 bt_size = backtrace (bt, 500); 02857 02858 syms = backtrace_symbols (bt, bt_size); 02859 02860 i = 0; 02861 while (i < bt_size) 02862 { 02863 /* don't use dbus_warn since it can _dbus_abort() */ 02864 fprintf (stderr, " %s\n", syms[i]); 02865 ++i; 02866 } 02867 fflush (stderr); 02868 02869 free (syms); 02870 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02871 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02872 #else 02873 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02874 #endif 02875 } 02876 02894 dbus_bool_t 02895 _dbus_full_duplex_pipe (int *fd1, 02896 int *fd2, 02897 dbus_bool_t blocking, 02898 DBusError *error) 02899 { 02900 #ifdef HAVE_SOCKETPAIR 02901 int fds[2]; 02902 int retval; 02903 02904 #ifdef SOCK_CLOEXEC 02905 dbus_bool_t cloexec_done; 02906 02907 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 02908 cloexec_done = retval >= 0; 02909 02910 if (retval < 0 && errno == EINVAL) 02911 #endif 02912 { 02913 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 02914 } 02915 02916 if (retval < 0) 02917 { 02918 dbus_set_error (error, _dbus_error_from_errno (errno), 02919 "Could not create full-duplex pipe"); 02920 return FALSE; 02921 } 02922 02923 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02924 02925 #ifdef SOCK_CLOEXEC 02926 if (!cloexec_done) 02927 #endif 02928 { 02929 _dbus_fd_set_close_on_exec (fds[0]); 02930 _dbus_fd_set_close_on_exec (fds[1]); 02931 } 02932 02933 if (!blocking && 02934 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02935 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02936 { 02937 dbus_set_error (error, _dbus_error_from_errno (errno), 02938 "Could not set full-duplex pipe nonblocking"); 02939 02940 _dbus_close (fds[0], NULL); 02941 _dbus_close (fds[1], NULL); 02942 02943 return FALSE; 02944 } 02945 02946 *fd1 = fds[0]; 02947 *fd2 = fds[1]; 02948 02949 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 02950 *fd1, *fd2); 02951 02952 return TRUE; 02953 #else 02954 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 02955 dbus_set_error (error, DBUS_ERROR_FAILED, 02956 "_dbus_full_duplex_pipe() not implemented on this OS"); 02957 return FALSE; 02958 #endif 02959 } 02960 02969 int 02970 _dbus_printf_string_upper_bound (const char *format, 02971 va_list args) 02972 { 02973 char c; 02974 return vsnprintf (&c, 1, format, args); 02975 } 02976 02983 const char* 02984 _dbus_get_tmpdir(void) 02985 { 02986 static const char* tmpdir = NULL; 02987 02988 if (tmpdir == NULL) 02989 { 02990 /* TMPDIR is what glibc uses, then 02991 * glibc falls back to the P_tmpdir macro which 02992 * just expands to "/tmp" 02993 */ 02994 if (tmpdir == NULL) 02995 tmpdir = getenv("TMPDIR"); 02996 02997 /* These two env variables are probably 02998 * broken, but maybe some OS uses them? 02999 */ 03000 if (tmpdir == NULL) 03001 tmpdir = getenv("TMP"); 03002 if (tmpdir == NULL) 03003 tmpdir = getenv("TEMP"); 03004 03005 /* And this is the sane fallback. */ 03006 if (tmpdir == NULL) 03007 tmpdir = "/tmp"; 03008 } 03009 03010 _dbus_assert(tmpdir != NULL); 03011 03012 return tmpdir; 03013 } 03014 03034 static dbus_bool_t 03035 _read_subprocess_line_argv (const char *progpath, 03036 dbus_bool_t path_fallback, 03037 char * const *argv, 03038 DBusString *result, 03039 DBusError *error) 03040 { 03041 int result_pipe[2] = { -1, -1 }; 03042 int errors_pipe[2] = { -1, -1 }; 03043 pid_t pid; 03044 int ret; 03045 int status; 03046 int orig_len; 03047 int i; 03048 03049 dbus_bool_t retval; 03050 sigset_t new_set, old_set; 03051 03052 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03053 retval = FALSE; 03054 03055 /* We need to block any existing handlers for SIGCHLD temporarily; they 03056 * will cause waitpid() below to fail. 03057 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03058 */ 03059 sigemptyset (&new_set); 03060 sigaddset (&new_set, SIGCHLD); 03061 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03062 03063 orig_len = _dbus_string_get_length (result); 03064 03065 #define READ_END 0 03066 #define WRITE_END 1 03067 if (pipe (result_pipe) < 0) 03068 { 03069 dbus_set_error (error, _dbus_error_from_errno (errno), 03070 "Failed to create a pipe to call %s: %s", 03071 progpath, _dbus_strerror (errno)); 03072 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03073 progpath, _dbus_strerror (errno)); 03074 goto out; 03075 } 03076 if (pipe (errors_pipe) < 0) 03077 { 03078 dbus_set_error (error, _dbus_error_from_errno (errno), 03079 "Failed to create a pipe to call %s: %s", 03080 progpath, _dbus_strerror (errno)); 03081 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03082 progpath, _dbus_strerror (errno)); 03083 goto out; 03084 } 03085 03086 pid = fork (); 03087 if (pid < 0) 03088 { 03089 dbus_set_error (error, _dbus_error_from_errno (errno), 03090 "Failed to fork() to call %s: %s", 03091 progpath, _dbus_strerror (errno)); 03092 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03093 progpath, _dbus_strerror (errno)); 03094 goto out; 03095 } 03096 03097 if (pid == 0) 03098 { 03099 /* child process */ 03100 int maxfds; 03101 int fd; 03102 03103 fd = open ("/dev/null", O_RDWR); 03104 if (fd == -1) 03105 /* huh?! can't open /dev/null? */ 03106 _exit (1); 03107 03108 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03109 03110 /* set-up stdXXX */ 03111 close (result_pipe[READ_END]); 03112 close (errors_pipe[READ_END]); 03113 close (0); /* close stdin */ 03114 close (1); /* close stdout */ 03115 close (2); /* close stderr */ 03116 03117 if (dup2 (fd, 0) == -1) 03118 _exit (1); 03119 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03120 _exit (1); 03121 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03122 _exit (1); 03123 03124 maxfds = sysconf (_SC_OPEN_MAX); 03125 /* Pick something reasonable if for some reason sysconf 03126 * says unlimited. 03127 */ 03128 if (maxfds < 0) 03129 maxfds = 1024; 03130 /* close all inherited fds */ 03131 for (i = 3; i < maxfds; i++) 03132 close (i); 03133 03134 sigprocmask (SIG_SETMASK, &old_set, NULL); 03135 03136 /* If it looks fully-qualified, try execv first */ 03137 if (progpath[0] == '/') 03138 { 03139 execv (progpath, argv); 03140 /* Ok, that failed. Now if path_fallback is given, let's 03141 * try unqualified. This is mostly a hack to work 03142 * around systems which ship dbus-launch in /usr/bin 03143 * but everything else in /bin (because dbus-launch 03144 * depends on X11). 03145 */ 03146 if (path_fallback) 03147 /* We must have a slash, because we checked above */ 03148 execvp (strrchr (progpath, '/')+1, argv); 03149 } 03150 else 03151 execvp (progpath, argv); 03152 03153 /* still nothing, we failed */ 03154 _exit (1); 03155 } 03156 03157 /* parent process */ 03158 close (result_pipe[WRITE_END]); 03159 close (errors_pipe[WRITE_END]); 03160 result_pipe[WRITE_END] = -1; 03161 errors_pipe[WRITE_END] = -1; 03162 03163 ret = 0; 03164 do 03165 { 03166 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03167 } 03168 while (ret > 0); 03169 03170 /* reap the child process to avoid it lingering as zombie */ 03171 do 03172 { 03173 ret = waitpid (pid, &status, 0); 03174 } 03175 while (ret == -1 && errno == EINTR); 03176 03177 /* We succeeded if the process exited with status 0 and 03178 anything was read */ 03179 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03180 { 03181 /* The process ended with error */ 03182 DBusString error_message; 03183 _dbus_string_init (&error_message); 03184 ret = 0; 03185 do 03186 { 03187 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03188 } 03189 while (ret > 0); 03190 03191 _dbus_string_set_length (result, orig_len); 03192 if (_dbus_string_get_length (&error_message) > 0) 03193 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03194 "%s terminated abnormally with the following error: %s", 03195 progpath, _dbus_string_get_data (&error_message)); 03196 else 03197 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03198 "%s terminated abnormally without any error message", 03199 progpath); 03200 goto out; 03201 } 03202 03203 retval = TRUE; 03204 03205 out: 03206 sigprocmask (SIG_SETMASK, &old_set, NULL); 03207 03208 if (retval) 03209 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03210 else 03211 _DBUS_ASSERT_ERROR_IS_SET (error); 03212 03213 if (result_pipe[0] != -1) 03214 close (result_pipe[0]); 03215 if (result_pipe[1] != -1) 03216 close (result_pipe[1]); 03217 if (errors_pipe[0] != -1) 03218 close (errors_pipe[0]); 03219 if (errors_pipe[1] != -1) 03220 close (errors_pipe[1]); 03221 03222 return retval; 03223 } 03224 03236 dbus_bool_t 03237 _dbus_get_autolaunch_address (DBusString *address, 03238 DBusError *error) 03239 { 03240 static char *argv[6]; 03241 int i; 03242 DBusString uuid; 03243 dbus_bool_t retval; 03244 03245 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03246 retval = FALSE; 03247 03248 if (!_dbus_string_init (&uuid)) 03249 { 03250 _DBUS_SET_OOM (error); 03251 return FALSE; 03252 } 03253 03254 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03255 { 03256 _DBUS_SET_OOM (error); 03257 goto out; 03258 } 03259 03260 i = 0; 03261 argv[i] = "dbus-launch"; 03262 ++i; 03263 argv[i] = "--autolaunch"; 03264 ++i; 03265 argv[i] = _dbus_string_get_data (&uuid); 03266 ++i; 03267 argv[i] = "--binary-syntax"; 03268 ++i; 03269 argv[i] = "--close-stderr"; 03270 ++i; 03271 argv[i] = NULL; 03272 ++i; 03273 03274 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03275 03276 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03277 TRUE, 03278 argv, address, error); 03279 03280 out: 03281 _dbus_string_free (&uuid); 03282 return retval; 03283 } 03284 03303 dbus_bool_t 03304 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03305 dbus_bool_t create_if_not_found, 03306 DBusError *error) 03307 { 03308 DBusString filename; 03309 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03310 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03311 } 03312 03313 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03314 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03315 03335 dbus_bool_t 03336 _dbus_lookup_session_address (dbus_bool_t *supported, 03337 DBusString *address, 03338 DBusError *error) 03339 { 03340 /* On non-Mac Unix platforms, if the session address isn't already 03341 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03342 * fall back to the autolaunch: global default; see 03343 * init_session_address in dbus/dbus-bus.c. */ 03344 *supported = FALSE; 03345 return TRUE; 03346 } 03347 03365 dbus_bool_t 03366 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03367 { 03368 const char *xdg_data_home; 03369 const char *xdg_data_dirs; 03370 DBusString servicedir_path; 03371 03372 if (!_dbus_string_init (&servicedir_path)) 03373 return FALSE; 03374 03375 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03376 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03377 03378 if (xdg_data_dirs != NULL) 03379 { 03380 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03381 goto oom; 03382 03383 if (!_dbus_string_append (&servicedir_path, ":")) 03384 goto oom; 03385 } 03386 else 03387 { 03388 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03389 goto oom; 03390 } 03391 03392 /* 03393 * add configured datadir to defaults 03394 * this may be the same as an xdg dir 03395 * however the config parser should take 03396 * care of duplicates 03397 */ 03398 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) 03399 goto oom; 03400 03401 if (xdg_data_home != NULL) 03402 { 03403 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03404 goto oom; 03405 } 03406 else 03407 { 03408 const DBusString *homedir; 03409 DBusString local_share; 03410 03411 if (!_dbus_homedir_from_current_process (&homedir)) 03412 goto oom; 03413 03414 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03415 goto oom; 03416 03417 _dbus_string_init_const (&local_share, "/.local/share"); 03418 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03419 goto oom; 03420 } 03421 03422 if (!_dbus_split_paths_and_append (&servicedir_path, 03423 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03424 dirs)) 03425 goto oom; 03426 03427 _dbus_string_free (&servicedir_path); 03428 return TRUE; 03429 03430 oom: 03431 _dbus_string_free (&servicedir_path); 03432 return FALSE; 03433 } 03434 03435 03454 dbus_bool_t 03455 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03456 { 03457 const char *xdg_data_dirs; 03458 DBusString servicedir_path; 03459 03460 if (!_dbus_string_init (&servicedir_path)) 03461 return FALSE; 03462 03463 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03464 03465 if (xdg_data_dirs != NULL) 03466 { 03467 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03468 goto oom; 03469 03470 if (!_dbus_string_append (&servicedir_path, ":")) 03471 goto oom; 03472 } 03473 else 03474 { 03475 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03476 goto oom; 03477 } 03478 03479 /* 03480 * add configured datadir to defaults 03481 * this may be the same as an xdg dir 03482 * however the config parser should take 03483 * care of duplicates 03484 */ 03485 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) 03486 goto oom; 03487 03488 if (!_dbus_split_paths_and_append (&servicedir_path, 03489 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03490 dirs)) 03491 goto oom; 03492 03493 _dbus_string_free (&servicedir_path); 03494 return TRUE; 03495 03496 oom: 03497 _dbus_string_free (&servicedir_path); 03498 return FALSE; 03499 } 03500 03509 dbus_bool_t 03510 _dbus_append_system_config_file (DBusString *str) 03511 { 03512 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03513 } 03514 03521 dbus_bool_t 03522 _dbus_append_session_config_file (DBusString *str) 03523 { 03524 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03525 } 03526 03534 void 03535 _dbus_flush_caches (void) 03536 { 03537 _dbus_user_database_flush_system (); 03538 } 03539 03553 dbus_bool_t 03554 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03555 DBusCredentials *credentials) 03556 { 03557 DBusString homedir; 03558 DBusString dotdir; 03559 dbus_uid_t uid; 03560 03561 _dbus_assert (credentials != NULL); 03562 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03563 03564 if (!_dbus_string_init (&homedir)) 03565 return FALSE; 03566 03567 uid = _dbus_credentials_get_unix_uid (credentials); 03568 _dbus_assert (uid != DBUS_UID_UNSET); 03569 03570 if (!_dbus_homedir_from_uid (uid, &homedir)) 03571 goto failed; 03572 03573 #ifdef DBUS_BUILD_TESTS 03574 { 03575 const char *override; 03576 03577 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03578 if (override != NULL && *override != '\0') 03579 { 03580 _dbus_string_set_length (&homedir, 0); 03581 if (!_dbus_string_append (&homedir, override)) 03582 goto failed; 03583 03584 _dbus_verbose ("Using fake homedir for testing: %s\n", 03585 _dbus_string_get_const_data (&homedir)); 03586 } 03587 else 03588 { 03589 static dbus_bool_t already_warned = FALSE; 03590 if (!already_warned) 03591 { 03592 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03593 already_warned = TRUE; 03594 } 03595 } 03596 } 03597 #endif 03598 03599 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03600 if (!_dbus_concat_dir_and_file (&homedir, 03601 &dotdir)) 03602 goto failed; 03603 03604 if (!_dbus_string_copy (&homedir, 0, 03605 directory, _dbus_string_get_length (directory))) { 03606 goto failed; 03607 } 03608 03609 _dbus_string_free (&homedir); 03610 return TRUE; 03611 03612 failed: 03613 _dbus_string_free (&homedir); 03614 return FALSE; 03615 } 03616 03617 //PENDING(kdab) docs 03618 void 03619 _dbus_daemon_publish_session_bus_address (const char* addr) 03620 { 03621 03622 } 03623 03624 //PENDING(kdab) docs 03625 void 03626 _dbus_daemon_unpublish_session_bus_address (void) 03627 { 03628 03629 } 03630 03637 dbus_bool_t 03638 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03639 { 03640 return errno == EAGAIN || errno == EWOULDBLOCK; 03641 } 03642 03650 dbus_bool_t 03651 _dbus_delete_directory (const DBusString *filename, 03652 DBusError *error) 03653 { 03654 const char *filename_c; 03655 03656 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03657 03658 filename_c = _dbus_string_get_const_data (filename); 03659 03660 if (rmdir (filename_c) != 0) 03661 { 03662 dbus_set_error (error, DBUS_ERROR_FAILED, 03663 "Failed to remove directory %s: %s\n", 03664 filename_c, _dbus_strerror (errno)); 03665 return FALSE; 03666 } 03667 03668 return TRUE; 03669 } 03670 03678 dbus_bool_t 03679 _dbus_socket_can_pass_unix_fd(int fd) { 03680 03681 #ifdef SCM_RIGHTS 03682 union { 03683 struct sockaddr sa; 03684 struct sockaddr_storage storage; 03685 struct sockaddr_un un; 03686 } sa_buf; 03687 03688 socklen_t sa_len = sizeof(sa_buf); 03689 03690 _DBUS_ZERO(sa_buf); 03691 03692 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03693 return FALSE; 03694 03695 return sa_buf.sa.sa_family == AF_UNIX; 03696 03697 #else 03698 return FALSE; 03699 03700 #endif 03701 } 03702 03703 03704 /* 03705 * replaces the term DBUS_PREFIX in configure_time_path by the 03706 * current dbus installation directory. On unix this function is a noop 03707 * 03708 * @param configure_time_path 03709 * @return real path 03710 */ 03711 const char * 03712 _dbus_replace_install_prefix (const char *configure_time_path) 03713 { 03714 return configure_time_path; 03715 } 03716 03717 /* tests in dbus-sysdeps-util.c */