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 again: 00323 00324 bytes_read = recvmsg(fd, &m, 0 00325 #ifdef MSG_CMSG_CLOEXEC 00326 |MSG_CMSG_CLOEXEC 00327 #endif 00328 ); 00329 00330 if (bytes_read < 0) 00331 { 00332 if (errno == EINTR) 00333 goto again; 00334 else 00335 { 00336 /* put length back (note that this doesn't actually realloc anything) */ 00337 _dbus_string_set_length (buffer, start); 00338 return -1; 00339 } 00340 } 00341 else 00342 { 00343 struct cmsghdr *cm; 00344 dbus_bool_t found = FALSE; 00345 00346 if (m.msg_flags & MSG_CTRUNC) 00347 { 00348 /* Hmm, apparently the control data was truncated. The bad 00349 thing is that we might have completely lost a couple of fds 00350 without chance to recover them. Hence let's treat this as a 00351 serious error. */ 00352 00353 errno = ENOSPC; 00354 _dbus_string_set_length (buffer, start); 00355 return -1; 00356 } 00357 00358 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) 00359 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) 00360 { 00361 unsigned i; 00362 00363 _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int))); 00364 *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int); 00365 00366 memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int)); 00367 found = TRUE; 00368 00369 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually 00370 worked, hence we need to go through this list and set 00371 CLOEXEC everywhere in any case */ 00372 for (i = 0; i < *n_fds; i++) 00373 _dbus_fd_set_close_on_exec(fds[i]); 00374 00375 break; 00376 } 00377 00378 if (!found) 00379 *n_fds = 0; 00380 00381 /* put length back (doesn't actually realloc) */ 00382 _dbus_string_set_length (buffer, start + bytes_read); 00383 00384 #if 0 00385 if (bytes_read > 0) 00386 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00387 #endif 00388 00389 return bytes_read; 00390 } 00391 #endif 00392 } 00393 00394 int 00395 _dbus_write_socket_with_unix_fds(int fd, 00396 const DBusString *buffer, 00397 int start, 00398 int len, 00399 const int *fds, 00400 int n_fds) { 00401 00402 #ifndef HAVE_UNIX_FD_PASSING 00403 00404 if (n_fds > 0) { 00405 errno = ENOTSUP; 00406 return -1; 00407 } 00408 00409 return _dbus_write_socket(fd, buffer, start, len); 00410 #else 00411 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds); 00412 #endif 00413 } 00414 00415 int 00416 _dbus_write_socket_with_unix_fds_two(int fd, 00417 const DBusString *buffer1, 00418 int start1, 00419 int len1, 00420 const DBusString *buffer2, 00421 int start2, 00422 int len2, 00423 const int *fds, 00424 int n_fds) { 00425 00426 #ifndef HAVE_UNIX_FD_PASSING 00427 00428 if (n_fds > 0) { 00429 errno = ENOTSUP; 00430 return -1; 00431 } 00432 00433 return _dbus_write_socket_two(fd, 00434 buffer1, start1, len1, 00435 buffer2, start2, len2); 00436 #else 00437 00438 struct msghdr m; 00439 struct cmsghdr *cm; 00440 struct iovec iov[2]; 00441 int bytes_written; 00442 00443 _dbus_assert (len1 >= 0); 00444 _dbus_assert (len2 >= 0); 00445 _dbus_assert (n_fds >= 0); 00446 00447 _DBUS_ZERO(iov); 00448 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1); 00449 iov[0].iov_len = len1; 00450 00451 if (buffer2) 00452 { 00453 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2); 00454 iov[1].iov_len = len2; 00455 } 00456 00457 _DBUS_ZERO(m); 00458 m.msg_iov = iov; 00459 m.msg_iovlen = buffer2 ? 2 : 1; 00460 00461 if (n_fds > 0) 00462 { 00463 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int)); 00464 m.msg_control = alloca(m.msg_controllen); 00465 memset(m.msg_control, 0, m.msg_controllen); 00466 00467 cm = CMSG_FIRSTHDR(&m); 00468 cm->cmsg_level = SOL_SOCKET; 00469 cm->cmsg_type = SCM_RIGHTS; 00470 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int)); 00471 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int)); 00472 } 00473 00474 again: 00475 00476 bytes_written = sendmsg (fd, &m, 0 00477 #if HAVE_DECL_MSG_NOSIGNAL 00478 |MSG_NOSIGNAL 00479 #endif 00480 ); 00481 00482 if (bytes_written < 0 && errno == EINTR) 00483 goto again; 00484 00485 #if 0 00486 if (bytes_written > 0) 00487 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00488 #endif 00489 00490 return bytes_written; 00491 #endif 00492 } 00493 00507 int 00508 _dbus_write_socket_two (int fd, 00509 const DBusString *buffer1, 00510 int start1, 00511 int len1, 00512 const DBusString *buffer2, 00513 int start2, 00514 int len2) 00515 { 00516 #if HAVE_DECL_MSG_NOSIGNAL 00517 struct iovec vectors[2]; 00518 const char *data1; 00519 const char *data2; 00520 int bytes_written; 00521 struct msghdr m; 00522 00523 _dbus_assert (buffer1 != NULL); 00524 _dbus_assert (start1 >= 0); 00525 _dbus_assert (start2 >= 0); 00526 _dbus_assert (len1 >= 0); 00527 _dbus_assert (len2 >= 0); 00528 00529 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00530 00531 if (buffer2 != NULL) 00532 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00533 else 00534 { 00535 data2 = NULL; 00536 start2 = 0; 00537 len2 = 0; 00538 } 00539 00540 vectors[0].iov_base = (char*) data1; 00541 vectors[0].iov_len = len1; 00542 vectors[1].iov_base = (char*) data2; 00543 vectors[1].iov_len = len2; 00544 00545 _DBUS_ZERO(m); 00546 m.msg_iov = vectors; 00547 m.msg_iovlen = data2 ? 2 : 1; 00548 00549 again: 00550 00551 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL); 00552 00553 if (bytes_written < 0 && errno == EINTR) 00554 goto again; 00555 00556 return bytes_written; 00557 00558 #else 00559 return _dbus_write_two (fd, buffer1, start1, len1, 00560 buffer2, start2, len2); 00561 #endif 00562 } 00563 00564 dbus_bool_t 00565 _dbus_socket_is_invalid (int fd) 00566 { 00567 return fd < 0 ? TRUE : FALSE; 00568 } 00569 00586 int 00587 _dbus_read (int fd, 00588 DBusString *buffer, 00589 int count) 00590 { 00591 int bytes_read; 00592 int start; 00593 char *data; 00594 00595 _dbus_assert (count >= 0); 00596 00597 start = _dbus_string_get_length (buffer); 00598 00599 if (!_dbus_string_lengthen (buffer, count)) 00600 { 00601 errno = ENOMEM; 00602 return -1; 00603 } 00604 00605 data = _dbus_string_get_data_len (buffer, start, count); 00606 00607 again: 00608 00609 bytes_read = read (fd, data, count); 00610 00611 if (bytes_read < 0) 00612 { 00613 if (errno == EINTR) 00614 goto again; 00615 else 00616 { 00617 /* put length back (note that this doesn't actually realloc anything) */ 00618 _dbus_string_set_length (buffer, start); 00619 return -1; 00620 } 00621 } 00622 else 00623 { 00624 /* put length back (doesn't actually realloc) */ 00625 _dbus_string_set_length (buffer, start + bytes_read); 00626 00627 #if 0 00628 if (bytes_read > 0) 00629 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00630 #endif 00631 00632 return bytes_read; 00633 } 00634 } 00635 00646 int 00647 _dbus_write (int fd, 00648 const DBusString *buffer, 00649 int start, 00650 int len) 00651 { 00652 const char *data; 00653 int bytes_written; 00654 00655 data = _dbus_string_get_const_data_len (buffer, start, len); 00656 00657 again: 00658 00659 bytes_written = write (fd, data, len); 00660 00661 if (bytes_written < 0 && errno == EINTR) 00662 goto again; 00663 00664 #if 0 00665 if (bytes_written > 0) 00666 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00667 #endif 00668 00669 return bytes_written; 00670 } 00671 00692 int 00693 _dbus_write_two (int fd, 00694 const DBusString *buffer1, 00695 int start1, 00696 int len1, 00697 const DBusString *buffer2, 00698 int start2, 00699 int len2) 00700 { 00701 _dbus_assert (buffer1 != NULL); 00702 _dbus_assert (start1 >= 0); 00703 _dbus_assert (start2 >= 0); 00704 _dbus_assert (len1 >= 0); 00705 _dbus_assert (len2 >= 0); 00706 00707 #ifdef HAVE_WRITEV 00708 { 00709 struct iovec vectors[2]; 00710 const char *data1; 00711 const char *data2; 00712 int bytes_written; 00713 00714 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00715 00716 if (buffer2 != NULL) 00717 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00718 else 00719 { 00720 data2 = NULL; 00721 start2 = 0; 00722 len2 = 0; 00723 } 00724 00725 vectors[0].iov_base = (char*) data1; 00726 vectors[0].iov_len = len1; 00727 vectors[1].iov_base = (char*) data2; 00728 vectors[1].iov_len = len2; 00729 00730 again: 00731 00732 bytes_written = writev (fd, 00733 vectors, 00734 data2 ? 2 : 1); 00735 00736 if (bytes_written < 0 && errno == EINTR) 00737 goto again; 00738 00739 return bytes_written; 00740 } 00741 #else /* HAVE_WRITEV */ 00742 { 00743 int ret1; 00744 00745 ret1 = _dbus_write (fd, buffer1, start1, len1); 00746 if (ret1 == len1 && buffer2 != NULL) 00747 { 00748 ret2 = _dbus_write (fd, buffer2, start2, len2); 00749 if (ret2 < 0) 00750 ret2 = 0; /* we can't report an error as the first write was OK */ 00751 00752 return ret1 + ret2; 00753 } 00754 else 00755 return ret1; 00756 } 00757 #endif /* !HAVE_WRITEV */ 00758 } 00759 00760 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00761 00791 int 00792 _dbus_connect_unix_socket (const char *path, 00793 dbus_bool_t abstract, 00794 DBusError *error) 00795 { 00796 int fd; 00797 size_t path_len; 00798 struct sockaddr_un addr; 00799 00800 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00801 00802 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00803 path, abstract); 00804 00805 00806 if (!_dbus_open_unix_socket (&fd, error)) 00807 { 00808 _DBUS_ASSERT_ERROR_IS_SET(error); 00809 return -1; 00810 } 00811 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00812 00813 _DBUS_ZERO (addr); 00814 addr.sun_family = AF_UNIX; 00815 path_len = strlen (path); 00816 00817 if (abstract) 00818 { 00819 #ifdef HAVE_ABSTRACT_SOCKETS 00820 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00821 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00822 00823 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00824 { 00825 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00826 "Abstract socket name too long\n"); 00827 _dbus_close (fd, NULL); 00828 return -1; 00829 } 00830 00831 strncpy (&addr.sun_path[1], path, path_len); 00832 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00833 #else /* HAVE_ABSTRACT_SOCKETS */ 00834 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00835 "Operating system does not support abstract socket namespace\n"); 00836 _dbus_close (fd, NULL); 00837 return -1; 00838 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00839 } 00840 else 00841 { 00842 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00843 { 00844 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00845 "Socket name too long\n"); 00846 _dbus_close (fd, NULL); 00847 return -1; 00848 } 00849 00850 strncpy (addr.sun_path, path, path_len); 00851 } 00852 00853 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00854 { 00855 dbus_set_error (error, 00856 _dbus_error_from_errno (errno), 00857 "Failed to connect to socket %s: %s", 00858 path, _dbus_strerror (errno)); 00859 00860 _dbus_close (fd, NULL); 00861 return -1; 00862 } 00863 00864 if (!_dbus_set_fd_nonblocking (fd, error)) 00865 { 00866 _DBUS_ASSERT_ERROR_IS_SET (error); 00867 00868 _dbus_close (fd, NULL); 00869 return -1; 00870 } 00871 00872 return fd; 00873 } 00874 00884 static dbus_bool_t 00885 _dbus_set_local_creds (int fd, dbus_bool_t on) 00886 { 00887 dbus_bool_t retval = TRUE; 00888 00889 #if defined(HAVE_CMSGCRED) 00890 /* NOOP just to make sure only one codepath is used 00891 * and to prefer CMSGCRED 00892 */ 00893 #elif defined(LOCAL_CREDS) 00894 int val = on ? 1 : 0; 00895 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) 00896 { 00897 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); 00898 retval = FALSE; 00899 } 00900 else 00901 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", 00902 on ? "enabled" : "disabled", fd); 00903 #endif 00904 00905 return retval; 00906 } 00907 00925 int 00926 _dbus_listen_unix_socket (const char *path, 00927 dbus_bool_t abstract, 00928 DBusError *error) 00929 { 00930 int listen_fd; 00931 struct sockaddr_un addr; 00932 size_t path_len; 00933 unsigned int reuseaddr; 00934 00935 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00936 00937 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 00938 path, abstract); 00939 00940 if (!_dbus_open_unix_socket (&listen_fd, error)) 00941 { 00942 _DBUS_ASSERT_ERROR_IS_SET(error); 00943 return -1; 00944 } 00945 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00946 00947 _DBUS_ZERO (addr); 00948 addr.sun_family = AF_UNIX; 00949 path_len = strlen (path); 00950 00951 if (abstract) 00952 { 00953 #ifdef HAVE_ABSTRACT_SOCKETS 00954 /* remember that abstract names aren't nul-terminated so we rely 00955 * on sun_path being filled in with zeroes above. 00956 */ 00957 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00958 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00959 00960 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00961 { 00962 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00963 "Abstract socket name too long\n"); 00964 _dbus_close (listen_fd, NULL); 00965 return -1; 00966 } 00967 00968 strncpy (&addr.sun_path[1], path, path_len); 00969 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00970 #else /* HAVE_ABSTRACT_SOCKETS */ 00971 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00972 "Operating system does not support abstract socket namespace\n"); 00973 _dbus_close (listen_fd, NULL); 00974 return -1; 00975 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00976 } 00977 else 00978 { 00979 /* Discussed security implications of this with Nalin, 00980 * and we couldn't think of where it would kick our ass, but 00981 * it still seems a bit sucky. It also has non-security suckage; 00982 * really we'd prefer to exit if the socket is already in use. 00983 * But there doesn't seem to be a good way to do this. 00984 * 00985 * Just to be extra careful, I threw in the stat() - clearly 00986 * the stat() can't *fix* any security issue, but it at least 00987 * avoids inadvertent/accidental data loss. 00988 */ 00989 { 00990 struct stat sb; 00991 00992 if (stat (path, &sb) == 0 && 00993 S_ISSOCK (sb.st_mode)) 00994 unlink (path); 00995 } 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, path, path_len); 01006 } 01007 01008 reuseaddr = 1; 01009 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01010 { 01011 _dbus_warn ("Failed to set socket option\"%s\": %s", 01012 path, _dbus_strerror (errno)); 01013 } 01014 01015 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 01016 { 01017 dbus_set_error (error, _dbus_error_from_errno (errno), 01018 "Failed to bind socket \"%s\": %s", 01019 path, _dbus_strerror (errno)); 01020 _dbus_close (listen_fd, NULL); 01021 return -1; 01022 } 01023 01024 if (listen (listen_fd, 30 /* backlog */) < 0) 01025 { 01026 dbus_set_error (error, _dbus_error_from_errno (errno), 01027 "Failed to listen on socket \"%s\": %s", 01028 path, _dbus_strerror (errno)); 01029 _dbus_close (listen_fd, NULL); 01030 return -1; 01031 } 01032 01033 if (!_dbus_set_local_creds (listen_fd, TRUE)) 01034 { 01035 dbus_set_error (error, _dbus_error_from_errno (errno), 01036 "Failed to enable LOCAL_CREDS on socket \"%s\": %s", 01037 path, _dbus_strerror (errno)); 01038 close (listen_fd); 01039 return -1; 01040 } 01041 01042 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01043 { 01044 _DBUS_ASSERT_ERROR_IS_SET (error); 01045 _dbus_close (listen_fd, NULL); 01046 return -1; 01047 } 01048 01049 /* Try opening up the permissions, but if we can't, just go ahead 01050 * and continue, maybe it will be good enough. 01051 */ 01052 if (!abstract && chmod (path, 0777) < 0) 01053 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01054 path); 01055 01056 return listen_fd; 01057 } 01058 01069 int 01070 _dbus_listen_systemd_sockets (int **fds, 01071 DBusError *error) 01072 { 01073 int r, n; 01074 unsigned fd; 01075 int *new_fds; 01076 01077 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01078 01079 n = sd_listen_fds (TRUE); 01080 if (n < 0) 01081 { 01082 dbus_set_error (error, _dbus_error_from_errno (-n), 01083 "Failed to acquire systemd socket: %s", 01084 _dbus_strerror (-n)); 01085 return -1; 01086 } 01087 01088 if (n <= 0) 01089 { 01090 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01091 "No socket received."); 01092 return -1; 01093 } 01094 01095 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01096 { 01097 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01098 if (r < 0) 01099 { 01100 dbus_set_error (error, _dbus_error_from_errno (-r), 01101 "Failed to verify systemd socket type: %s", 01102 _dbus_strerror (-r)); 01103 return -1; 01104 } 01105 01106 if (!r) 01107 { 01108 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01109 "Passed socket has wrong type."); 01110 return -1; 01111 } 01112 } 01113 01114 /* OK, the file descriptors are all good, so let's take posession of 01115 them then. */ 01116 01117 new_fds = dbus_new (int, n); 01118 if (!new_fds) 01119 { 01120 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01121 "Failed to allocate file handle array."); 01122 goto fail; 01123 } 01124 01125 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01126 { 01127 if (!_dbus_set_local_creds (fd, TRUE)) 01128 { 01129 dbus_set_error (error, _dbus_error_from_errno (errno), 01130 "Failed to enable LOCAL_CREDS on systemd socket: %s", 01131 _dbus_strerror (errno)); 01132 goto fail; 01133 } 01134 01135 if (!_dbus_set_fd_nonblocking (fd, error)) 01136 { 01137 _DBUS_ASSERT_ERROR_IS_SET (error); 01138 goto fail; 01139 } 01140 01141 new_fds[fd - SD_LISTEN_FDS_START] = fd; 01142 } 01143 01144 *fds = new_fds; 01145 return n; 01146 01147 fail: 01148 01149 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01150 { 01151 _dbus_close (fd, NULL); 01152 } 01153 01154 dbus_free (new_fds); 01155 return -1; 01156 } 01157 01171 int 01172 _dbus_connect_tcp_socket (const char *host, 01173 const char *port, 01174 const char *family, 01175 DBusError *error) 01176 { 01177 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01178 } 01179 01180 int 01181 _dbus_connect_tcp_socket_with_nonce (const char *host, 01182 const char *port, 01183 const char *family, 01184 const char *noncefile, 01185 DBusError *error) 01186 { 01187 int saved_errno = 0; 01188 int fd = -1, res; 01189 struct addrinfo hints; 01190 struct addrinfo *ai, *tmp; 01191 01192 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01193 01194 _DBUS_ZERO (hints); 01195 01196 if (!family) 01197 hints.ai_family = AF_UNSPEC; 01198 else if (!strcmp(family, "ipv4")) 01199 hints.ai_family = AF_INET; 01200 else if (!strcmp(family, "ipv6")) 01201 hints.ai_family = AF_INET6; 01202 else 01203 { 01204 dbus_set_error (error, 01205 DBUS_ERROR_BAD_ADDRESS, 01206 "Unknown address family %s", family); 01207 return -1; 01208 } 01209 hints.ai_protocol = IPPROTO_TCP; 01210 hints.ai_socktype = SOCK_STREAM; 01211 hints.ai_flags = AI_ADDRCONFIG; 01212 01213 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01214 { 01215 dbus_set_error (error, 01216 _dbus_error_from_errno (errno), 01217 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01218 host, port, gai_strerror(res), res); 01219 return -1; 01220 } 01221 01222 tmp = ai; 01223 while (tmp) 01224 { 01225 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01226 { 01227 freeaddrinfo(ai); 01228 _DBUS_ASSERT_ERROR_IS_SET(error); 01229 return -1; 01230 } 01231 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01232 01233 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01234 { 01235 saved_errno = errno; 01236 _dbus_close(fd, NULL); 01237 fd = -1; 01238 tmp = tmp->ai_next; 01239 continue; 01240 } 01241 01242 break; 01243 } 01244 freeaddrinfo(ai); 01245 01246 if (fd == -1) 01247 { 01248 dbus_set_error (error, 01249 _dbus_error_from_errno (saved_errno), 01250 "Failed to connect to socket \"%s:%s\" %s", 01251 host, port, _dbus_strerror(saved_errno)); 01252 return -1; 01253 } 01254 01255 if (noncefile != NULL) 01256 { 01257 DBusString noncefileStr; 01258 dbus_bool_t ret; 01259 _dbus_string_init_const (&noncefileStr, noncefile); 01260 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01261 _dbus_string_free (&noncefileStr); 01262 01263 if (!ret) 01264 { 01265 _dbus_close (fd, NULL); 01266 return -1; 01267 } 01268 } 01269 01270 if (!_dbus_set_fd_nonblocking (fd, error)) 01271 { 01272 _dbus_close (fd, NULL); 01273 return -1; 01274 } 01275 01276 return fd; 01277 } 01278 01295 int 01296 _dbus_listen_tcp_socket (const char *host, 01297 const char *port, 01298 const char *family, 01299 DBusString *retport, 01300 int **fds_p, 01301 DBusError *error) 01302 { 01303 int saved_errno; 01304 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01305 struct addrinfo hints; 01306 struct addrinfo *ai, *tmp; 01307 unsigned int reuseaddr; 01308 01309 *fds_p = NULL; 01310 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01311 01312 _DBUS_ZERO (hints); 01313 01314 if (!family) 01315 hints.ai_family = AF_UNSPEC; 01316 else if (!strcmp(family, "ipv4")) 01317 hints.ai_family = AF_INET; 01318 else if (!strcmp(family, "ipv6")) 01319 hints.ai_family = AF_INET6; 01320 else 01321 { 01322 dbus_set_error (error, 01323 DBUS_ERROR_BAD_ADDRESS, 01324 "Unknown address family %s", family); 01325 return -1; 01326 } 01327 01328 hints.ai_protocol = IPPROTO_TCP; 01329 hints.ai_socktype = SOCK_STREAM; 01330 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01331 01332 redo_lookup_with_port: 01333 ai = NULL; 01334 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01335 { 01336 dbus_set_error (error, 01337 _dbus_error_from_errno (errno), 01338 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01339 host ? host : "*", port, gai_strerror(res), res); 01340 goto failed; 01341 } 01342 01343 tmp = ai; 01344 while (tmp) 01345 { 01346 int fd = -1, *newlisten_fd; 01347 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01348 { 01349 _DBUS_ASSERT_ERROR_IS_SET(error); 01350 goto failed; 01351 } 01352 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01353 01354 reuseaddr = 1; 01355 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01356 { 01357 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01358 host ? host : "*", port, _dbus_strerror (errno)); 01359 } 01360 01361 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01362 { 01363 saved_errno = errno; 01364 _dbus_close(fd, NULL); 01365 if (saved_errno == EADDRINUSE) 01366 { 01367 /* Depending on kernel policy, it may or may not 01368 be neccessary to bind to both IPv4 & 6 addresses 01369 so ignore EADDRINUSE here */ 01370 tmp = tmp->ai_next; 01371 continue; 01372 } 01373 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01374 "Failed to bind socket \"%s:%s\": %s", 01375 host ? host : "*", port, _dbus_strerror (saved_errno)); 01376 goto failed; 01377 } 01378 01379 if (listen (fd, 30 /* backlog */) < 0) 01380 { 01381 saved_errno = errno; 01382 _dbus_close (fd, NULL); 01383 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01384 "Failed to listen on socket \"%s:%s\": %s", 01385 host ? host : "*", port, _dbus_strerror (saved_errno)); 01386 goto failed; 01387 } 01388 01389 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01390 if (!newlisten_fd) 01391 { 01392 saved_errno = errno; 01393 _dbus_close (fd, NULL); 01394 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01395 "Failed to allocate file handle array: %s", 01396 _dbus_strerror (saved_errno)); 01397 goto failed; 01398 } 01399 listen_fd = newlisten_fd; 01400 listen_fd[nlisten_fd] = fd; 01401 nlisten_fd++; 01402 01403 if (!_dbus_string_get_length(retport)) 01404 { 01405 /* If the user didn't specify a port, or used 0, then 01406 the kernel chooses a port. After the first address 01407 is bound to, we need to force all remaining addresses 01408 to use the same port */ 01409 if (!port || !strcmp(port, "0")) 01410 { 01411 int result; 01412 struct sockaddr_storage addr; 01413 socklen_t addrlen; 01414 char portbuf[50]; 01415 01416 addrlen = sizeof(addr); 01417 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01418 01419 if (result == -1 || 01420 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0, 01421 portbuf, sizeof(portbuf), 01422 NI_NUMERICHOST)) != 0) 01423 { 01424 dbus_set_error (error, _dbus_error_from_errno (errno), 01425 "Failed to resolve port \"%s:%s\": %s (%s)", 01426 host ? host : "*", port, gai_strerror(res), res); 01427 goto failed; 01428 } 01429 if (!_dbus_string_append(retport, portbuf)) 01430 { 01431 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01432 goto failed; 01433 } 01434 01435 /* Release current address list & redo lookup */ 01436 port = _dbus_string_get_const_data(retport); 01437 freeaddrinfo(ai); 01438 goto redo_lookup_with_port; 01439 } 01440 else 01441 { 01442 if (!_dbus_string_append(retport, port)) 01443 { 01444 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01445 goto failed; 01446 } 01447 } 01448 } 01449 01450 tmp = tmp->ai_next; 01451 } 01452 freeaddrinfo(ai); 01453 ai = NULL; 01454 01455 if (!nlisten_fd) 01456 { 01457 errno = EADDRINUSE; 01458 dbus_set_error (error, _dbus_error_from_errno (errno), 01459 "Failed to bind socket \"%s:%s\": %s", 01460 host ? host : "*", port, _dbus_strerror (errno)); 01461 goto failed; 01462 } 01463 01464 for (i = 0 ; i < nlisten_fd ; i++) 01465 { 01466 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01467 { 01468 goto failed; 01469 } 01470 } 01471 01472 *fds_p = listen_fd; 01473 01474 return nlisten_fd; 01475 01476 failed: 01477 if (ai) 01478 freeaddrinfo(ai); 01479 for (i = 0 ; i < nlisten_fd ; i++) 01480 _dbus_close(listen_fd[i], NULL); 01481 dbus_free(listen_fd); 01482 return -1; 01483 } 01484 01485 static dbus_bool_t 01486 write_credentials_byte (int server_fd, 01487 DBusError *error) 01488 { 01489 int bytes_written; 01490 char buf[1] = { '\0' }; 01491 #if defined(HAVE_CMSGCRED) 01492 union { 01493 struct cmsghdr hdr; 01494 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01495 } cmsg; 01496 struct iovec iov; 01497 struct msghdr msg; 01498 iov.iov_base = buf; 01499 iov.iov_len = 1; 01500 01501 _DBUS_ZERO(msg); 01502 msg.msg_iov = &iov; 01503 msg.msg_iovlen = 1; 01504 01505 msg.msg_control = (caddr_t) &cmsg; 01506 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01507 _DBUS_ZERO(cmsg); 01508 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01509 cmsg.hdr.cmsg_level = SOL_SOCKET; 01510 cmsg.hdr.cmsg_type = SCM_CREDS; 01511 #endif 01512 01513 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01514 01515 again: 01516 01517 #if defined(HAVE_CMSGCRED) 01518 bytes_written = sendmsg (server_fd, &msg, 0 01519 #if HAVE_DECL_MSG_NOSIGNAL 01520 |MSG_NOSIGNAL 01521 #endif 01522 ); 01523 #else 01524 bytes_written = send (server_fd, buf, 1, 0 01525 #if HAVE_DECL_MSG_NOSIGNAL 01526 |MSG_NOSIGNAL 01527 #endif 01528 ); 01529 #endif 01530 01531 if (bytes_written < 0 && errno == EINTR) 01532 goto again; 01533 01534 if (bytes_written < 0) 01535 { 01536 dbus_set_error (error, _dbus_error_from_errno (errno), 01537 "Failed to write credentials byte: %s", 01538 _dbus_strerror (errno)); 01539 return FALSE; 01540 } 01541 else if (bytes_written == 0) 01542 { 01543 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01544 "wrote zero bytes writing credentials byte"); 01545 return FALSE; 01546 } 01547 else 01548 { 01549 _dbus_assert (bytes_written == 1); 01550 _dbus_verbose ("wrote credentials byte\n"); 01551 return TRUE; 01552 } 01553 } 01554 01576 dbus_bool_t 01577 _dbus_read_credentials_socket (int client_fd, 01578 DBusCredentials *credentials, 01579 DBusError *error) 01580 { 01581 struct msghdr msg; 01582 struct iovec iov; 01583 char buf; 01584 dbus_uid_t uid_read; 01585 dbus_pid_t pid_read; 01586 int bytes_read; 01587 01588 #ifdef HAVE_CMSGCRED 01589 union { 01590 struct cmsghdr hdr; 01591 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01592 } cmsg; 01593 01594 #elif defined(LOCAL_CREDS) 01595 struct { 01596 struct cmsghdr hdr; 01597 struct sockcred cred; 01598 } cmsg; 01599 #endif 01600 01601 uid_read = DBUS_UID_UNSET; 01602 pid_read = DBUS_PID_UNSET; 01603 01604 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01605 01606 /* The POSIX spec certainly doesn't promise this, but 01607 * we need these assertions to fail as soon as we're wrong about 01608 * it so we can do the porting fixups 01609 */ 01610 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01611 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01612 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01613 01614 _dbus_credentials_clear (credentials); 01615 01616 /* Systems supporting LOCAL_CREDS are configured to have this feature 01617 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01618 * the connection. Therefore, the received message must carry the 01619 * credentials information without doing anything special. 01620 */ 01621 01622 iov.iov_base = &buf; 01623 iov.iov_len = 1; 01624 01625 _DBUS_ZERO(msg); 01626 msg.msg_iov = &iov; 01627 msg.msg_iovlen = 1; 01628 01629 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01630 _DBUS_ZERO(cmsg); 01631 msg.msg_control = (caddr_t) &cmsg; 01632 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01633 #endif 01634 01635 again: 01636 bytes_read = recvmsg (client_fd, &msg, 0); 01637 01638 if (bytes_read < 0) 01639 { 01640 if (errno == EINTR) 01641 goto again; 01642 01643 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01644 * normally only call read_credentials if the socket was ready 01645 * for reading 01646 */ 01647 01648 dbus_set_error (error, _dbus_error_from_errno (errno), 01649 "Failed to read credentials byte: %s", 01650 _dbus_strerror (errno)); 01651 return FALSE; 01652 } 01653 else if (bytes_read == 0) 01654 { 01655 /* this should not happen unless we are using recvmsg wrong, 01656 * so is essentially here for paranoia 01657 */ 01658 dbus_set_error (error, DBUS_ERROR_FAILED, 01659 "Failed to read credentials byte (zero-length read)"); 01660 return FALSE; 01661 } 01662 else if (buf != '\0') 01663 { 01664 dbus_set_error (error, DBUS_ERROR_FAILED, 01665 "Credentials byte was not nul"); 01666 return FALSE; 01667 } 01668 01669 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01670 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01671 || cmsg.hdr.cmsg_type != SCM_CREDS) 01672 { 01673 dbus_set_error (error, DBUS_ERROR_FAILED, 01674 "Message from recvmsg() was not SCM_CREDS"); 01675 return FALSE; 01676 } 01677 #endif 01678 01679 _dbus_verbose ("read credentials byte\n"); 01680 01681 { 01682 #ifdef SO_PEERCRED 01683 #ifdef __OpenBSD__ 01684 struct sockpeercred cr; 01685 #else 01686 struct ucred cr; 01687 #endif 01688 int cr_len = sizeof (cr); 01689 01690 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01691 cr_len == sizeof (cr)) 01692 { 01693 pid_read = cr.pid; 01694 uid_read = cr.uid; 01695 } 01696 else 01697 { 01698 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01699 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01700 } 01701 #elif defined(HAVE_CMSGCRED) 01702 struct cmsgcred *cred; 01703 01704 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01705 pid_read = cred->cmcred_pid; 01706 uid_read = cred->cmcred_euid; 01707 #elif defined(LOCAL_CREDS) 01708 pid_read = DBUS_PID_UNSET; 01709 uid_read = cmsg.cred.sc_uid; 01710 /* Since we have already got the credentials from this socket, we can 01711 * disable its LOCAL_CREDS flag if it was ever set. */ 01712 _dbus_set_local_creds (client_fd, FALSE); 01713 #elif defined(HAVE_GETPEEREID) 01714 uid_t euid; 01715 gid_t egid; 01716 if (getpeereid (client_fd, &euid, &egid) == 0) 01717 { 01718 uid_read = euid; 01719 } 01720 else 01721 { 01722 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01723 } 01724 #elif defined(HAVE_GETPEERUCRED) 01725 ucred_t * ucred = NULL; 01726 if (getpeerucred (client_fd, &ucred) == 0) 01727 { 01728 pid_read = ucred_getpid (ucred); 01729 uid_read = ucred_geteuid (ucred); 01730 #ifdef HAVE_ADT 01731 /* generate audit session data based on socket ucred */ 01732 adt_session_data_t *adth = NULL; 01733 adt_export_data_t *data = NULL; 01734 size_t size = 0; 01735 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01736 { 01737 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01738 } 01739 else 01740 { 01741 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01742 { 01743 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01744 } 01745 else 01746 { 01747 size = adt_export_session_data (adth, &data); 01748 if (size <= 0) 01749 { 01750 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01751 } 01752 else 01753 { 01754 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01755 free (data); 01756 } 01757 } 01758 (void) adt_end_session (adth); 01759 } 01760 #endif /* HAVE_ADT */ 01761 } 01762 else 01763 { 01764 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01765 } 01766 if (ucred != NULL) 01767 ucred_free (ucred); 01768 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01769 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01770 #endif 01771 } 01772 01773 _dbus_verbose ("Credentials:" 01774 " pid "DBUS_PID_FORMAT 01775 " uid "DBUS_UID_FORMAT 01776 "\n", 01777 pid_read, 01778 uid_read); 01779 01780 if (pid_read != DBUS_PID_UNSET) 01781 { 01782 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01783 { 01784 _DBUS_SET_OOM (error); 01785 return FALSE; 01786 } 01787 } 01788 01789 if (uid_read != DBUS_UID_UNSET) 01790 { 01791 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01792 { 01793 _DBUS_SET_OOM (error); 01794 return FALSE; 01795 } 01796 } 01797 01798 return TRUE; 01799 } 01800 01818 dbus_bool_t 01819 _dbus_send_credentials_socket (int server_fd, 01820 DBusError *error) 01821 { 01822 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01823 01824 if (write_credentials_byte (server_fd, error)) 01825 return TRUE; 01826 else 01827 return FALSE; 01828 } 01829 01839 int 01840 _dbus_accept (int listen_fd) 01841 { 01842 int client_fd; 01843 struct sockaddr addr; 01844 socklen_t addrlen; 01845 #ifdef HAVE_ACCEPT4 01846 dbus_bool_t cloexec_done; 01847 #endif 01848 01849 addrlen = sizeof (addr); 01850 01851 retry: 01852 01853 #ifdef HAVE_ACCEPT4 01854 /* We assume that if accept4 is available SOCK_CLOEXEC is too */ 01855 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01856 cloexec_done = client_fd >= 0; 01857 01858 if (client_fd < 0 && errno == ENOSYS) 01859 #endif 01860 { 01861 client_fd = accept (listen_fd, &addr, &addrlen); 01862 } 01863 01864 if (client_fd < 0) 01865 { 01866 if (errno == EINTR) 01867 goto retry; 01868 } 01869 01870 _dbus_verbose ("client fd %d accepted\n", client_fd); 01871 01872 #ifdef HAVE_ACCEPT4 01873 if (!cloexec_done) 01874 #endif 01875 { 01876 _dbus_fd_set_close_on_exec(client_fd); 01877 } 01878 01879 return client_fd; 01880 } 01881 01890 dbus_bool_t 01891 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01892 { 01893 const char *directory; 01894 struct stat sb; 01895 01896 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01897 01898 directory = _dbus_string_get_const_data (dir); 01899 01900 if (stat (directory, &sb) < 0) 01901 { 01902 dbus_set_error (error, _dbus_error_from_errno (errno), 01903 "%s", _dbus_strerror (errno)); 01904 01905 return FALSE; 01906 } 01907 01908 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01909 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01910 { 01911 dbus_set_error (error, DBUS_ERROR_FAILED, 01912 "%s directory is not private to the user", directory); 01913 return FALSE; 01914 } 01915 01916 return TRUE; 01917 } 01918 01919 static dbus_bool_t 01920 fill_user_info_from_passwd (struct passwd *p, 01921 DBusUserInfo *info, 01922 DBusError *error) 01923 { 01924 _dbus_assert (p->pw_name != NULL); 01925 _dbus_assert (p->pw_dir != NULL); 01926 01927 info->uid = p->pw_uid; 01928 info->primary_gid = p->pw_gid; 01929 info->username = _dbus_strdup (p->pw_name); 01930 info->homedir = _dbus_strdup (p->pw_dir); 01931 01932 if (info->username == NULL || 01933 info->homedir == NULL) 01934 { 01935 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01936 return FALSE; 01937 } 01938 01939 return TRUE; 01940 } 01941 01942 static dbus_bool_t 01943 fill_user_info (DBusUserInfo *info, 01944 dbus_uid_t uid, 01945 const DBusString *username, 01946 DBusError *error) 01947 { 01948 const char *username_c; 01949 01950 /* exactly one of username/uid provided */ 01951 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 01952 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 01953 01954 info->uid = DBUS_UID_UNSET; 01955 info->primary_gid = DBUS_GID_UNSET; 01956 info->group_ids = NULL; 01957 info->n_group_ids = 0; 01958 info->username = NULL; 01959 info->homedir = NULL; 01960 01961 if (username != NULL) 01962 username_c = _dbus_string_get_const_data (username); 01963 else 01964 username_c = NULL; 01965 01966 /* For now assuming that the getpwnam() and getpwuid() flavors 01967 * are always symmetrical, if not we have to add more configure 01968 * checks 01969 */ 01970 01971 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 01972 { 01973 struct passwd *p; 01974 int result; 01975 size_t buflen; 01976 char *buf; 01977 struct passwd p_str; 01978 01979 /* retrieve maximum needed size for buf */ 01980 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 01981 01982 /* sysconf actually returns a long, but everything else expects size_t, 01983 * so just recast here. 01984 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 01985 */ 01986 if ((long) buflen <= 0) 01987 buflen = 1024; 01988 01989 result = -1; 01990 while (1) 01991 { 01992 buf = dbus_malloc (buflen); 01993 if (buf == NULL) 01994 { 01995 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01996 return FALSE; 01997 } 01998 01999 p = NULL; 02000 #ifdef HAVE_POSIX_GETPWNAM_R 02001 if (uid != DBUS_UID_UNSET) 02002 result = getpwuid_r (uid, &p_str, buf, buflen, 02003 &p); 02004 else 02005 result = getpwnam_r (username_c, &p_str, buf, buflen, 02006 &p); 02007 #else 02008 if (uid != DBUS_UID_UNSET) 02009 p = getpwuid_r (uid, &p_str, buf, buflen); 02010 else 02011 p = getpwnam_r (username_c, &p_str, buf, buflen); 02012 result = 0; 02013 #endif /* !HAVE_POSIX_GETPWNAM_R */ 02014 //Try a bigger buffer if ERANGE was returned 02015 if (result == ERANGE && buflen < 512 * 1024) 02016 { 02017 dbus_free (buf); 02018 buflen *= 2; 02019 } 02020 else 02021 { 02022 break; 02023 } 02024 } 02025 if (result == 0 && p == &p_str) 02026 { 02027 if (!fill_user_info_from_passwd (p, info, error)) 02028 { 02029 dbus_free (buf); 02030 return FALSE; 02031 } 02032 dbus_free (buf); 02033 } 02034 else 02035 { 02036 dbus_set_error (error, _dbus_error_from_errno (errno), 02037 "User \"%s\" unknown or no memory to allocate password entry\n", 02038 username_c ? username_c : "???"); 02039 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02040 dbus_free (buf); 02041 return FALSE; 02042 } 02043 } 02044 #else /* ! HAVE_GETPWNAM_R */ 02045 { 02046 /* I guess we're screwed on thread safety here */ 02047 struct passwd *p; 02048 02049 if (uid != DBUS_UID_UNSET) 02050 p = getpwuid (uid); 02051 else 02052 p = getpwnam (username_c); 02053 02054 if (p != NULL) 02055 { 02056 if (!fill_user_info_from_passwd (p, info, error)) 02057 { 02058 return FALSE; 02059 } 02060 } 02061 else 02062 { 02063 dbus_set_error (error, _dbus_error_from_errno (errno), 02064 "User \"%s\" unknown or no memory to allocate password entry\n", 02065 username_c ? username_c : "???"); 02066 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02067 return FALSE; 02068 } 02069 } 02070 #endif /* ! HAVE_GETPWNAM_R */ 02071 02072 /* Fill this in so we can use it to get groups */ 02073 username_c = info->username; 02074 02075 #ifdef HAVE_GETGROUPLIST 02076 { 02077 gid_t *buf; 02078 int buf_count; 02079 int i; 02080 int initial_buf_count; 02081 02082 initial_buf_count = 17; 02083 buf_count = initial_buf_count; 02084 buf = dbus_new (gid_t, buf_count); 02085 if (buf == NULL) 02086 { 02087 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02088 goto failed; 02089 } 02090 02091 if (getgrouplist (username_c, 02092 info->primary_gid, 02093 buf, &buf_count) < 0) 02094 { 02095 gid_t *new; 02096 /* Presumed cause of negative return code: buf has insufficient 02097 entries to hold the entire group list. The Linux behavior in this 02098 case is to pass back the actual number of groups in buf_count, but 02099 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02100 So as a hack, try to help out a bit by guessing a larger 02101 number of groups, within reason.. might still fail, of course, 02102 but we can at least print a more informative message. I looked up 02103 the "right way" to do this by downloading Apple's own source code 02104 for the "id" command, and it turns out that they use an 02105 undocumented library function getgrouplist_2 (!) which is not 02106 declared in any header in /usr/include (!!). That did not seem 02107 like the way to go here. 02108 */ 02109 if (buf_count == initial_buf_count) 02110 { 02111 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02112 } 02113 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02114 if (new == NULL) 02115 { 02116 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02117 dbus_free (buf); 02118 goto failed; 02119 } 02120 02121 buf = new; 02122 02123 errno = 0; 02124 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02125 { 02126 if (errno == 0) 02127 { 02128 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02129 username_c, buf_count, buf_count); 02130 } 02131 else 02132 { 02133 dbus_set_error (error, 02134 _dbus_error_from_errno (errno), 02135 "Failed to get groups for username \"%s\" primary GID " 02136 DBUS_GID_FORMAT ": %s\n", 02137 username_c, info->primary_gid, 02138 _dbus_strerror (errno)); 02139 dbus_free (buf); 02140 goto failed; 02141 } 02142 } 02143 } 02144 02145 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02146 if (info->group_ids == NULL) 02147 { 02148 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02149 dbus_free (buf); 02150 goto failed; 02151 } 02152 02153 for (i = 0; i < buf_count; ++i) 02154 info->group_ids[i] = buf[i]; 02155 02156 info->n_group_ids = buf_count; 02157 02158 dbus_free (buf); 02159 } 02160 #else /* HAVE_GETGROUPLIST */ 02161 { 02162 /* We just get the one group ID */ 02163 info->group_ids = dbus_new (dbus_gid_t, 1); 02164 if (info->group_ids == NULL) 02165 { 02166 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02167 goto failed; 02168 } 02169 02170 info->n_group_ids = 1; 02171 02172 (info->group_ids)[0] = info->primary_gid; 02173 } 02174 #endif /* HAVE_GETGROUPLIST */ 02175 02176 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02177 02178 return TRUE; 02179 02180 failed: 02181 _DBUS_ASSERT_ERROR_IS_SET (error); 02182 return FALSE; 02183 } 02184 02193 dbus_bool_t 02194 _dbus_user_info_fill (DBusUserInfo *info, 02195 const DBusString *username, 02196 DBusError *error) 02197 { 02198 return fill_user_info (info, DBUS_UID_UNSET, 02199 username, error); 02200 } 02201 02210 dbus_bool_t 02211 _dbus_user_info_fill_uid (DBusUserInfo *info, 02212 dbus_uid_t uid, 02213 DBusError *error) 02214 { 02215 return fill_user_info (info, uid, 02216 NULL, error); 02217 } 02218 02226 dbus_bool_t 02227 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02228 { 02229 /* The POSIX spec certainly doesn't promise this, but 02230 * we need these assertions to fail as soon as we're wrong about 02231 * it so we can do the porting fixups 02232 */ 02233 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02234 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02235 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02236 02237 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 02238 return FALSE; 02239 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02240 return FALSE; 02241 02242 return TRUE; 02243 } 02244 02256 dbus_bool_t 02257 _dbus_append_user_from_current_process (DBusString *str) 02258 { 02259 return _dbus_string_append_uint (str, 02260 _dbus_geteuid ()); 02261 } 02262 02267 dbus_pid_t 02268 _dbus_getpid (void) 02269 { 02270 return getpid (); 02271 } 02272 02276 dbus_uid_t 02277 _dbus_getuid (void) 02278 { 02279 return getuid (); 02280 } 02281 02285 dbus_uid_t 02286 _dbus_geteuid (void) 02287 { 02288 return geteuid (); 02289 } 02290 02297 unsigned long 02298 _dbus_pid_for_log (void) 02299 { 02300 return getpid (); 02301 } 02302 02310 dbus_bool_t 02311 _dbus_parse_uid (const DBusString *uid_str, 02312 dbus_uid_t *uid) 02313 { 02314 int end; 02315 long val; 02316 02317 if (_dbus_string_get_length (uid_str) == 0) 02318 { 02319 _dbus_verbose ("UID string was zero length\n"); 02320 return FALSE; 02321 } 02322 02323 val = -1; 02324 end = 0; 02325 if (!_dbus_string_parse_int (uid_str, 0, &val, 02326 &end)) 02327 { 02328 _dbus_verbose ("could not parse string as a UID\n"); 02329 return FALSE; 02330 } 02331 02332 if (end != _dbus_string_get_length (uid_str)) 02333 { 02334 _dbus_verbose ("string contained trailing stuff after UID\n"); 02335 return FALSE; 02336 } 02337 02338 *uid = val; 02339 02340 return TRUE; 02341 } 02342 02343 #if !DBUS_USE_SYNC 02344 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02345 #endif 02346 02353 dbus_int32_t 02354 _dbus_atomic_inc (DBusAtomic *atomic) 02355 { 02356 #if DBUS_USE_SYNC 02357 return __sync_add_and_fetch(&atomic->value, 1)-1; 02358 #else 02359 dbus_int32_t res; 02360 _DBUS_LOCK (atomic); 02361 res = atomic->value; 02362 atomic->value += 1; 02363 _DBUS_UNLOCK (atomic); 02364 return res; 02365 #endif 02366 } 02367 02374 dbus_int32_t 02375 _dbus_atomic_dec (DBusAtomic *atomic) 02376 { 02377 #if DBUS_USE_SYNC 02378 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02379 #else 02380 dbus_int32_t res; 02381 02382 _DBUS_LOCK (atomic); 02383 res = atomic->value; 02384 atomic->value -= 1; 02385 _DBUS_UNLOCK (atomic); 02386 return res; 02387 #endif 02388 } 02389 02397 dbus_int32_t 02398 _dbus_atomic_get (DBusAtomic *atomic) 02399 { 02400 #if DBUS_USE_SYNC 02401 __sync_synchronize (); 02402 return atomic->value; 02403 #else 02404 dbus_int32_t res; 02405 02406 _DBUS_LOCK (atomic); 02407 res = atomic->value; 02408 _DBUS_UNLOCK (atomic); 02409 return res; 02410 #endif 02411 } 02412 02413 #ifdef DBUS_BUILD_TESTS 02414 02417 dbus_gid_t 02418 _dbus_getgid (void) 02419 { 02420 return getgid (); 02421 } 02422 #endif 02423 02432 int 02433 _dbus_poll (DBusPollFD *fds, 02434 int n_fds, 02435 int timeout_milliseconds) 02436 { 02437 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02438 /* This big thing is a constant expression and should get optimized 02439 * out of existence. So it's more robust than a configure check at 02440 * no cost. 02441 */ 02442 if (_DBUS_POLLIN == POLLIN && 02443 _DBUS_POLLPRI == POLLPRI && 02444 _DBUS_POLLOUT == POLLOUT && 02445 _DBUS_POLLERR == POLLERR && 02446 _DBUS_POLLHUP == POLLHUP && 02447 _DBUS_POLLNVAL == POLLNVAL && 02448 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02449 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02450 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02451 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02452 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02453 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02454 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02455 { 02456 return poll ((struct pollfd*) fds, 02457 n_fds, 02458 timeout_milliseconds); 02459 } 02460 else 02461 { 02462 /* We have to convert the DBusPollFD to an array of 02463 * struct pollfd, poll, and convert back. 02464 */ 02465 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02466 return -1; 02467 } 02468 #else /* ! HAVE_POLL */ 02469 02470 fd_set read_set, write_set, err_set; 02471 int max_fd = 0; 02472 int i; 02473 struct timeval tv; 02474 int ready; 02475 02476 FD_ZERO (&read_set); 02477 FD_ZERO (&write_set); 02478 FD_ZERO (&err_set); 02479 02480 for (i = 0; i < n_fds; i++) 02481 { 02482 DBusPollFD *fdp = &fds[i]; 02483 02484 if (fdp->events & _DBUS_POLLIN) 02485 FD_SET (fdp->fd, &read_set); 02486 02487 if (fdp->events & _DBUS_POLLOUT) 02488 FD_SET (fdp->fd, &write_set); 02489 02490 FD_SET (fdp->fd, &err_set); 02491 02492 max_fd = MAX (max_fd, fdp->fd); 02493 } 02494 02495 tv.tv_sec = timeout_milliseconds / 1000; 02496 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02497 02498 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02499 timeout_milliseconds < 0 ? NULL : &tv); 02500 02501 if (ready > 0) 02502 { 02503 for (i = 0; i < n_fds; i++) 02504 { 02505 DBusPollFD *fdp = &fds[i]; 02506 02507 fdp->revents = 0; 02508 02509 if (FD_ISSET (fdp->fd, &read_set)) 02510 fdp->revents |= _DBUS_POLLIN; 02511 02512 if (FD_ISSET (fdp->fd, &write_set)) 02513 fdp->revents |= _DBUS_POLLOUT; 02514 02515 if (FD_ISSET (fdp->fd, &err_set)) 02516 fdp->revents |= _DBUS_POLLERR; 02517 } 02518 } 02519 02520 return ready; 02521 #endif 02522 } 02523 02531 void 02532 _dbus_get_current_time (long *tv_sec, 02533 long *tv_usec) 02534 { 02535 struct timeval t; 02536 02537 #ifdef HAVE_MONOTONIC_CLOCK 02538 struct timespec ts; 02539 clock_gettime (CLOCK_MONOTONIC, &ts); 02540 02541 if (tv_sec) 02542 *tv_sec = ts.tv_sec; 02543 if (tv_usec) 02544 *tv_usec = ts.tv_nsec / 1000; 02545 #else 02546 gettimeofday (&t, NULL); 02547 02548 if (tv_sec) 02549 *tv_sec = t.tv_sec; 02550 if (tv_usec) 02551 *tv_usec = t.tv_usec; 02552 #endif 02553 } 02554 02563 dbus_bool_t 02564 _dbus_create_directory (const DBusString *filename, 02565 DBusError *error) 02566 { 02567 const char *filename_c; 02568 02569 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02570 02571 filename_c = _dbus_string_get_const_data (filename); 02572 02573 if (mkdir (filename_c, 0700) < 0) 02574 { 02575 if (errno == EEXIST) 02576 return TRUE; 02577 02578 dbus_set_error (error, DBUS_ERROR_FAILED, 02579 "Failed to create directory %s: %s\n", 02580 filename_c, _dbus_strerror (errno)); 02581 return FALSE; 02582 } 02583 else 02584 return TRUE; 02585 } 02586 02597 dbus_bool_t 02598 _dbus_concat_dir_and_file (DBusString *dir, 02599 const DBusString *next_component) 02600 { 02601 dbus_bool_t dir_ends_in_slash; 02602 dbus_bool_t file_starts_with_slash; 02603 02604 if (_dbus_string_get_length (dir) == 0 || 02605 _dbus_string_get_length (next_component) == 0) 02606 return TRUE; 02607 02608 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02609 _dbus_string_get_length (dir) - 1); 02610 02611 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02612 02613 if (dir_ends_in_slash && file_starts_with_slash) 02614 { 02615 _dbus_string_shorten (dir, 1); 02616 } 02617 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02618 { 02619 if (!_dbus_string_append_byte (dir, '/')) 02620 return FALSE; 02621 } 02622 02623 return _dbus_string_copy (next_component, 0, dir, 02624 _dbus_string_get_length (dir)); 02625 } 02626 02628 #define NANOSECONDS_PER_SECOND 1000000000 02629 02630 #define MICROSECONDS_PER_SECOND 1000000 02631 02632 #define MILLISECONDS_PER_SECOND 1000 02633 02634 #define NANOSECONDS_PER_MILLISECOND 1000000 02635 02636 #define MICROSECONDS_PER_MILLISECOND 1000 02637 02642 void 02643 _dbus_sleep_milliseconds (int milliseconds) 02644 { 02645 #ifdef HAVE_NANOSLEEP 02646 struct timespec req; 02647 struct timespec rem; 02648 02649 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02650 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02651 rem.tv_sec = 0; 02652 rem.tv_nsec = 0; 02653 02654 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02655 req = rem; 02656 #elif defined (HAVE_USLEEP) 02657 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02658 #else /* ! HAVE_USLEEP */ 02659 sleep (MAX (milliseconds / 1000, 1)); 02660 #endif 02661 } 02662 02663 static dbus_bool_t 02664 _dbus_generate_pseudorandom_bytes (DBusString *str, 02665 int n_bytes) 02666 { 02667 int old_len; 02668 char *p; 02669 02670 old_len = _dbus_string_get_length (str); 02671 02672 if (!_dbus_string_lengthen (str, n_bytes)) 02673 return FALSE; 02674 02675 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02676 02677 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02678 02679 return TRUE; 02680 } 02681 02690 dbus_bool_t 02691 _dbus_generate_random_bytes (DBusString *str, 02692 int n_bytes) 02693 { 02694 int old_len; 02695 int fd; 02696 02697 /* FALSE return means "no memory", if it could 02698 * mean something else then we'd need to return 02699 * a DBusError. So we always fall back to pseudorandom 02700 * if the I/O fails. 02701 */ 02702 02703 old_len = _dbus_string_get_length (str); 02704 fd = -1; 02705 02706 /* note, urandom on linux will fall back to pseudorandom */ 02707 fd = open ("/dev/urandom", O_RDONLY); 02708 if (fd < 0) 02709 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02710 02711 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02712 02713 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02714 { 02715 _dbus_close (fd, NULL); 02716 _dbus_string_set_length (str, old_len); 02717 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02718 } 02719 02720 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02721 n_bytes); 02722 02723 _dbus_close (fd, NULL); 02724 02725 return TRUE; 02726 } 02727 02733 void 02734 _dbus_exit (int code) 02735 { 02736 _exit (code); 02737 } 02738 02747 const char* 02748 _dbus_strerror (int error_number) 02749 { 02750 const char *msg; 02751 02752 msg = strerror (error_number); 02753 if (msg == NULL) 02754 msg = "unknown"; 02755 02756 return msg; 02757 } 02758 02762 void 02763 _dbus_disable_sigpipe (void) 02764 { 02765 signal (SIGPIPE, SIG_IGN); 02766 } 02767 02775 void 02776 _dbus_fd_set_close_on_exec (intptr_t fd) 02777 { 02778 int val; 02779 02780 val = fcntl (fd, F_GETFD, 0); 02781 02782 if (val < 0) 02783 return; 02784 02785 val |= FD_CLOEXEC; 02786 02787 fcntl (fd, F_SETFD, val); 02788 } 02789 02797 dbus_bool_t 02798 _dbus_close (int fd, 02799 DBusError *error) 02800 { 02801 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02802 02803 again: 02804 if (close (fd) < 0) 02805 { 02806 if (errno == EINTR) 02807 goto again; 02808 02809 dbus_set_error (error, _dbus_error_from_errno (errno), 02810 "Could not close fd %d", fd); 02811 return FALSE; 02812 } 02813 02814 return TRUE; 02815 } 02816 02824 int 02825 _dbus_dup(int fd, 02826 DBusError *error) 02827 { 02828 int new_fd; 02829 02830 #ifdef F_DUPFD_CLOEXEC 02831 dbus_bool_t cloexec_done; 02832 02833 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02834 cloexec_done = new_fd >= 0; 02835 02836 if (new_fd < 0 && errno == EINVAL) 02837 #endif 02838 { 02839 new_fd = fcntl(fd, F_DUPFD, 3); 02840 } 02841 02842 if (new_fd < 0) { 02843 02844 dbus_set_error (error, _dbus_error_from_errno (errno), 02845 "Could not duplicate fd %d", fd); 02846 return -1; 02847 } 02848 02849 #ifdef F_DUPFD_CLOEXEC 02850 if (!cloexec_done) 02851 #endif 02852 { 02853 _dbus_fd_set_close_on_exec(new_fd); 02854 } 02855 02856 return new_fd; 02857 } 02858 02866 dbus_bool_t 02867 _dbus_set_fd_nonblocking (int fd, 02868 DBusError *error) 02869 { 02870 int val; 02871 02872 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02873 02874 val = fcntl (fd, F_GETFL, 0); 02875 if (val < 0) 02876 { 02877 dbus_set_error (error, _dbus_error_from_errno (errno), 02878 "Failed to get flags from file descriptor %d: %s", 02879 fd, _dbus_strerror (errno)); 02880 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02881 _dbus_strerror (errno)); 02882 return FALSE; 02883 } 02884 02885 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02886 { 02887 dbus_set_error (error, _dbus_error_from_errno (errno), 02888 "Failed to set nonblocking flag of file descriptor %d: %s", 02889 fd, _dbus_strerror (errno)); 02890 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02891 fd, _dbus_strerror (errno)); 02892 02893 return FALSE; 02894 } 02895 02896 return TRUE; 02897 } 02898 02904 void 02905 _dbus_print_backtrace (void) 02906 { 02907 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02908 void *bt[500]; 02909 int bt_size; 02910 int i; 02911 char **syms; 02912 02913 bt_size = backtrace (bt, 500); 02914 02915 syms = backtrace_symbols (bt, bt_size); 02916 02917 i = 0; 02918 while (i < bt_size) 02919 { 02920 /* don't use dbus_warn since it can _dbus_abort() */ 02921 fprintf (stderr, " %s\n", syms[i]); 02922 ++i; 02923 } 02924 fflush (stderr); 02925 02926 free (syms); 02927 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02928 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02929 #else 02930 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02931 #endif 02932 } 02933 02951 dbus_bool_t 02952 _dbus_full_duplex_pipe (int *fd1, 02953 int *fd2, 02954 dbus_bool_t blocking, 02955 DBusError *error) 02956 { 02957 #ifdef HAVE_SOCKETPAIR 02958 int fds[2]; 02959 int retval; 02960 02961 #ifdef SOCK_CLOEXEC 02962 dbus_bool_t cloexec_done; 02963 02964 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 02965 cloexec_done = retval >= 0; 02966 02967 if (retval < 0 && errno == EINVAL) 02968 #endif 02969 { 02970 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 02971 } 02972 02973 if (retval < 0) 02974 { 02975 dbus_set_error (error, _dbus_error_from_errno (errno), 02976 "Could not create full-duplex pipe"); 02977 return FALSE; 02978 } 02979 02980 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02981 02982 #ifdef SOCK_CLOEXEC 02983 if (!cloexec_done) 02984 #endif 02985 { 02986 _dbus_fd_set_close_on_exec (fds[0]); 02987 _dbus_fd_set_close_on_exec (fds[1]); 02988 } 02989 02990 if (!blocking && 02991 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02992 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02993 { 02994 dbus_set_error (error, _dbus_error_from_errno (errno), 02995 "Could not set full-duplex pipe nonblocking"); 02996 02997 _dbus_close (fds[0], NULL); 02998 _dbus_close (fds[1], NULL); 02999 03000 return FALSE; 03001 } 03002 03003 *fd1 = fds[0]; 03004 *fd2 = fds[1]; 03005 03006 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 03007 *fd1, *fd2); 03008 03009 return TRUE; 03010 #else 03011 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 03012 dbus_set_error (error, DBUS_ERROR_FAILED, 03013 "_dbus_full_duplex_pipe() not implemented on this OS"); 03014 return FALSE; 03015 #endif 03016 } 03017 03026 int 03027 _dbus_printf_string_upper_bound (const char *format, 03028 va_list args) 03029 { 03030 char static_buf[1024]; 03031 int bufsize = sizeof (static_buf); 03032 int len; 03033 va_list args_copy; 03034 03035 DBUS_VA_COPY (args_copy, args); 03036 len = vsnprintf (static_buf, bufsize, format, args_copy); 03037 va_end (args_copy); 03038 03039 /* If vsnprintf() returned non-negative, then either the string fits in 03040 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03041 * returns the number of characters that were needed, or this OS returns the 03042 * truncated length. 03043 * 03044 * We ignore the possibility that snprintf might just ignore the length and 03045 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03046 * If your libc is really that bad, come back when you have a better one. */ 03047 if (len == bufsize) 03048 { 03049 /* This could be the truncated length (Tru64 and IRIX have this bug), 03050 * or the real length could be coincidentally the same. Which is it? 03051 * If vsnprintf returns the truncated length, we'll go to the slow 03052 * path. */ 03053 DBUS_VA_COPY (args_copy, args); 03054 03055 if (vsnprintf (static_buf, 1, format, args_copy) == 1) 03056 len = -1; 03057 03058 va_end (args_copy); 03059 } 03060 03061 /* If vsnprintf() returned negative, we have to do more work. 03062 * HP-UX returns negative. */ 03063 while (len < 0) 03064 { 03065 char *buf; 03066 03067 bufsize *= 2; 03068 03069 buf = dbus_malloc (bufsize); 03070 03071 if (buf == NULL) 03072 return -1; 03073 03074 DBUS_VA_COPY (args_copy, args); 03075 len = vsnprintf (buf, bufsize, format, args_copy); 03076 va_end (args_copy); 03077 03078 dbus_free (buf); 03079 03080 /* If the reported length is exactly the buffer size, round up to the 03081 * next size, in case vsnprintf has been returning the truncated 03082 * length */ 03083 if (len == bufsize) 03084 len = -1; 03085 } 03086 03087 return len; 03088 } 03089 03096 const char* 03097 _dbus_get_tmpdir(void) 03098 { 03099 static const char* tmpdir = NULL; 03100 03101 if (tmpdir == NULL) 03102 { 03103 /* TMPDIR is what glibc uses, then 03104 * glibc falls back to the P_tmpdir macro which 03105 * just expands to "/tmp" 03106 */ 03107 if (tmpdir == NULL) 03108 tmpdir = getenv("TMPDIR"); 03109 03110 /* These two env variables are probably 03111 * broken, but maybe some OS uses them? 03112 */ 03113 if (tmpdir == NULL) 03114 tmpdir = getenv("TMP"); 03115 if (tmpdir == NULL) 03116 tmpdir = getenv("TEMP"); 03117 03118 /* And this is the sane fallback. */ 03119 if (tmpdir == NULL) 03120 tmpdir = "/tmp"; 03121 } 03122 03123 _dbus_assert(tmpdir != NULL); 03124 03125 return tmpdir; 03126 } 03127 03147 static dbus_bool_t 03148 _read_subprocess_line_argv (const char *progpath, 03149 dbus_bool_t path_fallback, 03150 char * const *argv, 03151 DBusString *result, 03152 DBusError *error) 03153 { 03154 int result_pipe[2] = { -1, -1 }; 03155 int errors_pipe[2] = { -1, -1 }; 03156 pid_t pid; 03157 int ret; 03158 int status; 03159 int orig_len; 03160 int i; 03161 03162 dbus_bool_t retval; 03163 sigset_t new_set, old_set; 03164 03165 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03166 retval = FALSE; 03167 03168 /* We need to block any existing handlers for SIGCHLD temporarily; they 03169 * will cause waitpid() below to fail. 03170 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03171 */ 03172 sigemptyset (&new_set); 03173 sigaddset (&new_set, SIGCHLD); 03174 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03175 03176 orig_len = _dbus_string_get_length (result); 03177 03178 #define READ_END 0 03179 #define WRITE_END 1 03180 if (pipe (result_pipe) < 0) 03181 { 03182 dbus_set_error (error, _dbus_error_from_errno (errno), 03183 "Failed to create a pipe to call %s: %s", 03184 progpath, _dbus_strerror (errno)); 03185 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03186 progpath, _dbus_strerror (errno)); 03187 goto out; 03188 } 03189 if (pipe (errors_pipe) < 0) 03190 { 03191 dbus_set_error (error, _dbus_error_from_errno (errno), 03192 "Failed to create a pipe to call %s: %s", 03193 progpath, _dbus_strerror (errno)); 03194 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03195 progpath, _dbus_strerror (errno)); 03196 goto out; 03197 } 03198 03199 pid = fork (); 03200 if (pid < 0) 03201 { 03202 dbus_set_error (error, _dbus_error_from_errno (errno), 03203 "Failed to fork() to call %s: %s", 03204 progpath, _dbus_strerror (errno)); 03205 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03206 progpath, _dbus_strerror (errno)); 03207 goto out; 03208 } 03209 03210 if (pid == 0) 03211 { 03212 /* child process */ 03213 int maxfds; 03214 int fd; 03215 03216 fd = open ("/dev/null", O_RDWR); 03217 if (fd == -1) 03218 /* huh?! can't open /dev/null? */ 03219 _exit (1); 03220 03221 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03222 03223 /* set-up stdXXX */ 03224 close (result_pipe[READ_END]); 03225 close (errors_pipe[READ_END]); 03226 close (0); /* close stdin */ 03227 close (1); /* close stdout */ 03228 close (2); /* close stderr */ 03229 03230 if (dup2 (fd, 0) == -1) 03231 _exit (1); 03232 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03233 _exit (1); 03234 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03235 _exit (1); 03236 03237 maxfds = sysconf (_SC_OPEN_MAX); 03238 /* Pick something reasonable if for some reason sysconf 03239 * says unlimited. 03240 */ 03241 if (maxfds < 0) 03242 maxfds = 1024; 03243 /* close all inherited fds */ 03244 for (i = 3; i < maxfds; i++) 03245 close (i); 03246 03247 sigprocmask (SIG_SETMASK, &old_set, NULL); 03248 03249 /* If it looks fully-qualified, try execv first */ 03250 if (progpath[0] == '/') 03251 { 03252 execv (progpath, argv); 03253 /* Ok, that failed. Now if path_fallback is given, let's 03254 * try unqualified. This is mostly a hack to work 03255 * around systems which ship dbus-launch in /usr/bin 03256 * but everything else in /bin (because dbus-launch 03257 * depends on X11). 03258 */ 03259 if (path_fallback) 03260 /* We must have a slash, because we checked above */ 03261 execvp (strrchr (progpath, '/')+1, argv); 03262 } 03263 else 03264 execvp (progpath, argv); 03265 03266 /* still nothing, we failed */ 03267 _exit (1); 03268 } 03269 03270 /* parent process */ 03271 close (result_pipe[WRITE_END]); 03272 close (errors_pipe[WRITE_END]); 03273 result_pipe[WRITE_END] = -1; 03274 errors_pipe[WRITE_END] = -1; 03275 03276 ret = 0; 03277 do 03278 { 03279 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03280 } 03281 while (ret > 0); 03282 03283 /* reap the child process to avoid it lingering as zombie */ 03284 do 03285 { 03286 ret = waitpid (pid, &status, 0); 03287 } 03288 while (ret == -1 && errno == EINTR); 03289 03290 /* We succeeded if the process exited with status 0 and 03291 anything was read */ 03292 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03293 { 03294 /* The process ended with error */ 03295 DBusString error_message; 03296 if (!_dbus_string_init (&error_message)) 03297 { 03298 _DBUS_SET_OOM (error); 03299 goto out; 03300 } 03301 03302 ret = 0; 03303 do 03304 { 03305 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03306 } 03307 while (ret > 0); 03308 03309 _dbus_string_set_length (result, orig_len); 03310 if (_dbus_string_get_length (&error_message) > 0) 03311 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03312 "%s terminated abnormally with the following error: %s", 03313 progpath, _dbus_string_get_data (&error_message)); 03314 else 03315 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03316 "%s terminated abnormally without any error message", 03317 progpath); 03318 goto out; 03319 } 03320 03321 retval = TRUE; 03322 03323 out: 03324 sigprocmask (SIG_SETMASK, &old_set, NULL); 03325 03326 if (retval) 03327 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03328 else 03329 _DBUS_ASSERT_ERROR_IS_SET (error); 03330 03331 if (result_pipe[0] != -1) 03332 close (result_pipe[0]); 03333 if (result_pipe[1] != -1) 03334 close (result_pipe[1]); 03335 if (errors_pipe[0] != -1) 03336 close (errors_pipe[0]); 03337 if (errors_pipe[1] != -1) 03338 close (errors_pipe[1]); 03339 03340 return retval; 03341 } 03342 03354 dbus_bool_t 03355 _dbus_get_autolaunch_address (const char *scope, 03356 DBusString *address, 03357 DBusError *error) 03358 { 03359 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03360 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03361 * but that's done elsewhere, and if it worked, this function wouldn't 03362 * be called.) */ 03363 const char *display; 03364 static char *argv[6]; 03365 int i; 03366 DBusString uuid; 03367 dbus_bool_t retval; 03368 03369 if (_dbus_check_setuid ()) 03370 { 03371 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03372 "Unable to autolaunch when setuid"); 03373 return FALSE; 03374 } 03375 03376 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03377 retval = FALSE; 03378 03379 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03380 * dbus-launch-x11 is just going to fail. Rather than trying to 03381 * run it, we might as well bail out early with a nice error. */ 03382 display = _dbus_getenv ("DISPLAY"); 03383 03384 if (display == NULL || display[0] == '\0') 03385 { 03386 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03387 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03388 return FALSE; 03389 } 03390 03391 if (!_dbus_string_init (&uuid)) 03392 { 03393 _DBUS_SET_OOM (error); 03394 return FALSE; 03395 } 03396 03397 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03398 { 03399 _DBUS_SET_OOM (error); 03400 goto out; 03401 } 03402 03403 i = 0; 03404 argv[i] = "dbus-launch"; 03405 ++i; 03406 argv[i] = "--autolaunch"; 03407 ++i; 03408 argv[i] = _dbus_string_get_data (&uuid); 03409 ++i; 03410 argv[i] = "--binary-syntax"; 03411 ++i; 03412 argv[i] = "--close-stderr"; 03413 ++i; 03414 argv[i] = NULL; 03415 ++i; 03416 03417 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03418 03419 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03420 TRUE, 03421 argv, address, error); 03422 03423 out: 03424 _dbus_string_free (&uuid); 03425 return retval; 03426 #else 03427 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03428 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03429 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03430 return FALSE; 03431 #endif 03432 } 03433 03452 dbus_bool_t 03453 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03454 dbus_bool_t create_if_not_found, 03455 DBusError *error) 03456 { 03457 DBusString filename; 03458 dbus_bool_t b; 03459 03460 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03461 03462 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03463 if (b) 03464 return TRUE; 03465 03466 dbus_error_free (error); 03467 03468 /* Fallback to the system machine ID */ 03469 _dbus_string_init_const (&filename, "/etc/machine-id"); 03470 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03471 } 03472 03473 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03474 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03475 03482 dbus_bool_t 03483 _dbus_lookup_launchd_socket (DBusString *socket_path, 03484 const char *launchd_env_var, 03485 DBusError *error) 03486 { 03487 #ifdef DBUS_ENABLE_LAUNCHD 03488 char *argv[4]; 03489 int i; 03490 03491 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03492 03493 if (_dbus_check_setuid ()) 03494 { 03495 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03496 "Unable to find launchd socket when setuid"); 03497 return FALSE; 03498 } 03499 03500 i = 0; 03501 argv[i] = "launchctl"; 03502 ++i; 03503 argv[i] = "getenv"; 03504 ++i; 03505 argv[i] = (char*)launchd_env_var; 03506 ++i; 03507 argv[i] = NULL; 03508 ++i; 03509 03510 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03511 03512 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03513 { 03514 return FALSE; 03515 } 03516 03517 /* no error, but no result either */ 03518 if (_dbus_string_get_length(socket_path) == 0) 03519 { 03520 return FALSE; 03521 } 03522 03523 /* strip the carriage-return */ 03524 _dbus_string_shorten(socket_path, 1); 03525 return TRUE; 03526 #else /* DBUS_ENABLE_LAUNCHD */ 03527 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03528 "can't lookup socket from launchd; launchd support not compiled in"); 03529 return FALSE; 03530 #endif 03531 } 03532 03533 static dbus_bool_t 03534 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03535 { 03536 #ifdef DBUS_ENABLE_LAUNCHD 03537 dbus_bool_t valid_socket; 03538 DBusString socket_path; 03539 03540 if (_dbus_check_setuid ()) 03541 { 03542 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03543 "Unable to find launchd socket when setuid"); 03544 return FALSE; 03545 } 03546 03547 if (!_dbus_string_init (&socket_path)) 03548 { 03549 _DBUS_SET_OOM (error); 03550 return FALSE; 03551 } 03552 03553 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03554 03555 if (dbus_error_is_set(error)) 03556 { 03557 _dbus_string_free(&socket_path); 03558 return FALSE; 03559 } 03560 03561 if (!valid_socket) 03562 { 03563 dbus_set_error(error, "no socket path", 03564 "launchd did not provide a socket path, " 03565 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03566 _dbus_string_free(&socket_path); 03567 return FALSE; 03568 } 03569 if (!_dbus_string_append (address, "unix:path=")) 03570 { 03571 _DBUS_SET_OOM (error); 03572 _dbus_string_free(&socket_path); 03573 return FALSE; 03574 } 03575 if (!_dbus_string_copy (&socket_path, 0, address, 03576 _dbus_string_get_length (address))) 03577 { 03578 _DBUS_SET_OOM (error); 03579 _dbus_string_free(&socket_path); 03580 return FALSE; 03581 } 03582 03583 _dbus_string_free(&socket_path); 03584 return TRUE; 03585 #else 03586 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03587 "can't lookup session address from launchd; launchd support not compiled in"); 03588 return FALSE; 03589 #endif 03590 } 03591 03611 dbus_bool_t 03612 _dbus_lookup_session_address (dbus_bool_t *supported, 03613 DBusString *address, 03614 DBusError *error) 03615 { 03616 #ifdef DBUS_ENABLE_LAUNCHD 03617 *supported = TRUE; 03618 return _dbus_lookup_session_address_launchd (address, error); 03619 #else 03620 /* On non-Mac Unix platforms, if the session address isn't already 03621 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03622 * fall back to the autolaunch: global default; see 03623 * init_session_address in dbus/dbus-bus.c. */ 03624 *supported = FALSE; 03625 return TRUE; 03626 #endif 03627 } 03628 03646 dbus_bool_t 03647 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03648 { 03649 const char *xdg_data_home; 03650 const char *xdg_data_dirs; 03651 DBusString servicedir_path; 03652 03653 if (!_dbus_string_init (&servicedir_path)) 03654 return FALSE; 03655 03656 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03657 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03658 03659 if (xdg_data_home != NULL) 03660 { 03661 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03662 goto oom; 03663 } 03664 else 03665 { 03666 const DBusString *homedir; 03667 DBusString local_share; 03668 03669 if (!_dbus_homedir_from_current_process (&homedir)) 03670 goto oom; 03671 03672 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03673 goto oom; 03674 03675 _dbus_string_init_const (&local_share, "/.local/share"); 03676 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03677 goto oom; 03678 } 03679 03680 if (!_dbus_string_append (&servicedir_path, ":")) 03681 goto oom; 03682 03683 if (xdg_data_dirs != NULL) 03684 { 03685 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03686 goto oom; 03687 03688 if (!_dbus_string_append (&servicedir_path, ":")) 03689 goto oom; 03690 } 03691 else 03692 { 03693 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03694 goto oom; 03695 } 03696 03697 /* 03698 * add configured datadir to defaults 03699 * this may be the same as an xdg dir 03700 * however the config parser should take 03701 * care of duplicates 03702 */ 03703 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03704 goto oom; 03705 03706 if (!_dbus_split_paths_and_append (&servicedir_path, 03707 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03708 dirs)) 03709 goto oom; 03710 03711 _dbus_string_free (&servicedir_path); 03712 return TRUE; 03713 03714 oom: 03715 _dbus_string_free (&servicedir_path); 03716 return FALSE; 03717 } 03718 03719 03738 dbus_bool_t 03739 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03740 { 03741 const char *xdg_data_dirs; 03742 DBusString servicedir_path; 03743 03744 if (!_dbus_string_init (&servicedir_path)) 03745 return FALSE; 03746 03747 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03748 03749 if (xdg_data_dirs != NULL) 03750 { 03751 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03752 goto oom; 03753 03754 if (!_dbus_string_append (&servicedir_path, ":")) 03755 goto oom; 03756 } 03757 else 03758 { 03759 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03760 goto oom; 03761 } 03762 03763 /* 03764 * Add configured datadir to defaults. This may be the same as one 03765 * of the XDG directories. However, the config parser should take 03766 * care of the duplicates. 03767 * 03768 * Also, append /lib as counterpart of /usr/share on the root 03769 * directory (the root directory does not know /share), in order to 03770 * facilitate early boot system bus activation where /usr might not 03771 * be available. 03772 */ 03773 if (!_dbus_string_append (&servicedir_path, 03774 DBUS_DATADIR":" 03775 "/lib:")) 03776 goto oom; 03777 03778 if (!_dbus_split_paths_and_append (&servicedir_path, 03779 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03780 dirs)) 03781 goto oom; 03782 03783 _dbus_string_free (&servicedir_path); 03784 return TRUE; 03785 03786 oom: 03787 _dbus_string_free (&servicedir_path); 03788 return FALSE; 03789 } 03790 03799 dbus_bool_t 03800 _dbus_append_system_config_file (DBusString *str) 03801 { 03802 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03803 } 03804 03811 dbus_bool_t 03812 _dbus_append_session_config_file (DBusString *str) 03813 { 03814 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03815 } 03816 03824 void 03825 _dbus_flush_caches (void) 03826 { 03827 _dbus_user_database_flush_system (); 03828 } 03829 03843 dbus_bool_t 03844 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03845 DBusCredentials *credentials) 03846 { 03847 DBusString homedir; 03848 DBusString dotdir; 03849 dbus_uid_t uid; 03850 03851 _dbus_assert (credentials != NULL); 03852 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03853 03854 if (!_dbus_string_init (&homedir)) 03855 return FALSE; 03856 03857 uid = _dbus_credentials_get_unix_uid (credentials); 03858 _dbus_assert (uid != DBUS_UID_UNSET); 03859 03860 if (!_dbus_homedir_from_uid (uid, &homedir)) 03861 goto failed; 03862 03863 #ifdef DBUS_BUILD_TESTS 03864 { 03865 const char *override; 03866 03867 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03868 if (override != NULL && *override != '\0') 03869 { 03870 _dbus_string_set_length (&homedir, 0); 03871 if (!_dbus_string_append (&homedir, override)) 03872 goto failed; 03873 03874 _dbus_verbose ("Using fake homedir for testing: %s\n", 03875 _dbus_string_get_const_data (&homedir)); 03876 } 03877 else 03878 { 03879 static dbus_bool_t already_warned = FALSE; 03880 if (!already_warned) 03881 { 03882 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03883 already_warned = TRUE; 03884 } 03885 } 03886 } 03887 #endif 03888 03889 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03890 if (!_dbus_concat_dir_and_file (&homedir, 03891 &dotdir)) 03892 goto failed; 03893 03894 if (!_dbus_string_copy (&homedir, 0, 03895 directory, _dbus_string_get_length (directory))) { 03896 goto failed; 03897 } 03898 03899 _dbus_string_free (&homedir); 03900 return TRUE; 03901 03902 failed: 03903 _dbus_string_free (&homedir); 03904 return FALSE; 03905 } 03906 03907 //PENDING(kdab) docs 03908 dbus_bool_t 03909 _dbus_daemon_publish_session_bus_address (const char* addr, 03910 const char *scope) 03911 { 03912 return TRUE; 03913 } 03914 03915 //PENDING(kdab) docs 03916 void 03917 _dbus_daemon_unpublish_session_bus_address (void) 03918 { 03919 03920 } 03921 03928 dbus_bool_t 03929 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03930 { 03931 return errno == EAGAIN || errno == EWOULDBLOCK; 03932 } 03933 03941 dbus_bool_t 03942 _dbus_delete_directory (const DBusString *filename, 03943 DBusError *error) 03944 { 03945 const char *filename_c; 03946 03947 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03948 03949 filename_c = _dbus_string_get_const_data (filename); 03950 03951 if (rmdir (filename_c) != 0) 03952 { 03953 dbus_set_error (error, DBUS_ERROR_FAILED, 03954 "Failed to remove directory %s: %s\n", 03955 filename_c, _dbus_strerror (errno)); 03956 return FALSE; 03957 } 03958 03959 return TRUE; 03960 } 03961 03969 dbus_bool_t 03970 _dbus_socket_can_pass_unix_fd(int fd) { 03971 03972 #ifdef SCM_RIGHTS 03973 union { 03974 struct sockaddr sa; 03975 struct sockaddr_storage storage; 03976 struct sockaddr_un un; 03977 } sa_buf; 03978 03979 socklen_t sa_len = sizeof(sa_buf); 03980 03981 _DBUS_ZERO(sa_buf); 03982 03983 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03984 return FALSE; 03985 03986 return sa_buf.sa.sa_family == AF_UNIX; 03987 03988 #else 03989 return FALSE; 03990 03991 #endif 03992 } 03993 03994 03995 /* 03996 * replaces the term DBUS_PREFIX in configure_time_path by the 03997 * current dbus installation directory. On unix this function is a noop 03998 * 03999 * @param configure_time_path 04000 * @return real path 04001 */ 04002 const char * 04003 _dbus_replace_install_prefix (const char *configure_time_path) 04004 { 04005 return configure_time_path; 04006 } 04007 04017 dbus_bool_t 04018 _dbus_check_setuid (void) 04019 { 04020 /* TODO: get __libc_enable_secure exported from glibc. 04021 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1 04022 */ 04023 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE) 04024 { 04025 /* See glibc/include/unistd.h */ 04026 extern int __libc_enable_secure; 04027 return __libc_enable_secure; 04028 } 04029 #elif defined(HAVE_ISSETUGID) 04030 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */ 04031 return issetugid (); 04032 #else 04033 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ 04034 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ 04035 04036 static dbus_bool_t check_setuid_initialised; 04037 static dbus_bool_t is_setuid; 04038 04039 if (_DBUS_UNLIKELY (!check_setuid_initialised)) 04040 { 04041 #ifdef HAVE_GETRESUID 04042 if (getresuid (&ruid, &euid, &suid) != 0 || 04043 getresgid (&rgid, &egid, &sgid) != 0) 04044 #endif /* HAVE_GETRESUID */ 04045 { 04046 suid = ruid = getuid (); 04047 sgid = rgid = getgid (); 04048 euid = geteuid (); 04049 egid = getegid (); 04050 } 04051 04052 check_setuid_initialised = TRUE; 04053 is_setuid = (ruid != euid || ruid != suid || 04054 rgid != egid || rgid != sgid); 04055 04056 } 04057 return is_setuid; 04058 #endif 04059 } 04060 04061 /* tests in dbus-sysdeps-util.c */