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