D-Bus
1.4.16
|
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 _dbus_close (fd, NULL); 01220 return -1; 01221 } 01222 01223 tmp = ai; 01224 while (tmp) 01225 { 01226 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01227 { 01228 freeaddrinfo(ai); 01229 _DBUS_ASSERT_ERROR_IS_SET(error); 01230 return -1; 01231 } 01232 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01233 01234 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01235 { 01236 saved_errno = errno; 01237 _dbus_close(fd, NULL); 01238 fd = -1; 01239 tmp = tmp->ai_next; 01240 continue; 01241 } 01242 01243 break; 01244 } 01245 freeaddrinfo(ai); 01246 01247 if (fd == -1) 01248 { 01249 dbus_set_error (error, 01250 _dbus_error_from_errno (saved_errno), 01251 "Failed to connect to socket \"%s:%s\" %s", 01252 host, port, _dbus_strerror(saved_errno)); 01253 return -1; 01254 } 01255 01256 if (noncefile != NULL) 01257 { 01258 DBusString noncefileStr; 01259 dbus_bool_t ret; 01260 _dbus_string_init_const (&noncefileStr, noncefile); 01261 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01262 _dbus_string_free (&noncefileStr); 01263 01264 if (!ret) 01265 { 01266 _dbus_close (fd, NULL); 01267 return -1; 01268 } 01269 } 01270 01271 if (!_dbus_set_fd_nonblocking (fd, error)) 01272 { 01273 _dbus_close (fd, NULL); 01274 return -1; 01275 } 01276 01277 return fd; 01278 } 01279 01296 int 01297 _dbus_listen_tcp_socket (const char *host, 01298 const char *port, 01299 const char *family, 01300 DBusString *retport, 01301 int **fds_p, 01302 DBusError *error) 01303 { 01304 int saved_errno; 01305 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01306 struct addrinfo hints; 01307 struct addrinfo *ai, *tmp; 01308 unsigned int reuseaddr; 01309 01310 *fds_p = NULL; 01311 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01312 01313 _DBUS_ZERO (hints); 01314 01315 if (!family) 01316 hints.ai_family = AF_UNSPEC; 01317 else if (!strcmp(family, "ipv4")) 01318 hints.ai_family = AF_INET; 01319 else if (!strcmp(family, "ipv6")) 01320 hints.ai_family = AF_INET6; 01321 else 01322 { 01323 dbus_set_error (error, 01324 DBUS_ERROR_BAD_ADDRESS, 01325 "Unknown address family %s", family); 01326 return -1; 01327 } 01328 01329 hints.ai_protocol = IPPROTO_TCP; 01330 hints.ai_socktype = SOCK_STREAM; 01331 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01332 01333 redo_lookup_with_port: 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 return -1; 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 if (_dbus_check_setuid ()) 03360 { 03361 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03362 "Unable to autolaunch when setuid"); 03363 return FALSE; 03364 } 03365 03366 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03367 retval = FALSE; 03368 03369 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03370 * dbus-launch-x11 is just going to fail. Rather than trying to 03371 * run it, we might as well bail out early with a nice error. */ 03372 display = _dbus_getenv ("DISPLAY"); 03373 03374 if (display == NULL || display[0] == '\0') 03375 { 03376 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03377 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03378 return FALSE; 03379 } 03380 03381 if (!_dbus_string_init (&uuid)) 03382 { 03383 _DBUS_SET_OOM (error); 03384 return FALSE; 03385 } 03386 03387 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03388 { 03389 _DBUS_SET_OOM (error); 03390 goto out; 03391 } 03392 03393 i = 0; 03394 argv[i] = "dbus-launch"; 03395 ++i; 03396 argv[i] = "--autolaunch"; 03397 ++i; 03398 argv[i] = _dbus_string_get_data (&uuid); 03399 ++i; 03400 argv[i] = "--binary-syntax"; 03401 ++i; 03402 argv[i] = "--close-stderr"; 03403 ++i; 03404 argv[i] = NULL; 03405 ++i; 03406 03407 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03408 03409 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03410 TRUE, 03411 argv, address, error); 03412 03413 out: 03414 _dbus_string_free (&uuid); 03415 return retval; 03416 #else 03417 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03418 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03419 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03420 return FALSE; 03421 #endif 03422 } 03423 03442 dbus_bool_t 03443 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03444 dbus_bool_t create_if_not_found, 03445 DBusError *error) 03446 { 03447 DBusString filename; 03448 dbus_bool_t b; 03449 03450 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03451 03452 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03453 if (b) 03454 return TRUE; 03455 03456 dbus_error_free (error); 03457 03458 /* Fallback to the system machine ID */ 03459 _dbus_string_init_const (&filename, "/etc/machine-id"); 03460 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03461 } 03462 03463 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03464 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03465 03472 dbus_bool_t 03473 _dbus_lookup_launchd_socket (DBusString *socket_path, 03474 const char *launchd_env_var, 03475 DBusError *error) 03476 { 03477 #ifdef DBUS_ENABLE_LAUNCHD 03478 char *argv[4]; 03479 int i; 03480 03481 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03482 03483 if (_dbus_check_setuid ()) 03484 { 03485 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03486 "Unable to find launchd socket when setuid"); 03487 return FALSE; 03488 } 03489 03490 i = 0; 03491 argv[i] = "launchctl"; 03492 ++i; 03493 argv[i] = "getenv"; 03494 ++i; 03495 argv[i] = (char*)launchd_env_var; 03496 ++i; 03497 argv[i] = NULL; 03498 ++i; 03499 03500 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03501 03502 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03503 { 03504 return FALSE; 03505 } 03506 03507 /* no error, but no result either */ 03508 if (_dbus_string_get_length(socket_path) == 0) 03509 { 03510 return FALSE; 03511 } 03512 03513 /* strip the carriage-return */ 03514 _dbus_string_shorten(socket_path, 1); 03515 return TRUE; 03516 #else /* DBUS_ENABLE_LAUNCHD */ 03517 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03518 "can't lookup socket from launchd; launchd support not compiled in"); 03519 return FALSE; 03520 #endif 03521 } 03522 03523 static dbus_bool_t 03524 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03525 { 03526 #ifdef DBUS_ENABLE_LAUNCHD 03527 dbus_bool_t valid_socket; 03528 DBusString socket_path; 03529 03530 if (_dbus_check_setuid ()) 03531 { 03532 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03533 "Unable to find launchd socket when setuid"); 03534 return FALSE; 03535 } 03536 03537 if (!_dbus_string_init (&socket_path)) 03538 { 03539 _DBUS_SET_OOM (error); 03540 return FALSE; 03541 } 03542 03543 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03544 03545 if (dbus_error_is_set(error)) 03546 { 03547 _dbus_string_free(&socket_path); 03548 return FALSE; 03549 } 03550 03551 if (!valid_socket) 03552 { 03553 dbus_set_error(error, "no socket path", 03554 "launchd did not provide a socket path, " 03555 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03556 _dbus_string_free(&socket_path); 03557 return FALSE; 03558 } 03559 if (!_dbus_string_append (address, "unix:path=")) 03560 { 03561 _DBUS_SET_OOM (error); 03562 _dbus_string_free(&socket_path); 03563 return FALSE; 03564 } 03565 if (!_dbus_string_copy (&socket_path, 0, address, 03566 _dbus_string_get_length (address))) 03567 { 03568 _DBUS_SET_OOM (error); 03569 _dbus_string_free(&socket_path); 03570 return FALSE; 03571 } 03572 03573 _dbus_string_free(&socket_path); 03574 return TRUE; 03575 #else 03576 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03577 "can't lookup session address from launchd; launchd support not compiled in"); 03578 return FALSE; 03579 #endif 03580 } 03581 03601 dbus_bool_t 03602 _dbus_lookup_session_address (dbus_bool_t *supported, 03603 DBusString *address, 03604 DBusError *error) 03605 { 03606 #ifdef DBUS_ENABLE_LAUNCHD 03607 *supported = TRUE; 03608 return _dbus_lookup_session_address_launchd (address, error); 03609 #else 03610 /* On non-Mac Unix platforms, if the session address isn't already 03611 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03612 * fall back to the autolaunch: global default; see 03613 * init_session_address in dbus/dbus-bus.c. */ 03614 *supported = FALSE; 03615 return TRUE; 03616 #endif 03617 } 03618 03636 dbus_bool_t 03637 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03638 { 03639 const char *xdg_data_home; 03640 const char *xdg_data_dirs; 03641 DBusString servicedir_path; 03642 03643 if (!_dbus_string_init (&servicedir_path)) 03644 return FALSE; 03645 03646 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03647 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03648 03649 if (xdg_data_home != NULL) 03650 { 03651 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03652 goto oom; 03653 } 03654 else 03655 { 03656 const DBusString *homedir; 03657 DBusString local_share; 03658 03659 if (!_dbus_homedir_from_current_process (&homedir)) 03660 goto oom; 03661 03662 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03663 goto oom; 03664 03665 _dbus_string_init_const (&local_share, "/.local/share"); 03666 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03667 goto oom; 03668 } 03669 03670 if (!_dbus_string_append (&servicedir_path, ":")) 03671 goto oom; 03672 03673 if (xdg_data_dirs != NULL) 03674 { 03675 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03676 goto oom; 03677 03678 if (!_dbus_string_append (&servicedir_path, ":")) 03679 goto oom; 03680 } 03681 else 03682 { 03683 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03684 goto oom; 03685 } 03686 03687 /* 03688 * add configured datadir to defaults 03689 * this may be the same as an xdg dir 03690 * however the config parser should take 03691 * care of duplicates 03692 */ 03693 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03694 goto oom; 03695 03696 if (!_dbus_split_paths_and_append (&servicedir_path, 03697 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03698 dirs)) 03699 goto oom; 03700 03701 _dbus_string_free (&servicedir_path); 03702 return TRUE; 03703 03704 oom: 03705 _dbus_string_free (&servicedir_path); 03706 return FALSE; 03707 } 03708 03709 03728 dbus_bool_t 03729 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03730 { 03731 const char *xdg_data_dirs; 03732 DBusString servicedir_path; 03733 03734 if (!_dbus_string_init (&servicedir_path)) 03735 return FALSE; 03736 03737 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03738 03739 if (xdg_data_dirs != NULL) 03740 { 03741 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03742 goto oom; 03743 03744 if (!_dbus_string_append (&servicedir_path, ":")) 03745 goto oom; 03746 } 03747 else 03748 { 03749 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03750 goto oom; 03751 } 03752 03753 /* 03754 * Add configured datadir to defaults. This may be the same as one 03755 * of the XDG directories. However, the config parser should take 03756 * care of the duplicates. 03757 * 03758 * Also, append /lib as counterpart of /usr/share on the root 03759 * directory (the root directory does not know /share), in order to 03760 * facilitate early boot system bus activation where /usr might not 03761 * be available. 03762 */ 03763 if (!_dbus_string_append (&servicedir_path, 03764 DBUS_DATADIR":" 03765 "/lib:")) 03766 goto oom; 03767 03768 if (!_dbus_split_paths_and_append (&servicedir_path, 03769 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03770 dirs)) 03771 goto oom; 03772 03773 _dbus_string_free (&servicedir_path); 03774 return TRUE; 03775 03776 oom: 03777 _dbus_string_free (&servicedir_path); 03778 return FALSE; 03779 } 03780 03789 dbus_bool_t 03790 _dbus_append_system_config_file (DBusString *str) 03791 { 03792 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03793 } 03794 03801 dbus_bool_t 03802 _dbus_append_session_config_file (DBusString *str) 03803 { 03804 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03805 } 03806 03814 void 03815 _dbus_flush_caches (void) 03816 { 03817 _dbus_user_database_flush_system (); 03818 } 03819 03833 dbus_bool_t 03834 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03835 DBusCredentials *credentials) 03836 { 03837 DBusString homedir; 03838 DBusString dotdir; 03839 dbus_uid_t uid; 03840 03841 _dbus_assert (credentials != NULL); 03842 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03843 03844 if (!_dbus_string_init (&homedir)) 03845 return FALSE; 03846 03847 uid = _dbus_credentials_get_unix_uid (credentials); 03848 _dbus_assert (uid != DBUS_UID_UNSET); 03849 03850 if (!_dbus_homedir_from_uid (uid, &homedir)) 03851 goto failed; 03852 03853 #ifdef DBUS_BUILD_TESTS 03854 { 03855 const char *override; 03856 03857 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03858 if (override != NULL && *override != '\0') 03859 { 03860 _dbus_string_set_length (&homedir, 0); 03861 if (!_dbus_string_append (&homedir, override)) 03862 goto failed; 03863 03864 _dbus_verbose ("Using fake homedir for testing: %s\n", 03865 _dbus_string_get_const_data (&homedir)); 03866 } 03867 else 03868 { 03869 static dbus_bool_t already_warned = FALSE; 03870 if (!already_warned) 03871 { 03872 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03873 already_warned = TRUE; 03874 } 03875 } 03876 } 03877 #endif 03878 03879 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03880 if (!_dbus_concat_dir_and_file (&homedir, 03881 &dotdir)) 03882 goto failed; 03883 03884 if (!_dbus_string_copy (&homedir, 0, 03885 directory, _dbus_string_get_length (directory))) { 03886 goto failed; 03887 } 03888 03889 _dbus_string_free (&homedir); 03890 return TRUE; 03891 03892 failed: 03893 _dbus_string_free (&homedir); 03894 return FALSE; 03895 } 03896 03897 //PENDING(kdab) docs 03898 dbus_bool_t 03899 _dbus_daemon_publish_session_bus_address (const char* addr, 03900 const char *scope) 03901 { 03902 return TRUE; 03903 } 03904 03905 //PENDING(kdab) docs 03906 void 03907 _dbus_daemon_unpublish_session_bus_address (void) 03908 { 03909 03910 } 03911 03918 dbus_bool_t 03919 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03920 { 03921 return errno == EAGAIN || errno == EWOULDBLOCK; 03922 } 03923 03931 dbus_bool_t 03932 _dbus_delete_directory (const DBusString *filename, 03933 DBusError *error) 03934 { 03935 const char *filename_c; 03936 03937 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03938 03939 filename_c = _dbus_string_get_const_data (filename); 03940 03941 if (rmdir (filename_c) != 0) 03942 { 03943 dbus_set_error (error, DBUS_ERROR_FAILED, 03944 "Failed to remove directory %s: %s\n", 03945 filename_c, _dbus_strerror (errno)); 03946 return FALSE; 03947 } 03948 03949 return TRUE; 03950 } 03951 03959 dbus_bool_t 03960 _dbus_socket_can_pass_unix_fd(int fd) { 03961 03962 #ifdef SCM_RIGHTS 03963 union { 03964 struct sockaddr sa; 03965 struct sockaddr_storage storage; 03966 struct sockaddr_un un; 03967 } sa_buf; 03968 03969 socklen_t sa_len = sizeof(sa_buf); 03970 03971 _DBUS_ZERO(sa_buf); 03972 03973 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03974 return FALSE; 03975 03976 return sa_buf.sa.sa_family == AF_UNIX; 03977 03978 #else 03979 return FALSE; 03980 03981 #endif 03982 } 03983 03984 03985 /* 03986 * replaces the term DBUS_PREFIX in configure_time_path by the 03987 * current dbus installation directory. On unix this function is a noop 03988 * 03989 * @param configure_time_path 03990 * @return real path 03991 */ 03992 const char * 03993 _dbus_replace_install_prefix (const char *configure_time_path) 03994 { 03995 return configure_time_path; 03996 } 03997 04007 dbus_bool_t 04008 _dbus_check_setuid (void) 04009 { 04010 /* TODO: get __libc_enable_secure exported from glibc. 04011 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1 04012 */ 04013 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE) 04014 { 04015 /* See glibc/include/unistd.h */ 04016 extern int __libc_enable_secure; 04017 return __libc_enable_secure; 04018 } 04019 #elif defined(HAVE_ISSETUGID) 04020 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */ 04021 return issetugid (); 04022 #else 04023 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ 04024 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ 04025 04026 static dbus_bool_t check_setuid_initialised; 04027 static dbus_bool_t is_setuid; 04028 04029 if (_DBUS_UNLIKELY (!check_setuid_initialised)) 04030 { 04031 #ifdef HAVE_GETRESUID 04032 if (getresuid (&ruid, &euid, &suid) != 0 || 04033 getresgid (&rgid, &egid, &sgid) != 0) 04034 #endif /* HAVE_GETRESUID */ 04035 { 04036 suid = ruid = getuid (); 04037 sgid = rgid = getgid (); 04038 euid = geteuid (); 04039 egid = getegid (); 04040 } 04041 04042 check_setuid_initialised = TRUE; 04043 is_setuid = (ruid != euid || ruid != suid || 04044 rgid != egid || rgid != sgid); 04045 04046 } 04047 return is_setuid; 04048 #endif 04049 } 04050 04051 /* tests in dbus-sysdeps-util.c */