D-Bus 1.4.20
|
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 03034 len = vsnprintf (static_buf, bufsize, format, args); 03035 03036 /* If vsnprintf() returned non-negative, then either the string fits in 03037 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03038 * returns the number of characters that were needed, or this OS returns the 03039 * truncated length. 03040 * 03041 * We ignore the possibility that snprintf might just ignore the length and 03042 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03043 * If your libc is really that bad, come back when you have a better one. */ 03044 if (len == bufsize) 03045 { 03046 /* This could be the truncated length (Tru64 and IRIX have this bug), 03047 * or the real length could be coincidentally the same. Which is it? 03048 * If vsnprintf returns the truncated length, we'll go to the slow 03049 * path. */ 03050 if (vsnprintf (static_buf, 1, format, args) == 1) 03051 len = -1; 03052 } 03053 03054 /* If vsnprintf() returned negative, we have to do more work. 03055 * HP-UX returns negative. */ 03056 while (len < 0) 03057 { 03058 char *buf; 03059 03060 bufsize *= 2; 03061 03062 buf = dbus_malloc (bufsize); 03063 03064 if (buf == NULL) 03065 return -1; 03066 03067 len = vsnprintf (buf, bufsize, format, args); 03068 dbus_free (buf); 03069 03070 /* If the reported length is exactly the buffer size, round up to the 03071 * next size, in case vsnprintf has been returning the truncated 03072 * length */ 03073 if (len == bufsize) 03074 len = -1; 03075 } 03076 03077 return len; 03078 } 03079 03086 const char* 03087 _dbus_get_tmpdir(void) 03088 { 03089 static const char* tmpdir = NULL; 03090 03091 if (tmpdir == NULL) 03092 { 03093 /* TMPDIR is what glibc uses, then 03094 * glibc falls back to the P_tmpdir macro which 03095 * just expands to "/tmp" 03096 */ 03097 if (tmpdir == NULL) 03098 tmpdir = getenv("TMPDIR"); 03099 03100 /* These two env variables are probably 03101 * broken, but maybe some OS uses them? 03102 */ 03103 if (tmpdir == NULL) 03104 tmpdir = getenv("TMP"); 03105 if (tmpdir == NULL) 03106 tmpdir = getenv("TEMP"); 03107 03108 /* And this is the sane fallback. */ 03109 if (tmpdir == NULL) 03110 tmpdir = "/tmp"; 03111 } 03112 03113 _dbus_assert(tmpdir != NULL); 03114 03115 return tmpdir; 03116 } 03117 03137 static dbus_bool_t 03138 _read_subprocess_line_argv (const char *progpath, 03139 dbus_bool_t path_fallback, 03140 char * const *argv, 03141 DBusString *result, 03142 DBusError *error) 03143 { 03144 int result_pipe[2] = { -1, -1 }; 03145 int errors_pipe[2] = { -1, -1 }; 03146 pid_t pid; 03147 int ret; 03148 int status; 03149 int orig_len; 03150 int i; 03151 03152 dbus_bool_t retval; 03153 sigset_t new_set, old_set; 03154 03155 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03156 retval = FALSE; 03157 03158 /* We need to block any existing handlers for SIGCHLD temporarily; they 03159 * will cause waitpid() below to fail. 03160 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03161 */ 03162 sigemptyset (&new_set); 03163 sigaddset (&new_set, SIGCHLD); 03164 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03165 03166 orig_len = _dbus_string_get_length (result); 03167 03168 #define READ_END 0 03169 #define WRITE_END 1 03170 if (pipe (result_pipe) < 0) 03171 { 03172 dbus_set_error (error, _dbus_error_from_errno (errno), 03173 "Failed to create a pipe to call %s: %s", 03174 progpath, _dbus_strerror (errno)); 03175 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03176 progpath, _dbus_strerror (errno)); 03177 goto out; 03178 } 03179 if (pipe (errors_pipe) < 0) 03180 { 03181 dbus_set_error (error, _dbus_error_from_errno (errno), 03182 "Failed to create a pipe to call %s: %s", 03183 progpath, _dbus_strerror (errno)); 03184 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03185 progpath, _dbus_strerror (errno)); 03186 goto out; 03187 } 03188 03189 pid = fork (); 03190 if (pid < 0) 03191 { 03192 dbus_set_error (error, _dbus_error_from_errno (errno), 03193 "Failed to fork() to call %s: %s", 03194 progpath, _dbus_strerror (errno)); 03195 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03196 progpath, _dbus_strerror (errno)); 03197 goto out; 03198 } 03199 03200 if (pid == 0) 03201 { 03202 /* child process */ 03203 int maxfds; 03204 int fd; 03205 03206 fd = open ("/dev/null", O_RDWR); 03207 if (fd == -1) 03208 /* huh?! can't open /dev/null? */ 03209 _exit (1); 03210 03211 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03212 03213 /* set-up stdXXX */ 03214 close (result_pipe[READ_END]); 03215 close (errors_pipe[READ_END]); 03216 close (0); /* close stdin */ 03217 close (1); /* close stdout */ 03218 close (2); /* close stderr */ 03219 03220 if (dup2 (fd, 0) == -1) 03221 _exit (1); 03222 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03223 _exit (1); 03224 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03225 _exit (1); 03226 03227 maxfds = sysconf (_SC_OPEN_MAX); 03228 /* Pick something reasonable if for some reason sysconf 03229 * says unlimited. 03230 */ 03231 if (maxfds < 0) 03232 maxfds = 1024; 03233 /* close all inherited fds */ 03234 for (i = 3; i < maxfds; i++) 03235 close (i); 03236 03237 sigprocmask (SIG_SETMASK, &old_set, NULL); 03238 03239 /* If it looks fully-qualified, try execv first */ 03240 if (progpath[0] == '/') 03241 { 03242 execv (progpath, argv); 03243 /* Ok, that failed. Now if path_fallback is given, let's 03244 * try unqualified. This is mostly a hack to work 03245 * around systems which ship dbus-launch in /usr/bin 03246 * but everything else in /bin (because dbus-launch 03247 * depends on X11). 03248 */ 03249 if (path_fallback) 03250 /* We must have a slash, because we checked above */ 03251 execvp (strrchr (progpath, '/')+1, argv); 03252 } 03253 else 03254 execvp (progpath, argv); 03255 03256 /* still nothing, we failed */ 03257 _exit (1); 03258 } 03259 03260 /* parent process */ 03261 close (result_pipe[WRITE_END]); 03262 close (errors_pipe[WRITE_END]); 03263 result_pipe[WRITE_END] = -1; 03264 errors_pipe[WRITE_END] = -1; 03265 03266 ret = 0; 03267 do 03268 { 03269 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03270 } 03271 while (ret > 0); 03272 03273 /* reap the child process to avoid it lingering as zombie */ 03274 do 03275 { 03276 ret = waitpid (pid, &status, 0); 03277 } 03278 while (ret == -1 && errno == EINTR); 03279 03280 /* We succeeded if the process exited with status 0 and 03281 anything was read */ 03282 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03283 { 03284 /* The process ended with error */ 03285 DBusString error_message; 03286 if (!_dbus_string_init (&error_message)) 03287 { 03288 _DBUS_SET_OOM (error); 03289 goto out; 03290 } 03291 03292 ret = 0; 03293 do 03294 { 03295 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03296 } 03297 while (ret > 0); 03298 03299 _dbus_string_set_length (result, orig_len); 03300 if (_dbus_string_get_length (&error_message) > 0) 03301 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03302 "%s terminated abnormally with the following error: %s", 03303 progpath, _dbus_string_get_data (&error_message)); 03304 else 03305 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03306 "%s terminated abnormally without any error message", 03307 progpath); 03308 goto out; 03309 } 03310 03311 retval = TRUE; 03312 03313 out: 03314 sigprocmask (SIG_SETMASK, &old_set, NULL); 03315 03316 if (retval) 03317 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03318 else 03319 _DBUS_ASSERT_ERROR_IS_SET (error); 03320 03321 if (result_pipe[0] != -1) 03322 close (result_pipe[0]); 03323 if (result_pipe[1] != -1) 03324 close (result_pipe[1]); 03325 if (errors_pipe[0] != -1) 03326 close (errors_pipe[0]); 03327 if (errors_pipe[1] != -1) 03328 close (errors_pipe[1]); 03329 03330 return retval; 03331 } 03332 03344 dbus_bool_t 03345 _dbus_get_autolaunch_address (const char *scope, 03346 DBusString *address, 03347 DBusError *error) 03348 { 03349 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03350 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03351 * but that's done elsewhere, and if it worked, this function wouldn't 03352 * be called.) */ 03353 const char *display; 03354 static char *argv[6]; 03355 int i; 03356 DBusString uuid; 03357 dbus_bool_t retval; 03358 03359 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03360 retval = FALSE; 03361 03362 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03363 * dbus-launch-x11 is just going to fail. Rather than trying to 03364 * run it, we might as well bail out early with a nice error. */ 03365 display = _dbus_getenv ("DISPLAY"); 03366 03367 if (display == NULL || display[0] == '\0') 03368 { 03369 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03370 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03371 return FALSE; 03372 } 03373 03374 if (!_dbus_string_init (&uuid)) 03375 { 03376 _DBUS_SET_OOM (error); 03377 return FALSE; 03378 } 03379 03380 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03381 { 03382 _DBUS_SET_OOM (error); 03383 goto out; 03384 } 03385 03386 i = 0; 03387 argv[i] = "dbus-launch"; 03388 ++i; 03389 argv[i] = "--autolaunch"; 03390 ++i; 03391 argv[i] = _dbus_string_get_data (&uuid); 03392 ++i; 03393 argv[i] = "--binary-syntax"; 03394 ++i; 03395 argv[i] = "--close-stderr"; 03396 ++i; 03397 argv[i] = NULL; 03398 ++i; 03399 03400 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03401 03402 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03403 TRUE, 03404 argv, address, error); 03405 03406 out: 03407 _dbus_string_free (&uuid); 03408 return retval; 03409 #else 03410 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03411 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03412 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03413 return FALSE; 03414 #endif 03415 } 03416 03435 dbus_bool_t 03436 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03437 dbus_bool_t create_if_not_found, 03438 DBusError *error) 03439 { 03440 DBusString filename; 03441 dbus_bool_t b; 03442 03443 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03444 03445 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03446 if (b) 03447 return TRUE; 03448 03449 dbus_error_free (error); 03450 03451 /* Fallback to the system machine ID */ 03452 _dbus_string_init_const (&filename, "/etc/machine-id"); 03453 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03454 } 03455 03456 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03457 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03458 03465 dbus_bool_t 03466 _dbus_lookup_launchd_socket (DBusString *socket_path, 03467 const char *launchd_env_var, 03468 DBusError *error) 03469 { 03470 #ifdef DBUS_ENABLE_LAUNCHD 03471 char *argv[4]; 03472 int i; 03473 03474 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03475 03476 i = 0; 03477 argv[i] = "launchctl"; 03478 ++i; 03479 argv[i] = "getenv"; 03480 ++i; 03481 argv[i] = (char*)launchd_env_var; 03482 ++i; 03483 argv[i] = NULL; 03484 ++i; 03485 03486 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03487 03488 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03489 { 03490 return FALSE; 03491 } 03492 03493 /* no error, but no result either */ 03494 if (_dbus_string_get_length(socket_path) == 0) 03495 { 03496 return FALSE; 03497 } 03498 03499 /* strip the carriage-return */ 03500 _dbus_string_shorten(socket_path, 1); 03501 return TRUE; 03502 #else /* DBUS_ENABLE_LAUNCHD */ 03503 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03504 "can't lookup socket from launchd; launchd support not compiled in"); 03505 return FALSE; 03506 #endif 03507 } 03508 03509 static dbus_bool_t 03510 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03511 { 03512 #ifdef DBUS_ENABLE_LAUNCHD 03513 dbus_bool_t valid_socket; 03514 DBusString socket_path; 03515 03516 if (!_dbus_string_init (&socket_path)) 03517 { 03518 _DBUS_SET_OOM (error); 03519 return FALSE; 03520 } 03521 03522 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03523 03524 if (dbus_error_is_set(error)) 03525 { 03526 _dbus_string_free(&socket_path); 03527 return FALSE; 03528 } 03529 03530 if (!valid_socket) 03531 { 03532 dbus_set_error(error, "no socket path", 03533 "launchd did not provide a socket path, " 03534 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03535 _dbus_string_free(&socket_path); 03536 return FALSE; 03537 } 03538 if (!_dbus_string_append (address, "unix:path=")) 03539 { 03540 _DBUS_SET_OOM (error); 03541 _dbus_string_free(&socket_path); 03542 return FALSE; 03543 } 03544 if (!_dbus_string_copy (&socket_path, 0, address, 03545 _dbus_string_get_length (address))) 03546 { 03547 _DBUS_SET_OOM (error); 03548 _dbus_string_free(&socket_path); 03549 return FALSE; 03550 } 03551 03552 _dbus_string_free(&socket_path); 03553 return TRUE; 03554 #else 03555 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03556 "can't lookup session address from launchd; launchd support not compiled in"); 03557 return FALSE; 03558 #endif 03559 } 03560 03580 dbus_bool_t 03581 _dbus_lookup_session_address (dbus_bool_t *supported, 03582 DBusString *address, 03583 DBusError *error) 03584 { 03585 #ifdef DBUS_ENABLE_LAUNCHD 03586 *supported = TRUE; 03587 return _dbus_lookup_session_address_launchd (address, error); 03588 #else 03589 /* On non-Mac Unix platforms, if the session address isn't already 03590 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03591 * fall back to the autolaunch: global default; see 03592 * init_session_address in dbus/dbus-bus.c. */ 03593 *supported = FALSE; 03594 return TRUE; 03595 #endif 03596 } 03597 03615 dbus_bool_t 03616 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03617 { 03618 const char *xdg_data_home; 03619 const char *xdg_data_dirs; 03620 DBusString servicedir_path; 03621 03622 if (!_dbus_string_init (&servicedir_path)) 03623 return FALSE; 03624 03625 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03626 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03627 03628 if (xdg_data_home != NULL) 03629 { 03630 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03631 goto oom; 03632 } 03633 else 03634 { 03635 const DBusString *homedir; 03636 DBusString local_share; 03637 03638 if (!_dbus_homedir_from_current_process (&homedir)) 03639 goto oom; 03640 03641 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03642 goto oom; 03643 03644 _dbus_string_init_const (&local_share, "/.local/share"); 03645 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03646 goto oom; 03647 } 03648 03649 if (!_dbus_string_append (&servicedir_path, ":")) 03650 goto oom; 03651 03652 if (xdg_data_dirs != NULL) 03653 { 03654 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03655 goto oom; 03656 03657 if (!_dbus_string_append (&servicedir_path, ":")) 03658 goto oom; 03659 } 03660 else 03661 { 03662 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03663 goto oom; 03664 } 03665 03666 /* 03667 * add configured datadir to defaults 03668 * this may be the same as an xdg dir 03669 * however the config parser should take 03670 * care of duplicates 03671 */ 03672 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03673 goto oom; 03674 03675 if (!_dbus_split_paths_and_append (&servicedir_path, 03676 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03677 dirs)) 03678 goto oom; 03679 03680 _dbus_string_free (&servicedir_path); 03681 return TRUE; 03682 03683 oom: 03684 _dbus_string_free (&servicedir_path); 03685 return FALSE; 03686 } 03687 03688 03707 dbus_bool_t 03708 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03709 { 03710 const char *xdg_data_dirs; 03711 DBusString servicedir_path; 03712 03713 if (!_dbus_string_init (&servicedir_path)) 03714 return FALSE; 03715 03716 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03717 03718 if (xdg_data_dirs != NULL) 03719 { 03720 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03721 goto oom; 03722 03723 if (!_dbus_string_append (&servicedir_path, ":")) 03724 goto oom; 03725 } 03726 else 03727 { 03728 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03729 goto oom; 03730 } 03731 03732 /* 03733 * Add configured datadir to defaults. This may be the same as one 03734 * of the XDG directories. However, the config parser should take 03735 * care of the duplicates. 03736 * 03737 * Also, append /lib as counterpart of /usr/share on the root 03738 * directory (the root directory does not know /share), in order to 03739 * facilitate early boot system bus activation where /usr might not 03740 * be available. 03741 */ 03742 if (!_dbus_string_append (&servicedir_path, 03743 DBUS_DATADIR":" 03744 "/lib:")) 03745 goto oom; 03746 03747 if (!_dbus_split_paths_and_append (&servicedir_path, 03748 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03749 dirs)) 03750 goto oom; 03751 03752 _dbus_string_free (&servicedir_path); 03753 return TRUE; 03754 03755 oom: 03756 _dbus_string_free (&servicedir_path); 03757 return FALSE; 03758 } 03759 03768 dbus_bool_t 03769 _dbus_append_system_config_file (DBusString *str) 03770 { 03771 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03772 } 03773 03780 dbus_bool_t 03781 _dbus_append_session_config_file (DBusString *str) 03782 { 03783 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03784 } 03785 03793 void 03794 _dbus_flush_caches (void) 03795 { 03796 _dbus_user_database_flush_system (); 03797 } 03798 03812 dbus_bool_t 03813 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03814 DBusCredentials *credentials) 03815 { 03816 DBusString homedir; 03817 DBusString dotdir; 03818 dbus_uid_t uid; 03819 03820 _dbus_assert (credentials != NULL); 03821 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03822 03823 if (!_dbus_string_init (&homedir)) 03824 return FALSE; 03825 03826 uid = _dbus_credentials_get_unix_uid (credentials); 03827 _dbus_assert (uid != DBUS_UID_UNSET); 03828 03829 if (!_dbus_homedir_from_uid (uid, &homedir)) 03830 goto failed; 03831 03832 #ifdef DBUS_BUILD_TESTS 03833 { 03834 const char *override; 03835 03836 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03837 if (override != NULL && *override != '\0') 03838 { 03839 _dbus_string_set_length (&homedir, 0); 03840 if (!_dbus_string_append (&homedir, override)) 03841 goto failed; 03842 03843 _dbus_verbose ("Using fake homedir for testing: %s\n", 03844 _dbus_string_get_const_data (&homedir)); 03845 } 03846 else 03847 { 03848 static dbus_bool_t already_warned = FALSE; 03849 if (!already_warned) 03850 { 03851 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03852 already_warned = TRUE; 03853 } 03854 } 03855 } 03856 #endif 03857 03858 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03859 if (!_dbus_concat_dir_and_file (&homedir, 03860 &dotdir)) 03861 goto failed; 03862 03863 if (!_dbus_string_copy (&homedir, 0, 03864 directory, _dbus_string_get_length (directory))) { 03865 goto failed; 03866 } 03867 03868 _dbus_string_free (&homedir); 03869 return TRUE; 03870 03871 failed: 03872 _dbus_string_free (&homedir); 03873 return FALSE; 03874 } 03875 03876 //PENDING(kdab) docs 03877 dbus_bool_t 03878 _dbus_daemon_publish_session_bus_address (const char* addr, 03879 const char *scope) 03880 { 03881 return TRUE; 03882 } 03883 03884 //PENDING(kdab) docs 03885 void 03886 _dbus_daemon_unpublish_session_bus_address (void) 03887 { 03888 03889 } 03890 03897 dbus_bool_t 03898 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03899 { 03900 return errno == EAGAIN || errno == EWOULDBLOCK; 03901 } 03902 03910 dbus_bool_t 03911 _dbus_delete_directory (const DBusString *filename, 03912 DBusError *error) 03913 { 03914 const char *filename_c; 03915 03916 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03917 03918 filename_c = _dbus_string_get_const_data (filename); 03919 03920 if (rmdir (filename_c) != 0) 03921 { 03922 dbus_set_error (error, DBUS_ERROR_FAILED, 03923 "Failed to remove directory %s: %s\n", 03924 filename_c, _dbus_strerror (errno)); 03925 return FALSE; 03926 } 03927 03928 return TRUE; 03929 } 03930 03938 dbus_bool_t 03939 _dbus_socket_can_pass_unix_fd(int fd) { 03940 03941 #ifdef SCM_RIGHTS 03942 union { 03943 struct sockaddr sa; 03944 struct sockaddr_storage storage; 03945 struct sockaddr_un un; 03946 } sa_buf; 03947 03948 socklen_t sa_len = sizeof(sa_buf); 03949 03950 _DBUS_ZERO(sa_buf); 03951 03952 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03953 return FALSE; 03954 03955 return sa_buf.sa.sa_family == AF_UNIX; 03956 03957 #else 03958 return FALSE; 03959 03960 #endif 03961 } 03962 03963 03964 /* 03965 * replaces the term DBUS_PREFIX in configure_time_path by the 03966 * current dbus installation directory. On unix this function is a noop 03967 * 03968 * @param configure_time_path 03969 * @return real path 03970 */ 03971 const char * 03972 _dbus_replace_install_prefix (const char *configure_time_path) 03973 { 03974 return configure_time_path; 03975 } 03976 03977 /* tests in dbus-sysdeps-util.c */