|
D-Bus
1.5.8
|
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 00177 static dbus_bool_t 00178 _dbus_open_unix_socket (int *fd, 00179 DBusError *error) 00180 { 00181 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error); 00182 } 00183 00192 dbus_bool_t 00193 _dbus_close_socket (int fd, 00194 DBusError *error) 00195 { 00196 return _dbus_close (fd, error); 00197 } 00198 00208 int 00209 _dbus_read_socket (int fd, 00210 DBusString *buffer, 00211 int count) 00212 { 00213 return _dbus_read (fd, buffer, count); 00214 } 00215 00226 int 00227 _dbus_write_socket (int fd, 00228 const DBusString *buffer, 00229 int start, 00230 int len) 00231 { 00232 #if HAVE_DECL_MSG_NOSIGNAL 00233 const char *data; 00234 int bytes_written; 00235 00236 data = _dbus_string_get_const_data_len (buffer, start, len); 00237 00238 again: 00239 00240 bytes_written = send (fd, data, len, MSG_NOSIGNAL); 00241 00242 if (bytes_written < 0 && errno == EINTR) 00243 goto again; 00244 00245 return bytes_written; 00246 00247 #else 00248 return _dbus_write (fd, buffer, start, len); 00249 #endif 00250 } 00251 00264 int 00265 _dbus_read_socket_with_unix_fds (int fd, 00266 DBusString *buffer, 00267 int count, 00268 int *fds, 00269 int *n_fds) { 00270 #ifndef HAVE_UNIX_FD_PASSING 00271 int r; 00272 00273 if ((r = _dbus_read_socket(fd, buffer, count)) < 0) 00274 return r; 00275 00276 *n_fds = 0; 00277 return r; 00278 00279 #else 00280 int bytes_read; 00281 int start; 00282 struct msghdr m; 00283 struct iovec iov; 00284 00285 _dbus_assert (count >= 0); 00286 _dbus_assert (*n_fds >= 0); 00287 00288 start = _dbus_string_get_length (buffer); 00289 00290 if (!_dbus_string_lengthen (buffer, count)) 00291 { 00292 errno = ENOMEM; 00293 return -1; 00294 } 00295 00296 _DBUS_ZERO(iov); 00297 iov.iov_base = _dbus_string_get_data_len (buffer, start, count); 00298 iov.iov_len = count; 00299 00300 _DBUS_ZERO(m); 00301 m.msg_iov = &iov; 00302 m.msg_iovlen = 1; 00303 00304 /* Hmm, we have no clue how long the control data will actually be 00305 that is queued for us. The least we can do is assume that the 00306 caller knows. Hence let's make space for the number of fds that 00307 we shall read at max plus the cmsg header. */ 00308 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int)); 00309 00310 /* It's probably safe to assume that systems with SCM_RIGHTS also 00311 know alloca() */ 00312 m.msg_control = alloca(m.msg_controllen); 00313 memset(m.msg_control, 0, m.msg_controllen); 00314 00315 again: 00316 00317 bytes_read = recvmsg(fd, &m, 0 00318 #ifdef MSG_CMSG_CLOEXEC 00319 |MSG_CMSG_CLOEXEC 00320 #endif 00321 ); 00322 00323 if (bytes_read < 0) 00324 { 00325 if (errno == EINTR) 00326 goto again; 00327 else 00328 { 00329 /* put length back (note that this doesn't actually realloc anything) */ 00330 _dbus_string_set_length (buffer, start); 00331 return -1; 00332 } 00333 } 00334 else 00335 { 00336 struct cmsghdr *cm; 00337 dbus_bool_t found = FALSE; 00338 00339 if (m.msg_flags & MSG_CTRUNC) 00340 { 00341 /* Hmm, apparently the control data was truncated. The bad 00342 thing is that we might have completely lost a couple of fds 00343 without chance to recover them. Hence let's treat this as a 00344 serious error. */ 00345 00346 errno = ENOSPC; 00347 _dbus_string_set_length (buffer, start); 00348 return -1; 00349 } 00350 00351 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) 00352 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) 00353 { 00354 unsigned i; 00355 00356 _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int))); 00357 *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int); 00358 00359 memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int)); 00360 found = TRUE; 00361 00362 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually 00363 worked, hence we need to go through this list and set 00364 CLOEXEC everywhere in any case */ 00365 for (i = 0; i < *n_fds; i++) 00366 _dbus_fd_set_close_on_exec(fds[i]); 00367 00368 break; 00369 } 00370 00371 if (!found) 00372 *n_fds = 0; 00373 00374 /* put length back (doesn't actually realloc) */ 00375 _dbus_string_set_length (buffer, start + bytes_read); 00376 00377 #if 0 00378 if (bytes_read > 0) 00379 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00380 #endif 00381 00382 return bytes_read; 00383 } 00384 #endif 00385 } 00386 00387 int 00388 _dbus_write_socket_with_unix_fds(int fd, 00389 const DBusString *buffer, 00390 int start, 00391 int len, 00392 const int *fds, 00393 int n_fds) { 00394 00395 #ifndef HAVE_UNIX_FD_PASSING 00396 00397 if (n_fds > 0) { 00398 errno = ENOTSUP; 00399 return -1; 00400 } 00401 00402 return _dbus_write_socket(fd, buffer, start, len); 00403 #else 00404 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds); 00405 #endif 00406 } 00407 00408 int 00409 _dbus_write_socket_with_unix_fds_two(int fd, 00410 const DBusString *buffer1, 00411 int start1, 00412 int len1, 00413 const DBusString *buffer2, 00414 int start2, 00415 int len2, 00416 const int *fds, 00417 int n_fds) { 00418 00419 #ifndef HAVE_UNIX_FD_PASSING 00420 00421 if (n_fds > 0) { 00422 errno = ENOTSUP; 00423 return -1; 00424 } 00425 00426 return _dbus_write_socket_two(fd, 00427 buffer1, start1, len1, 00428 buffer2, start2, len2); 00429 #else 00430 00431 struct msghdr m; 00432 struct cmsghdr *cm; 00433 struct iovec iov[2]; 00434 int bytes_written; 00435 00436 _dbus_assert (len1 >= 0); 00437 _dbus_assert (len2 >= 0); 00438 _dbus_assert (n_fds >= 0); 00439 00440 _DBUS_ZERO(iov); 00441 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1); 00442 iov[0].iov_len = len1; 00443 00444 if (buffer2) 00445 { 00446 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2); 00447 iov[1].iov_len = len2; 00448 } 00449 00450 _DBUS_ZERO(m); 00451 m.msg_iov = iov; 00452 m.msg_iovlen = buffer2 ? 2 : 1; 00453 00454 if (n_fds > 0) 00455 { 00456 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int)); 00457 m.msg_control = alloca(m.msg_controllen); 00458 memset(m.msg_control, 0, m.msg_controllen); 00459 00460 cm = CMSG_FIRSTHDR(&m); 00461 cm->cmsg_level = SOL_SOCKET; 00462 cm->cmsg_type = SCM_RIGHTS; 00463 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int)); 00464 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int)); 00465 } 00466 00467 again: 00468 00469 bytes_written = sendmsg (fd, &m, 0 00470 #if HAVE_DECL_MSG_NOSIGNAL 00471 |MSG_NOSIGNAL 00472 #endif 00473 ); 00474 00475 if (bytes_written < 0 && errno == EINTR) 00476 goto again; 00477 00478 #if 0 00479 if (bytes_written > 0) 00480 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00481 #endif 00482 00483 return bytes_written; 00484 #endif 00485 } 00486 00500 int 00501 _dbus_write_socket_two (int fd, 00502 const DBusString *buffer1, 00503 int start1, 00504 int len1, 00505 const DBusString *buffer2, 00506 int start2, 00507 int len2) 00508 { 00509 #if HAVE_DECL_MSG_NOSIGNAL 00510 struct iovec vectors[2]; 00511 const char *data1; 00512 const char *data2; 00513 int bytes_written; 00514 struct msghdr m; 00515 00516 _dbus_assert (buffer1 != NULL); 00517 _dbus_assert (start1 >= 0); 00518 _dbus_assert (start2 >= 0); 00519 _dbus_assert (len1 >= 0); 00520 _dbus_assert (len2 >= 0); 00521 00522 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00523 00524 if (buffer2 != NULL) 00525 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00526 else 00527 { 00528 data2 = NULL; 00529 start2 = 0; 00530 len2 = 0; 00531 } 00532 00533 vectors[0].iov_base = (char*) data1; 00534 vectors[0].iov_len = len1; 00535 vectors[1].iov_base = (char*) data2; 00536 vectors[1].iov_len = len2; 00537 00538 _DBUS_ZERO(m); 00539 m.msg_iov = vectors; 00540 m.msg_iovlen = data2 ? 2 : 1; 00541 00542 again: 00543 00544 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL); 00545 00546 if (bytes_written < 0 && errno == EINTR) 00547 goto again; 00548 00549 return bytes_written; 00550 00551 #else 00552 return _dbus_write_two (fd, buffer1, start1, len1, 00553 buffer2, start2, len2); 00554 #endif 00555 } 00556 00557 dbus_bool_t 00558 _dbus_socket_is_invalid (int fd) 00559 { 00560 return fd < 0 ? TRUE : FALSE; 00561 } 00562 00579 int 00580 _dbus_read (int fd, 00581 DBusString *buffer, 00582 int count) 00583 { 00584 int bytes_read; 00585 int start; 00586 char *data; 00587 00588 _dbus_assert (count >= 0); 00589 00590 start = _dbus_string_get_length (buffer); 00591 00592 if (!_dbus_string_lengthen (buffer, count)) 00593 { 00594 errno = ENOMEM; 00595 return -1; 00596 } 00597 00598 data = _dbus_string_get_data_len (buffer, start, count); 00599 00600 again: 00601 00602 bytes_read = read (fd, data, count); 00603 00604 if (bytes_read < 0) 00605 { 00606 if (errno == EINTR) 00607 goto again; 00608 else 00609 { 00610 /* put length back (note that this doesn't actually realloc anything) */ 00611 _dbus_string_set_length (buffer, start); 00612 return -1; 00613 } 00614 } 00615 else 00616 { 00617 /* put length back (doesn't actually realloc) */ 00618 _dbus_string_set_length (buffer, start + bytes_read); 00619 00620 #if 0 00621 if (bytes_read > 0) 00622 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00623 #endif 00624 00625 return bytes_read; 00626 } 00627 } 00628 00639 int 00640 _dbus_write (int fd, 00641 const DBusString *buffer, 00642 int start, 00643 int len) 00644 { 00645 const char *data; 00646 int bytes_written; 00647 00648 data = _dbus_string_get_const_data_len (buffer, start, len); 00649 00650 again: 00651 00652 bytes_written = write (fd, data, len); 00653 00654 if (bytes_written < 0 && errno == EINTR) 00655 goto again; 00656 00657 #if 0 00658 if (bytes_written > 0) 00659 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00660 #endif 00661 00662 return bytes_written; 00663 } 00664 00685 int 00686 _dbus_write_two (int fd, 00687 const DBusString *buffer1, 00688 int start1, 00689 int len1, 00690 const DBusString *buffer2, 00691 int start2, 00692 int len2) 00693 { 00694 _dbus_assert (buffer1 != NULL); 00695 _dbus_assert (start1 >= 0); 00696 _dbus_assert (start2 >= 0); 00697 _dbus_assert (len1 >= 0); 00698 _dbus_assert (len2 >= 0); 00699 00700 #ifdef HAVE_WRITEV 00701 { 00702 struct iovec vectors[2]; 00703 const char *data1; 00704 const char *data2; 00705 int bytes_written; 00706 00707 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00708 00709 if (buffer2 != NULL) 00710 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00711 else 00712 { 00713 data2 = NULL; 00714 start2 = 0; 00715 len2 = 0; 00716 } 00717 00718 vectors[0].iov_base = (char*) data1; 00719 vectors[0].iov_len = len1; 00720 vectors[1].iov_base = (char*) data2; 00721 vectors[1].iov_len = len2; 00722 00723 again: 00724 00725 bytes_written = writev (fd, 00726 vectors, 00727 data2 ? 2 : 1); 00728 00729 if (bytes_written < 0 && errno == EINTR) 00730 goto again; 00731 00732 return bytes_written; 00733 } 00734 #else /* HAVE_WRITEV */ 00735 { 00736 int ret1; 00737 00738 ret1 = _dbus_write (fd, buffer1, start1, len1); 00739 if (ret1 == len1 && buffer2 != NULL) 00740 { 00741 ret2 = _dbus_write (fd, buffer2, start2, len2); 00742 if (ret2 < 0) 00743 ret2 = 0; /* we can't report an error as the first write was OK */ 00744 00745 return ret1 + ret2; 00746 } 00747 else 00748 return ret1; 00749 } 00750 #endif /* !HAVE_WRITEV */ 00751 } 00752 00753 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00754 00784 int 00785 _dbus_connect_unix_socket (const char *path, 00786 dbus_bool_t abstract, 00787 DBusError *error) 00788 { 00789 int fd; 00790 size_t path_len; 00791 struct sockaddr_un addr; 00792 00793 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00794 00795 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00796 path, abstract); 00797 00798 00799 if (!_dbus_open_unix_socket (&fd, error)) 00800 { 00801 _DBUS_ASSERT_ERROR_IS_SET(error); 00802 return -1; 00803 } 00804 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00805 00806 _DBUS_ZERO (addr); 00807 addr.sun_family = AF_UNIX; 00808 path_len = strlen (path); 00809 00810 if (abstract) 00811 { 00812 #ifdef HAVE_ABSTRACT_SOCKETS 00813 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00814 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00815 00816 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00817 { 00818 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00819 "Abstract socket name too long\n"); 00820 _dbus_close (fd, NULL); 00821 return -1; 00822 } 00823 00824 strncpy (&addr.sun_path[1], path, path_len); 00825 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00826 #else /* HAVE_ABSTRACT_SOCKETS */ 00827 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00828 "Operating system does not support abstract socket namespace\n"); 00829 _dbus_close (fd, NULL); 00830 return -1; 00831 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00832 } 00833 else 00834 { 00835 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00836 { 00837 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00838 "Socket name too long\n"); 00839 _dbus_close (fd, NULL); 00840 return -1; 00841 } 00842 00843 strncpy (addr.sun_path, path, path_len); 00844 } 00845 00846 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00847 { 00848 dbus_set_error (error, 00849 _dbus_error_from_errno (errno), 00850 "Failed to connect to socket %s: %s", 00851 path, _dbus_strerror (errno)); 00852 00853 _dbus_close (fd, NULL); 00854 return -1; 00855 } 00856 00857 if (!_dbus_set_fd_nonblocking (fd, error)) 00858 { 00859 _DBUS_ASSERT_ERROR_IS_SET (error); 00860 00861 _dbus_close (fd, NULL); 00862 return -1; 00863 } 00864 00865 return fd; 00866 } 00867 00877 static dbus_bool_t 00878 _dbus_set_local_creds (int fd, dbus_bool_t on) 00879 { 00880 dbus_bool_t retval = TRUE; 00881 00882 #if defined(HAVE_CMSGCRED) 00883 /* NOOP just to make sure only one codepath is used 00884 * and to prefer CMSGCRED 00885 */ 00886 #elif defined(LOCAL_CREDS) 00887 int val = on ? 1 : 0; 00888 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) 00889 { 00890 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); 00891 retval = FALSE; 00892 } 00893 else 00894 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", 00895 on ? "enabled" : "disabled", fd); 00896 #endif 00897 00898 return retval; 00899 } 00900 00918 int 00919 _dbus_listen_unix_socket (const char *path, 00920 dbus_bool_t abstract, 00921 DBusError *error) 00922 { 00923 int listen_fd; 00924 struct sockaddr_un addr; 00925 size_t path_len; 00926 unsigned int reuseaddr; 00927 00928 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00929 00930 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 00931 path, abstract); 00932 00933 if (!_dbus_open_unix_socket (&listen_fd, error)) 00934 { 00935 _DBUS_ASSERT_ERROR_IS_SET(error); 00936 return -1; 00937 } 00938 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00939 00940 _DBUS_ZERO (addr); 00941 addr.sun_family = AF_UNIX; 00942 path_len = strlen (path); 00943 00944 if (abstract) 00945 { 00946 #ifdef HAVE_ABSTRACT_SOCKETS 00947 /* remember that abstract names aren't nul-terminated so we rely 00948 * on sun_path being filled in with zeroes above. 00949 */ 00950 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00951 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00952 00953 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00954 { 00955 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00956 "Abstract socket name too long\n"); 00957 _dbus_close (listen_fd, NULL); 00958 return -1; 00959 } 00960 00961 strncpy (&addr.sun_path[1], path, path_len); 00962 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00963 #else /* HAVE_ABSTRACT_SOCKETS */ 00964 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00965 "Operating system does not support abstract socket namespace\n"); 00966 _dbus_close (listen_fd, NULL); 00967 return -1; 00968 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00969 } 00970 else 00971 { 00972 /* Discussed security implications of this with Nalin, 00973 * and we couldn't think of where it would kick our ass, but 00974 * it still seems a bit sucky. It also has non-security suckage; 00975 * really we'd prefer to exit if the socket is already in use. 00976 * But there doesn't seem to be a good way to do this. 00977 * 00978 * Just to be extra careful, I threw in the stat() - clearly 00979 * the stat() can't *fix* any security issue, but it at least 00980 * avoids inadvertent/accidental data loss. 00981 */ 00982 { 00983 struct stat sb; 00984 00985 if (stat (path, &sb) == 0 && 00986 S_ISSOCK (sb.st_mode)) 00987 unlink (path); 00988 } 00989 00990 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00991 { 00992 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00993 "Abstract socket name too long\n"); 00994 _dbus_close (listen_fd, NULL); 00995 return -1; 00996 } 00997 00998 strncpy (addr.sun_path, path, path_len); 00999 } 01000 01001 reuseaddr = 1; 01002 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01003 { 01004 _dbus_warn ("Failed to set socket option\"%s\": %s", 01005 path, _dbus_strerror (errno)); 01006 } 01007 01008 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 01009 { 01010 dbus_set_error (error, _dbus_error_from_errno (errno), 01011 "Failed to bind socket \"%s\": %s", 01012 path, _dbus_strerror (errno)); 01013 _dbus_close (listen_fd, NULL); 01014 return -1; 01015 } 01016 01017 if (listen (listen_fd, 30 /* backlog */) < 0) 01018 { 01019 dbus_set_error (error, _dbus_error_from_errno (errno), 01020 "Failed to listen on socket \"%s\": %s", 01021 path, _dbus_strerror (errno)); 01022 _dbus_close (listen_fd, NULL); 01023 return -1; 01024 } 01025 01026 if (!_dbus_set_local_creds (listen_fd, TRUE)) 01027 { 01028 dbus_set_error (error, _dbus_error_from_errno (errno), 01029 "Failed to enable LOCAL_CREDS on socket \"%s\": %s", 01030 path, _dbus_strerror (errno)); 01031 close (listen_fd); 01032 return -1; 01033 } 01034 01035 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01036 { 01037 _DBUS_ASSERT_ERROR_IS_SET (error); 01038 _dbus_close (listen_fd, NULL); 01039 return -1; 01040 } 01041 01042 /* Try opening up the permissions, but if we can't, just go ahead 01043 * and continue, maybe it will be good enough. 01044 */ 01045 if (!abstract && chmod (path, 0777) < 0) 01046 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01047 path); 01048 01049 return listen_fd; 01050 } 01051 01062 int 01063 _dbus_listen_systemd_sockets (int **fds, 01064 DBusError *error) 01065 { 01066 int r, n; 01067 unsigned fd; 01068 int *new_fds; 01069 01070 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01071 01072 n = sd_listen_fds (TRUE); 01073 if (n < 0) 01074 { 01075 dbus_set_error (error, _dbus_error_from_errno (-n), 01076 "Failed to acquire systemd socket: %s", 01077 _dbus_strerror (-n)); 01078 return -1; 01079 } 01080 01081 if (n <= 0) 01082 { 01083 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01084 "No socket received."); 01085 return -1; 01086 } 01087 01088 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01089 { 01090 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01091 if (r < 0) 01092 { 01093 dbus_set_error (error, _dbus_error_from_errno (-r), 01094 "Failed to verify systemd socket type: %s", 01095 _dbus_strerror (-r)); 01096 return -1; 01097 } 01098 01099 if (!r) 01100 { 01101 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01102 "Passed socket has wrong type."); 01103 return -1; 01104 } 01105 } 01106 01107 /* OK, the file descriptors are all good, so let's take posession of 01108 them then. */ 01109 01110 new_fds = dbus_new (int, n); 01111 if (!new_fds) 01112 { 01113 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01114 "Failed to allocate file handle array."); 01115 goto fail; 01116 } 01117 01118 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01119 { 01120 if (!_dbus_set_local_creds (fd, TRUE)) 01121 { 01122 dbus_set_error (error, _dbus_error_from_errno (errno), 01123 "Failed to enable LOCAL_CREDS on systemd socket: %s", 01124 _dbus_strerror (errno)); 01125 goto fail; 01126 } 01127 01128 if (!_dbus_set_fd_nonblocking (fd, error)) 01129 { 01130 _DBUS_ASSERT_ERROR_IS_SET (error); 01131 goto fail; 01132 } 01133 01134 new_fds[fd - SD_LISTEN_FDS_START] = fd; 01135 } 01136 01137 *fds = new_fds; 01138 return n; 01139 01140 fail: 01141 01142 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01143 { 01144 _dbus_close (fd, NULL); 01145 } 01146 01147 dbus_free (new_fds); 01148 return -1; 01149 } 01150 01164 int 01165 _dbus_connect_tcp_socket (const char *host, 01166 const char *port, 01167 const char *family, 01168 DBusError *error) 01169 { 01170 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01171 } 01172 01173 int 01174 _dbus_connect_tcp_socket_with_nonce (const char *host, 01175 const char *port, 01176 const char *family, 01177 const char *noncefile, 01178 DBusError *error) 01179 { 01180 int saved_errno = 0; 01181 int fd = -1, res; 01182 struct addrinfo hints; 01183 struct addrinfo *ai, *tmp; 01184 01185 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01186 01187 _DBUS_ZERO (hints); 01188 01189 if (!family) 01190 hints.ai_family = AF_UNSPEC; 01191 else if (!strcmp(family, "ipv4")) 01192 hints.ai_family = AF_INET; 01193 else if (!strcmp(family, "ipv6")) 01194 hints.ai_family = AF_INET6; 01195 else 01196 { 01197 dbus_set_error (error, 01198 DBUS_ERROR_BAD_ADDRESS, 01199 "Unknown address family %s", family); 01200 return -1; 01201 } 01202 hints.ai_protocol = IPPROTO_TCP; 01203 hints.ai_socktype = SOCK_STREAM; 01204 hints.ai_flags = AI_ADDRCONFIG; 01205 01206 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01207 { 01208 dbus_set_error (error, 01209 _dbus_error_from_errno (errno), 01210 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01211 host, port, gai_strerror(res), res); 01212 _dbus_close (fd, NULL); 01213 return -1; 01214 } 01215 01216 tmp = ai; 01217 while (tmp) 01218 { 01219 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01220 { 01221 freeaddrinfo(ai); 01222 _DBUS_ASSERT_ERROR_IS_SET(error); 01223 return -1; 01224 } 01225 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01226 01227 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01228 { 01229 saved_errno = errno; 01230 _dbus_close(fd, NULL); 01231 fd = -1; 01232 tmp = tmp->ai_next; 01233 continue; 01234 } 01235 01236 break; 01237 } 01238 freeaddrinfo(ai); 01239 01240 if (fd == -1) 01241 { 01242 dbus_set_error (error, 01243 _dbus_error_from_errno (saved_errno), 01244 "Failed to connect to socket \"%s:%s\" %s", 01245 host, port, _dbus_strerror(saved_errno)); 01246 return -1; 01247 } 01248 01249 if (noncefile != NULL) 01250 { 01251 DBusString noncefileStr; 01252 dbus_bool_t ret; 01253 _dbus_string_init_const (&noncefileStr, noncefile); 01254 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01255 _dbus_string_free (&noncefileStr); 01256 01257 if (!ret) 01258 { 01259 _dbus_close (fd, NULL); 01260 return -1; 01261 } 01262 } 01263 01264 if (!_dbus_set_fd_nonblocking (fd, error)) 01265 { 01266 _dbus_close (fd, NULL); 01267 return -1; 01268 } 01269 01270 return fd; 01271 } 01272 01289 int 01290 _dbus_listen_tcp_socket (const char *host, 01291 const char *port, 01292 const char *family, 01293 DBusString *retport, 01294 int **fds_p, 01295 DBusError *error) 01296 { 01297 int saved_errno; 01298 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01299 struct addrinfo hints; 01300 struct addrinfo *ai, *tmp; 01301 unsigned int reuseaddr; 01302 01303 *fds_p = NULL; 01304 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01305 01306 _DBUS_ZERO (hints); 01307 01308 if (!family) 01309 hints.ai_family = AF_UNSPEC; 01310 else if (!strcmp(family, "ipv4")) 01311 hints.ai_family = AF_INET; 01312 else if (!strcmp(family, "ipv6")) 01313 hints.ai_family = AF_INET6; 01314 else 01315 { 01316 dbus_set_error (error, 01317 DBUS_ERROR_BAD_ADDRESS, 01318 "Unknown address family %s", family); 01319 return -1; 01320 } 01321 01322 hints.ai_protocol = IPPROTO_TCP; 01323 hints.ai_socktype = SOCK_STREAM; 01324 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01325 01326 redo_lookup_with_port: 01327 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01328 { 01329 dbus_set_error (error, 01330 _dbus_error_from_errno (errno), 01331 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01332 host ? host : "*", port, gai_strerror(res), res); 01333 return -1; 01334 } 01335 01336 tmp = ai; 01337 while (tmp) 01338 { 01339 int fd = -1, *newlisten_fd; 01340 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01341 { 01342 _DBUS_ASSERT_ERROR_IS_SET(error); 01343 goto failed; 01344 } 01345 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01346 01347 reuseaddr = 1; 01348 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01349 { 01350 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01351 host ? host : "*", port, _dbus_strerror (errno)); 01352 } 01353 01354 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01355 { 01356 saved_errno = errno; 01357 _dbus_close(fd, NULL); 01358 if (saved_errno == EADDRINUSE) 01359 { 01360 /* Depending on kernel policy, it may or may not 01361 be neccessary to bind to both IPv4 & 6 addresses 01362 so ignore EADDRINUSE here */ 01363 tmp = tmp->ai_next; 01364 continue; 01365 } 01366 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01367 "Failed to bind socket \"%s:%s\": %s", 01368 host ? host : "*", port, _dbus_strerror (saved_errno)); 01369 goto failed; 01370 } 01371 01372 if (listen (fd, 30 /* backlog */) < 0) 01373 { 01374 saved_errno = errno; 01375 _dbus_close (fd, NULL); 01376 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01377 "Failed to listen on socket \"%s:%s\": %s", 01378 host ? host : "*", port, _dbus_strerror (saved_errno)); 01379 goto failed; 01380 } 01381 01382 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01383 if (!newlisten_fd) 01384 { 01385 saved_errno = errno; 01386 _dbus_close (fd, NULL); 01387 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01388 "Failed to allocate file handle array: %s", 01389 _dbus_strerror (saved_errno)); 01390 goto failed; 01391 } 01392 listen_fd = newlisten_fd; 01393 listen_fd[nlisten_fd] = fd; 01394 nlisten_fd++; 01395 01396 if (!_dbus_string_get_length(retport)) 01397 { 01398 /* If the user didn't specify a port, or used 0, then 01399 the kernel chooses a port. After the first address 01400 is bound to, we need to force all remaining addresses 01401 to use the same port */ 01402 if (!port || !strcmp(port, "0")) 01403 { 01404 int result; 01405 struct sockaddr_storage addr; 01406 socklen_t addrlen; 01407 char portbuf[50]; 01408 01409 addrlen = sizeof(addr); 01410 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01411 01412 if (result == -1 || 01413 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0, 01414 portbuf, sizeof(portbuf), 01415 NI_NUMERICHOST)) != 0) 01416 { 01417 dbus_set_error (error, _dbus_error_from_errno (errno), 01418 "Failed to resolve port \"%s:%s\": %s (%s)", 01419 host ? host : "*", port, gai_strerror(res), res); 01420 goto failed; 01421 } 01422 if (!_dbus_string_append(retport, portbuf)) 01423 { 01424 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01425 goto failed; 01426 } 01427 01428 /* Release current address list & redo lookup */ 01429 port = _dbus_string_get_const_data(retport); 01430 freeaddrinfo(ai); 01431 goto redo_lookup_with_port; 01432 } 01433 else 01434 { 01435 if (!_dbus_string_append(retport, port)) 01436 { 01437 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01438 goto failed; 01439 } 01440 } 01441 } 01442 01443 tmp = tmp->ai_next; 01444 } 01445 freeaddrinfo(ai); 01446 ai = NULL; 01447 01448 if (!nlisten_fd) 01449 { 01450 errno = EADDRINUSE; 01451 dbus_set_error (error, _dbus_error_from_errno (errno), 01452 "Failed to bind socket \"%s:%s\": %s", 01453 host ? host : "*", port, _dbus_strerror (errno)); 01454 goto failed; 01455 } 01456 01457 for (i = 0 ; i < nlisten_fd ; i++) 01458 { 01459 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01460 { 01461 goto failed; 01462 } 01463 } 01464 01465 *fds_p = listen_fd; 01466 01467 return nlisten_fd; 01468 01469 failed: 01470 if (ai) 01471 freeaddrinfo(ai); 01472 for (i = 0 ; i < nlisten_fd ; i++) 01473 _dbus_close(listen_fd[i], NULL); 01474 dbus_free(listen_fd); 01475 return -1; 01476 } 01477 01478 static dbus_bool_t 01479 write_credentials_byte (int server_fd, 01480 DBusError *error) 01481 { 01482 int bytes_written; 01483 char buf[1] = { '\0' }; 01484 #if defined(HAVE_CMSGCRED) 01485 union { 01486 struct cmsghdr hdr; 01487 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01488 } cmsg; 01489 struct iovec iov; 01490 struct msghdr msg; 01491 iov.iov_base = buf; 01492 iov.iov_len = 1; 01493 01494 _DBUS_ZERO(msg); 01495 msg.msg_iov = &iov; 01496 msg.msg_iovlen = 1; 01497 01498 msg.msg_control = (caddr_t) &cmsg; 01499 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01500 _DBUS_ZERO(cmsg); 01501 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01502 cmsg.hdr.cmsg_level = SOL_SOCKET; 01503 cmsg.hdr.cmsg_type = SCM_CREDS; 01504 #endif 01505 01506 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01507 01508 again: 01509 01510 #if defined(HAVE_CMSGCRED) 01511 bytes_written = sendmsg (server_fd, &msg, 0 01512 #if HAVE_DECL_MSG_NOSIGNAL 01513 |MSG_NOSIGNAL 01514 #endif 01515 ); 01516 #else 01517 bytes_written = send (server_fd, buf, 1, 0 01518 #if HAVE_DECL_MSG_NOSIGNAL 01519 |MSG_NOSIGNAL 01520 #endif 01521 ); 01522 #endif 01523 01524 if (bytes_written < 0 && errno == EINTR) 01525 goto again; 01526 01527 if (bytes_written < 0) 01528 { 01529 dbus_set_error (error, _dbus_error_from_errno (errno), 01530 "Failed to write credentials byte: %s", 01531 _dbus_strerror (errno)); 01532 return FALSE; 01533 } 01534 else if (bytes_written == 0) 01535 { 01536 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01537 "wrote zero bytes writing credentials byte"); 01538 return FALSE; 01539 } 01540 else 01541 { 01542 _dbus_assert (bytes_written == 1); 01543 _dbus_verbose ("wrote credentials byte\n"); 01544 return TRUE; 01545 } 01546 } 01547 01569 dbus_bool_t 01570 _dbus_read_credentials_socket (int client_fd, 01571 DBusCredentials *credentials, 01572 DBusError *error) 01573 { 01574 struct msghdr msg; 01575 struct iovec iov; 01576 char buf; 01577 dbus_uid_t uid_read; 01578 dbus_pid_t pid_read; 01579 int bytes_read; 01580 01581 #ifdef HAVE_CMSGCRED 01582 union { 01583 struct cmsghdr hdr; 01584 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01585 } cmsg; 01586 01587 #elif defined(LOCAL_CREDS) 01588 struct { 01589 struct cmsghdr hdr; 01590 struct sockcred cred; 01591 } cmsg; 01592 #endif 01593 01594 uid_read = DBUS_UID_UNSET; 01595 pid_read = DBUS_PID_UNSET; 01596 01597 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01598 01599 /* The POSIX spec certainly doesn't promise this, but 01600 * we need these assertions to fail as soon as we're wrong about 01601 * it so we can do the porting fixups 01602 */ 01603 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01604 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01605 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01606 01607 _dbus_credentials_clear (credentials); 01608 01609 /* Systems supporting LOCAL_CREDS are configured to have this feature 01610 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01611 * the connection. Therefore, the received message must carry the 01612 * credentials information without doing anything special. 01613 */ 01614 01615 iov.iov_base = &buf; 01616 iov.iov_len = 1; 01617 01618 _DBUS_ZERO(msg); 01619 msg.msg_iov = &iov; 01620 msg.msg_iovlen = 1; 01621 01622 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01623 _DBUS_ZERO(cmsg); 01624 msg.msg_control = (caddr_t) &cmsg; 01625 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01626 #endif 01627 01628 again: 01629 bytes_read = recvmsg (client_fd, &msg, 0); 01630 01631 if (bytes_read < 0) 01632 { 01633 if (errno == EINTR) 01634 goto again; 01635 01636 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01637 * normally only call read_credentials if the socket was ready 01638 * for reading 01639 */ 01640 01641 dbus_set_error (error, _dbus_error_from_errno (errno), 01642 "Failed to read credentials byte: %s", 01643 _dbus_strerror (errno)); 01644 return FALSE; 01645 } 01646 else if (bytes_read == 0) 01647 { 01648 /* this should not happen unless we are using recvmsg wrong, 01649 * so is essentially here for paranoia 01650 */ 01651 dbus_set_error (error, DBUS_ERROR_FAILED, 01652 "Failed to read credentials byte (zero-length read)"); 01653 return FALSE; 01654 } 01655 else if (buf != '\0') 01656 { 01657 dbus_set_error (error, DBUS_ERROR_FAILED, 01658 "Credentials byte was not nul"); 01659 return FALSE; 01660 } 01661 01662 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01663 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01664 || cmsg.hdr.cmsg_type != SCM_CREDS) 01665 { 01666 dbus_set_error (error, DBUS_ERROR_FAILED, 01667 "Message from recvmsg() was not SCM_CREDS"); 01668 return FALSE; 01669 } 01670 #endif 01671 01672 _dbus_verbose ("read credentials byte\n"); 01673 01674 { 01675 #ifdef SO_PEERCRED 01676 #ifdef __OpenBSD__ 01677 struct sockpeercred cr; 01678 #else 01679 struct ucred cr; 01680 #endif 01681 int cr_len = sizeof (cr); 01682 01683 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01684 cr_len == sizeof (cr)) 01685 { 01686 pid_read = cr.pid; 01687 uid_read = cr.uid; 01688 } 01689 else 01690 { 01691 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01692 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01693 } 01694 #elif defined(HAVE_CMSGCRED) 01695 struct cmsgcred *cred; 01696 01697 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01698 pid_read = cred->cmcred_pid; 01699 uid_read = cred->cmcred_euid; 01700 #elif defined(LOCAL_CREDS) 01701 pid_read = DBUS_PID_UNSET; 01702 uid_read = cmsg.cred.sc_uid; 01703 /* Since we have already got the credentials from this socket, we can 01704 * disable its LOCAL_CREDS flag if it was ever set. */ 01705 _dbus_set_local_creds (client_fd, FALSE); 01706 #elif defined(HAVE_GETPEEREID) 01707 uid_t euid; 01708 gid_t egid; 01709 if (getpeereid (client_fd, &euid, &egid) == 0) 01710 { 01711 uid_read = euid; 01712 } 01713 else 01714 { 01715 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01716 } 01717 #elif defined(HAVE_GETPEERUCRED) 01718 ucred_t * ucred = NULL; 01719 if (getpeerucred (client_fd, &ucred) == 0) 01720 { 01721 pid_read = ucred_getpid (ucred); 01722 uid_read = ucred_geteuid (ucred); 01723 #ifdef HAVE_ADT 01724 /* generate audit session data based on socket ucred */ 01725 adt_session_data_t *adth = NULL; 01726 adt_export_data_t *data = NULL; 01727 size_t size = 0; 01728 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01729 { 01730 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01731 } 01732 else 01733 { 01734 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01735 { 01736 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01737 } 01738 else 01739 { 01740 size = adt_export_session_data (adth, &data); 01741 if (size <= 0) 01742 { 01743 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01744 } 01745 else 01746 { 01747 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01748 free (data); 01749 } 01750 } 01751 (void) adt_end_session (adth); 01752 } 01753 #endif /* HAVE_ADT */ 01754 } 01755 else 01756 { 01757 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01758 } 01759 if (ucred != NULL) 01760 ucred_free (ucred); 01761 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01762 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01763 #endif 01764 } 01765 01766 _dbus_verbose ("Credentials:" 01767 " pid "DBUS_PID_FORMAT 01768 " uid "DBUS_UID_FORMAT 01769 "\n", 01770 pid_read, 01771 uid_read); 01772 01773 if (pid_read != DBUS_PID_UNSET) 01774 { 01775 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01776 { 01777 _DBUS_SET_OOM (error); 01778 return FALSE; 01779 } 01780 } 01781 01782 if (uid_read != DBUS_UID_UNSET) 01783 { 01784 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01785 { 01786 _DBUS_SET_OOM (error); 01787 return FALSE; 01788 } 01789 } 01790 01791 return TRUE; 01792 } 01793 01811 dbus_bool_t 01812 _dbus_send_credentials_socket (int server_fd, 01813 DBusError *error) 01814 { 01815 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01816 01817 if (write_credentials_byte (server_fd, error)) 01818 return TRUE; 01819 else 01820 return FALSE; 01821 } 01822 01832 int 01833 _dbus_accept (int listen_fd) 01834 { 01835 int client_fd; 01836 struct sockaddr addr; 01837 socklen_t addrlen; 01838 #ifdef HAVE_ACCEPT4 01839 dbus_bool_t cloexec_done; 01840 #endif 01841 01842 addrlen = sizeof (addr); 01843 01844 retry: 01845 01846 #ifdef HAVE_ACCEPT4 01847 /* We assume that if accept4 is available SOCK_CLOEXEC is too */ 01848 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01849 cloexec_done = client_fd >= 0; 01850 01851 if (client_fd < 0 && errno == ENOSYS) 01852 #endif 01853 { 01854 client_fd = accept (listen_fd, &addr, &addrlen); 01855 } 01856 01857 if (client_fd < 0) 01858 { 01859 if (errno == EINTR) 01860 goto retry; 01861 } 01862 01863 _dbus_verbose ("client fd %d accepted\n", client_fd); 01864 01865 #ifdef HAVE_ACCEPT4 01866 if (!cloexec_done) 01867 #endif 01868 { 01869 _dbus_fd_set_close_on_exec(client_fd); 01870 } 01871 01872 return client_fd; 01873 } 01874 01883 dbus_bool_t 01884 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01885 { 01886 const char *directory; 01887 struct stat sb; 01888 01889 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01890 01891 directory = _dbus_string_get_const_data (dir); 01892 01893 if (stat (directory, &sb) < 0) 01894 { 01895 dbus_set_error (error, _dbus_error_from_errno (errno), 01896 "%s", _dbus_strerror (errno)); 01897 01898 return FALSE; 01899 } 01900 01901 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01902 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01903 { 01904 dbus_set_error (error, DBUS_ERROR_FAILED, 01905 "%s directory is not private to the user", directory); 01906 return FALSE; 01907 } 01908 01909 return TRUE; 01910 } 01911 01912 static dbus_bool_t 01913 fill_user_info_from_passwd (struct passwd *p, 01914 DBusUserInfo *info, 01915 DBusError *error) 01916 { 01917 _dbus_assert (p->pw_name != NULL); 01918 _dbus_assert (p->pw_dir != NULL); 01919 01920 info->uid = p->pw_uid; 01921 info->primary_gid = p->pw_gid; 01922 info->username = _dbus_strdup (p->pw_name); 01923 info->homedir = _dbus_strdup (p->pw_dir); 01924 01925 if (info->username == NULL || 01926 info->homedir == NULL) 01927 { 01928 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01929 return FALSE; 01930 } 01931 01932 return TRUE; 01933 } 01934 01935 static dbus_bool_t 01936 fill_user_info (DBusUserInfo *info, 01937 dbus_uid_t uid, 01938 const DBusString *username, 01939 DBusError *error) 01940 { 01941 const char *username_c; 01942 01943 /* exactly one of username/uid provided */ 01944 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 01945 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 01946 01947 info->uid = DBUS_UID_UNSET; 01948 info->primary_gid = DBUS_GID_UNSET; 01949 info->group_ids = NULL; 01950 info->n_group_ids = 0; 01951 info->username = NULL; 01952 info->homedir = NULL; 01953 01954 if (username != NULL) 01955 username_c = _dbus_string_get_const_data (username); 01956 else 01957 username_c = NULL; 01958 01959 /* For now assuming that the getpwnam() and getpwuid() flavors 01960 * are always symmetrical, if not we have to add more configure 01961 * checks 01962 */ 01963 01964 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 01965 { 01966 struct passwd *p; 01967 int result; 01968 size_t buflen; 01969 char *buf; 01970 struct passwd p_str; 01971 01972 /* retrieve maximum needed size for buf */ 01973 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 01974 01975 /* sysconf actually returns a long, but everything else expects size_t, 01976 * so just recast here. 01977 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 01978 */ 01979 if ((long) buflen <= 0) 01980 buflen = 1024; 01981 01982 result = -1; 01983 while (1) 01984 { 01985 buf = dbus_malloc (buflen); 01986 if (buf == NULL) 01987 { 01988 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01989 return FALSE; 01990 } 01991 01992 p = NULL; 01993 #ifdef HAVE_POSIX_GETPWNAM_R 01994 if (uid != DBUS_UID_UNSET) 01995 result = getpwuid_r (uid, &p_str, buf, buflen, 01996 &p); 01997 else 01998 result = getpwnam_r (username_c, &p_str, buf, buflen, 01999 &p); 02000 #else 02001 if (uid != DBUS_UID_UNSET) 02002 p = getpwuid_r (uid, &p_str, buf, buflen); 02003 else 02004 p = getpwnam_r (username_c, &p_str, buf, buflen); 02005 result = 0; 02006 #endif /* !HAVE_POSIX_GETPWNAM_R */ 02007 //Try a bigger buffer if ERANGE was returned 02008 if (result == ERANGE && buflen < 512 * 1024) 02009 { 02010 dbus_free (buf); 02011 buflen *= 2; 02012 } 02013 else 02014 { 02015 break; 02016 } 02017 } 02018 if (result == 0 && p == &p_str) 02019 { 02020 if (!fill_user_info_from_passwd (p, info, error)) 02021 { 02022 dbus_free (buf); 02023 return FALSE; 02024 } 02025 dbus_free (buf); 02026 } 02027 else 02028 { 02029 dbus_set_error (error, _dbus_error_from_errno (errno), 02030 "User \"%s\" unknown or no memory to allocate password entry\n", 02031 username_c ? username_c : "???"); 02032 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02033 dbus_free (buf); 02034 return FALSE; 02035 } 02036 } 02037 #else /* ! HAVE_GETPWNAM_R */ 02038 { 02039 /* I guess we're screwed on thread safety here */ 02040 struct passwd *p; 02041 02042 if (uid != DBUS_UID_UNSET) 02043 p = getpwuid (uid); 02044 else 02045 p = getpwnam (username_c); 02046 02047 if (p != NULL) 02048 { 02049 if (!fill_user_info_from_passwd (p, info, error)) 02050 { 02051 return FALSE; 02052 } 02053 } 02054 else 02055 { 02056 dbus_set_error (error, _dbus_error_from_errno (errno), 02057 "User \"%s\" unknown or no memory to allocate password entry\n", 02058 username_c ? username_c : "???"); 02059 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02060 return FALSE; 02061 } 02062 } 02063 #endif /* ! HAVE_GETPWNAM_R */ 02064 02065 /* Fill this in so we can use it to get groups */ 02066 username_c = info->username; 02067 02068 #ifdef HAVE_GETGROUPLIST 02069 { 02070 gid_t *buf; 02071 int buf_count; 02072 int i; 02073 int initial_buf_count; 02074 02075 initial_buf_count = 17; 02076 buf_count = initial_buf_count; 02077 buf = dbus_new (gid_t, buf_count); 02078 if (buf == NULL) 02079 { 02080 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02081 goto failed; 02082 } 02083 02084 if (getgrouplist (username_c, 02085 info->primary_gid, 02086 buf, &buf_count) < 0) 02087 { 02088 gid_t *new; 02089 /* Presumed cause of negative return code: buf has insufficient 02090 entries to hold the entire group list. The Linux behavior in this 02091 case is to pass back the actual number of groups in buf_count, but 02092 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02093 So as a hack, try to help out a bit by guessing a larger 02094 number of groups, within reason.. might still fail, of course, 02095 but we can at least print a more informative message. I looked up 02096 the "right way" to do this by downloading Apple's own source code 02097 for the "id" command, and it turns out that they use an 02098 undocumented library function getgrouplist_2 (!) which is not 02099 declared in any header in /usr/include (!!). That did not seem 02100 like the way to go here. 02101 */ 02102 if (buf_count == initial_buf_count) 02103 { 02104 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02105 } 02106 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02107 if (new == NULL) 02108 { 02109 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02110 dbus_free (buf); 02111 goto failed; 02112 } 02113 02114 buf = new; 02115 02116 errno = 0; 02117 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02118 { 02119 if (errno == 0) 02120 { 02121 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02122 username_c, buf_count, buf_count); 02123 } 02124 else 02125 { 02126 dbus_set_error (error, 02127 _dbus_error_from_errno (errno), 02128 "Failed to get groups for username \"%s\" primary GID " 02129 DBUS_GID_FORMAT ": %s\n", 02130 username_c, info->primary_gid, 02131 _dbus_strerror (errno)); 02132 dbus_free (buf); 02133 goto failed; 02134 } 02135 } 02136 } 02137 02138 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02139 if (info->group_ids == NULL) 02140 { 02141 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02142 dbus_free (buf); 02143 goto failed; 02144 } 02145 02146 for (i = 0; i < buf_count; ++i) 02147 info->group_ids[i] = buf[i]; 02148 02149 info->n_group_ids = buf_count; 02150 02151 dbus_free (buf); 02152 } 02153 #else /* HAVE_GETGROUPLIST */ 02154 { 02155 /* We just get the one group ID */ 02156 info->group_ids = dbus_new (dbus_gid_t, 1); 02157 if (info->group_ids == NULL) 02158 { 02159 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02160 goto failed; 02161 } 02162 02163 info->n_group_ids = 1; 02164 02165 (info->group_ids)[0] = info->primary_gid; 02166 } 02167 #endif /* HAVE_GETGROUPLIST */ 02168 02169 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02170 02171 return TRUE; 02172 02173 failed: 02174 _DBUS_ASSERT_ERROR_IS_SET (error); 02175 return FALSE; 02176 } 02177 02186 dbus_bool_t 02187 _dbus_user_info_fill (DBusUserInfo *info, 02188 const DBusString *username, 02189 DBusError *error) 02190 { 02191 return fill_user_info (info, DBUS_UID_UNSET, 02192 username, error); 02193 } 02194 02203 dbus_bool_t 02204 _dbus_user_info_fill_uid (DBusUserInfo *info, 02205 dbus_uid_t uid, 02206 DBusError *error) 02207 { 02208 return fill_user_info (info, uid, 02209 NULL, error); 02210 } 02211 02219 dbus_bool_t 02220 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02221 { 02222 /* The POSIX spec certainly doesn't promise this, but 02223 * we need these assertions to fail as soon as we're wrong about 02224 * it so we can do the porting fixups 02225 */ 02226 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02227 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02228 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02229 02230 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 02231 return FALSE; 02232 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02233 return FALSE; 02234 02235 return TRUE; 02236 } 02237 02249 dbus_bool_t 02250 _dbus_append_user_from_current_process (DBusString *str) 02251 { 02252 return _dbus_string_append_uint (str, 02253 _dbus_geteuid ()); 02254 } 02255 02260 dbus_pid_t 02261 _dbus_getpid (void) 02262 { 02263 return getpid (); 02264 } 02265 02269 dbus_uid_t 02270 _dbus_getuid (void) 02271 { 02272 return getuid (); 02273 } 02274 02278 dbus_uid_t 02279 _dbus_geteuid (void) 02280 { 02281 return geteuid (); 02282 } 02283 02290 unsigned long 02291 _dbus_pid_for_log (void) 02292 { 02293 return getpid (); 02294 } 02295 02303 dbus_bool_t 02304 _dbus_parse_uid (const DBusString *uid_str, 02305 dbus_uid_t *uid) 02306 { 02307 int end; 02308 long val; 02309 02310 if (_dbus_string_get_length (uid_str) == 0) 02311 { 02312 _dbus_verbose ("UID string was zero length\n"); 02313 return FALSE; 02314 } 02315 02316 val = -1; 02317 end = 0; 02318 if (!_dbus_string_parse_int (uid_str, 0, &val, 02319 &end)) 02320 { 02321 _dbus_verbose ("could not parse string as a UID\n"); 02322 return FALSE; 02323 } 02324 02325 if (end != _dbus_string_get_length (uid_str)) 02326 { 02327 _dbus_verbose ("string contained trailing stuff after UID\n"); 02328 return FALSE; 02329 } 02330 02331 *uid = val; 02332 02333 return TRUE; 02334 } 02335 02336 #if !DBUS_USE_SYNC 02337 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02338 #endif 02339 02346 dbus_int32_t 02347 _dbus_atomic_inc (DBusAtomic *atomic) 02348 { 02349 #if DBUS_USE_SYNC 02350 return __sync_add_and_fetch(&atomic->value, 1)-1; 02351 #else 02352 dbus_int32_t res; 02353 _DBUS_LOCK (atomic); 02354 res = atomic->value; 02355 atomic->value += 1; 02356 _DBUS_UNLOCK (atomic); 02357 return res; 02358 #endif 02359 } 02360 02367 dbus_int32_t 02368 _dbus_atomic_dec (DBusAtomic *atomic) 02369 { 02370 #if DBUS_USE_SYNC 02371 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02372 #else 02373 dbus_int32_t res; 02374 02375 _DBUS_LOCK (atomic); 02376 res = atomic->value; 02377 atomic->value -= 1; 02378 _DBUS_UNLOCK (atomic); 02379 return res; 02380 #endif 02381 } 02382 02390 dbus_int32_t 02391 _dbus_atomic_get (DBusAtomic *atomic) 02392 { 02393 #if DBUS_USE_SYNC 02394 __sync_synchronize (); 02395 return atomic->value; 02396 #else 02397 dbus_int32_t res; 02398 02399 _DBUS_LOCK (atomic); 02400 res = atomic->value; 02401 _DBUS_UNLOCK (atomic); 02402 return res; 02403 #endif 02404 } 02405 02406 #ifdef DBUS_BUILD_TESTS 02407 02410 dbus_gid_t 02411 _dbus_getgid (void) 02412 { 02413 return getgid (); 02414 } 02415 #endif 02416 02425 int 02426 _dbus_poll (DBusPollFD *fds, 02427 int n_fds, 02428 int timeout_milliseconds) 02429 { 02430 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02431 /* This big thing is a constant expression and should get optimized 02432 * out of existence. So it's more robust than a configure check at 02433 * no cost. 02434 */ 02435 if (_DBUS_POLLIN == POLLIN && 02436 _DBUS_POLLPRI == POLLPRI && 02437 _DBUS_POLLOUT == POLLOUT && 02438 _DBUS_POLLERR == POLLERR && 02439 _DBUS_POLLHUP == POLLHUP && 02440 _DBUS_POLLNVAL == POLLNVAL && 02441 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02442 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02443 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02444 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02445 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02446 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02447 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02448 { 02449 return poll ((struct pollfd*) fds, 02450 n_fds, 02451 timeout_milliseconds); 02452 } 02453 else 02454 { 02455 /* We have to convert the DBusPollFD to an array of 02456 * struct pollfd, poll, and convert back. 02457 */ 02458 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02459 return -1; 02460 } 02461 #else /* ! HAVE_POLL */ 02462 02463 fd_set read_set, write_set, err_set; 02464 int max_fd = 0; 02465 int i; 02466 struct timeval tv; 02467 int ready; 02468 02469 FD_ZERO (&read_set); 02470 FD_ZERO (&write_set); 02471 FD_ZERO (&err_set); 02472 02473 for (i = 0; i < n_fds; i++) 02474 { 02475 DBusPollFD *fdp = &fds[i]; 02476 02477 if (fdp->events & _DBUS_POLLIN) 02478 FD_SET (fdp->fd, &read_set); 02479 02480 if (fdp->events & _DBUS_POLLOUT) 02481 FD_SET (fdp->fd, &write_set); 02482 02483 FD_SET (fdp->fd, &err_set); 02484 02485 max_fd = MAX (max_fd, fdp->fd); 02486 } 02487 02488 tv.tv_sec = timeout_milliseconds / 1000; 02489 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02490 02491 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02492 timeout_milliseconds < 0 ? NULL : &tv); 02493 02494 if (ready > 0) 02495 { 02496 for (i = 0; i < n_fds; i++) 02497 { 02498 DBusPollFD *fdp = &fds[i]; 02499 02500 fdp->revents = 0; 02501 02502 if (FD_ISSET (fdp->fd, &read_set)) 02503 fdp->revents |= _DBUS_POLLIN; 02504 02505 if (FD_ISSET (fdp->fd, &write_set)) 02506 fdp->revents |= _DBUS_POLLOUT; 02507 02508 if (FD_ISSET (fdp->fd, &err_set)) 02509 fdp->revents |= _DBUS_POLLERR; 02510 } 02511 } 02512 02513 return ready; 02514 #endif 02515 } 02516 02524 void 02525 _dbus_get_current_time (long *tv_sec, 02526 long *tv_usec) 02527 { 02528 #ifdef HAVE_MONOTONIC_CLOCK 02529 struct timespec ts; 02530 clock_gettime (CLOCK_MONOTONIC, &ts); 02531 02532 if (tv_sec) 02533 *tv_sec = ts.tv_sec; 02534 if (tv_usec) 02535 *tv_usec = ts.tv_nsec / 1000; 02536 #else 02537 struct timeval t; 02538 02539 gettimeofday (&t, NULL); 02540 02541 if (tv_sec) 02542 *tv_sec = t.tv_sec; 02543 if (tv_usec) 02544 *tv_usec = t.tv_usec; 02545 #endif 02546 } 02547 02556 dbus_bool_t 02557 _dbus_create_directory (const DBusString *filename, 02558 DBusError *error) 02559 { 02560 const char *filename_c; 02561 02562 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02563 02564 filename_c = _dbus_string_get_const_data (filename); 02565 02566 if (mkdir (filename_c, 0700) < 0) 02567 { 02568 if (errno == EEXIST) 02569 return TRUE; 02570 02571 dbus_set_error (error, DBUS_ERROR_FAILED, 02572 "Failed to create directory %s: %s\n", 02573 filename_c, _dbus_strerror (errno)); 02574 return FALSE; 02575 } 02576 else 02577 return TRUE; 02578 } 02579 02590 dbus_bool_t 02591 _dbus_concat_dir_and_file (DBusString *dir, 02592 const DBusString *next_component) 02593 { 02594 dbus_bool_t dir_ends_in_slash; 02595 dbus_bool_t file_starts_with_slash; 02596 02597 if (_dbus_string_get_length (dir) == 0 || 02598 _dbus_string_get_length (next_component) == 0) 02599 return TRUE; 02600 02601 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02602 _dbus_string_get_length (dir) - 1); 02603 02604 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02605 02606 if (dir_ends_in_slash && file_starts_with_slash) 02607 { 02608 _dbus_string_shorten (dir, 1); 02609 } 02610 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02611 { 02612 if (!_dbus_string_append_byte (dir, '/')) 02613 return FALSE; 02614 } 02615 02616 return _dbus_string_copy (next_component, 0, dir, 02617 _dbus_string_get_length (dir)); 02618 } 02619 02621 #define NANOSECONDS_PER_SECOND 1000000000 02622 02623 #define MICROSECONDS_PER_SECOND 1000000 02624 02625 #define MILLISECONDS_PER_SECOND 1000 02626 02627 #define NANOSECONDS_PER_MILLISECOND 1000000 02628 02629 #define MICROSECONDS_PER_MILLISECOND 1000 02630 02635 void 02636 _dbus_sleep_milliseconds (int milliseconds) 02637 { 02638 #ifdef HAVE_NANOSLEEP 02639 struct timespec req; 02640 struct timespec rem; 02641 02642 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02643 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02644 rem.tv_sec = 0; 02645 rem.tv_nsec = 0; 02646 02647 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02648 req = rem; 02649 #elif defined (HAVE_USLEEP) 02650 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02651 #else /* ! HAVE_USLEEP */ 02652 sleep (MAX (milliseconds / 1000, 1)); 02653 #endif 02654 } 02655 02656 static dbus_bool_t 02657 _dbus_generate_pseudorandom_bytes (DBusString *str, 02658 int n_bytes) 02659 { 02660 int old_len; 02661 char *p; 02662 02663 old_len = _dbus_string_get_length (str); 02664 02665 if (!_dbus_string_lengthen (str, n_bytes)) 02666 return FALSE; 02667 02668 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02669 02670 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02671 02672 return TRUE; 02673 } 02674 02683 dbus_bool_t 02684 _dbus_generate_random_bytes (DBusString *str, 02685 int n_bytes) 02686 { 02687 int old_len; 02688 int fd; 02689 02690 /* FALSE return means "no memory", if it could 02691 * mean something else then we'd need to return 02692 * a DBusError. So we always fall back to pseudorandom 02693 * if the I/O fails. 02694 */ 02695 02696 old_len = _dbus_string_get_length (str); 02697 fd = -1; 02698 02699 /* note, urandom on linux will fall back to pseudorandom */ 02700 fd = open ("/dev/urandom", O_RDONLY); 02701 if (fd < 0) 02702 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02703 02704 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02705 02706 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02707 { 02708 _dbus_close (fd, NULL); 02709 _dbus_string_set_length (str, old_len); 02710 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02711 } 02712 02713 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02714 n_bytes); 02715 02716 _dbus_close (fd, NULL); 02717 02718 return TRUE; 02719 } 02720 02726 void 02727 _dbus_exit (int code) 02728 { 02729 _exit (code); 02730 } 02731 02740 const char* 02741 _dbus_strerror (int error_number) 02742 { 02743 const char *msg; 02744 02745 msg = strerror (error_number); 02746 if (msg == NULL) 02747 msg = "unknown"; 02748 02749 return msg; 02750 } 02751 02755 void 02756 _dbus_disable_sigpipe (void) 02757 { 02758 signal (SIGPIPE, SIG_IGN); 02759 } 02760 02768 void 02769 _dbus_fd_set_close_on_exec (intptr_t fd) 02770 { 02771 int val; 02772 02773 val = fcntl (fd, F_GETFD, 0); 02774 02775 if (val < 0) 02776 return; 02777 02778 val |= FD_CLOEXEC; 02779 02780 fcntl (fd, F_SETFD, val); 02781 } 02782 02790 dbus_bool_t 02791 _dbus_close (int fd, 02792 DBusError *error) 02793 { 02794 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02795 02796 again: 02797 if (close (fd) < 0) 02798 { 02799 if (errno == EINTR) 02800 goto again; 02801 02802 dbus_set_error (error, _dbus_error_from_errno (errno), 02803 "Could not close fd %d", fd); 02804 return FALSE; 02805 } 02806 02807 return TRUE; 02808 } 02809 02817 int 02818 _dbus_dup(int fd, 02819 DBusError *error) 02820 { 02821 int new_fd; 02822 02823 #ifdef F_DUPFD_CLOEXEC 02824 dbus_bool_t cloexec_done; 02825 02826 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02827 cloexec_done = new_fd >= 0; 02828 02829 if (new_fd < 0 && errno == EINVAL) 02830 #endif 02831 { 02832 new_fd = fcntl(fd, F_DUPFD, 3); 02833 } 02834 02835 if (new_fd < 0) { 02836 02837 dbus_set_error (error, _dbus_error_from_errno (errno), 02838 "Could not duplicate fd %d", fd); 02839 return -1; 02840 } 02841 02842 #ifdef F_DUPFD_CLOEXEC 02843 if (!cloexec_done) 02844 #endif 02845 { 02846 _dbus_fd_set_close_on_exec(new_fd); 02847 } 02848 02849 return new_fd; 02850 } 02851 02859 dbus_bool_t 02860 _dbus_set_fd_nonblocking (int fd, 02861 DBusError *error) 02862 { 02863 int val; 02864 02865 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02866 02867 val = fcntl (fd, F_GETFL, 0); 02868 if (val < 0) 02869 { 02870 dbus_set_error (error, _dbus_error_from_errno (errno), 02871 "Failed to get flags from file descriptor %d: %s", 02872 fd, _dbus_strerror (errno)); 02873 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02874 _dbus_strerror (errno)); 02875 return FALSE; 02876 } 02877 02878 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02879 { 02880 dbus_set_error (error, _dbus_error_from_errno (errno), 02881 "Failed to set nonblocking flag of file descriptor %d: %s", 02882 fd, _dbus_strerror (errno)); 02883 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02884 fd, _dbus_strerror (errno)); 02885 02886 return FALSE; 02887 } 02888 02889 return TRUE; 02890 } 02891 02897 void 02898 _dbus_print_backtrace (void) 02899 { 02900 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02901 void *bt[500]; 02902 int bt_size; 02903 int i; 02904 char **syms; 02905 02906 bt_size = backtrace (bt, 500); 02907 02908 syms = backtrace_symbols (bt, bt_size); 02909 02910 i = 0; 02911 while (i < bt_size) 02912 { 02913 /* don't use dbus_warn since it can _dbus_abort() */ 02914 fprintf (stderr, " %s\n", syms[i]); 02915 ++i; 02916 } 02917 fflush (stderr); 02918 02919 free (syms); 02920 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02921 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02922 #else 02923 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02924 #endif 02925 } 02926 02944 dbus_bool_t 02945 _dbus_full_duplex_pipe (int *fd1, 02946 int *fd2, 02947 dbus_bool_t blocking, 02948 DBusError *error) 02949 { 02950 #ifdef HAVE_SOCKETPAIR 02951 int fds[2]; 02952 int retval; 02953 02954 #ifdef SOCK_CLOEXEC 02955 dbus_bool_t cloexec_done; 02956 02957 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 02958 cloexec_done = retval >= 0; 02959 02960 if (retval < 0 && errno == EINVAL) 02961 #endif 02962 { 02963 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 02964 } 02965 02966 if (retval < 0) 02967 { 02968 dbus_set_error (error, _dbus_error_from_errno (errno), 02969 "Could not create full-duplex pipe"); 02970 return FALSE; 02971 } 02972 02973 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02974 02975 #ifdef SOCK_CLOEXEC 02976 if (!cloexec_done) 02977 #endif 02978 { 02979 _dbus_fd_set_close_on_exec (fds[0]); 02980 _dbus_fd_set_close_on_exec (fds[1]); 02981 } 02982 02983 if (!blocking && 02984 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02985 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02986 { 02987 dbus_set_error (error, _dbus_error_from_errno (errno), 02988 "Could not set full-duplex pipe nonblocking"); 02989 02990 _dbus_close (fds[0], NULL); 02991 _dbus_close (fds[1], NULL); 02992 02993 return FALSE; 02994 } 02995 02996 *fd1 = fds[0]; 02997 *fd2 = fds[1]; 02998 02999 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 03000 *fd1, *fd2); 03001 03002 return TRUE; 03003 #else 03004 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 03005 dbus_set_error (error, DBUS_ERROR_FAILED, 03006 "_dbus_full_duplex_pipe() not implemented on this OS"); 03007 return FALSE; 03008 #endif 03009 } 03010 03019 int 03020 _dbus_printf_string_upper_bound (const char *format, 03021 va_list args) 03022 { 03023 char static_buf[1024]; 03024 int bufsize = sizeof (static_buf); 03025 int len; 03026 03027 len = vsnprintf (static_buf, bufsize, format, args); 03028 03029 /* If vsnprintf() returned non-negative, then either the string fits in 03030 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03031 * returns the number of characters that were needed, or this OS returns the 03032 * truncated length. 03033 * 03034 * We ignore the possibility that snprintf might just ignore the length and 03035 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03036 * If your libc is really that bad, come back when you have a better one. */ 03037 if (len == bufsize) 03038 { 03039 /* This could be the truncated length (Tru64 and IRIX have this bug), 03040 * or the real length could be coincidentally the same. Which is it? 03041 * If vsnprintf returns the truncated length, we'll go to the slow 03042 * path. */ 03043 if (vsnprintf (static_buf, 1, format, args) == 1) 03044 len = -1; 03045 } 03046 03047 /* If vsnprintf() returned negative, we have to do more work. 03048 * HP-UX returns negative. */ 03049 while (len < 0) 03050 { 03051 char *buf; 03052 03053 bufsize *= 2; 03054 03055 buf = dbus_malloc (bufsize); 03056 03057 if (buf == NULL) 03058 return -1; 03059 03060 len = vsnprintf (buf, bufsize, format, args); 03061 dbus_free (buf); 03062 03063 /* If the reported length is exactly the buffer size, round up to the 03064 * next size, in case vsnprintf has been returning the truncated 03065 * length */ 03066 if (len == bufsize) 03067 len = -1; 03068 } 03069 03070 return len; 03071 } 03072 03079 const char* 03080 _dbus_get_tmpdir(void) 03081 { 03082 static const char* tmpdir = NULL; 03083 03084 if (tmpdir == NULL) 03085 { 03086 /* TMPDIR is what glibc uses, then 03087 * glibc falls back to the P_tmpdir macro which 03088 * just expands to "/tmp" 03089 */ 03090 if (tmpdir == NULL) 03091 tmpdir = getenv("TMPDIR"); 03092 03093 /* These two env variables are probably 03094 * broken, but maybe some OS uses them? 03095 */ 03096 if (tmpdir == NULL) 03097 tmpdir = getenv("TMP"); 03098 if (tmpdir == NULL) 03099 tmpdir = getenv("TEMP"); 03100 03101 /* And this is the sane fallback. */ 03102 if (tmpdir == NULL) 03103 tmpdir = "/tmp"; 03104 } 03105 03106 _dbus_assert(tmpdir != NULL); 03107 03108 return tmpdir; 03109 } 03110 03130 static dbus_bool_t 03131 _read_subprocess_line_argv (const char *progpath, 03132 dbus_bool_t path_fallback, 03133 char * const *argv, 03134 DBusString *result, 03135 DBusError *error) 03136 { 03137 int result_pipe[2] = { -1, -1 }; 03138 int errors_pipe[2] = { -1, -1 }; 03139 pid_t pid; 03140 int ret; 03141 int status; 03142 int orig_len; 03143 int i; 03144 03145 dbus_bool_t retval; 03146 sigset_t new_set, old_set; 03147 03148 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03149 retval = FALSE; 03150 03151 /* We need to block any existing handlers for SIGCHLD temporarily; they 03152 * will cause waitpid() below to fail. 03153 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03154 */ 03155 sigemptyset (&new_set); 03156 sigaddset (&new_set, SIGCHLD); 03157 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03158 03159 orig_len = _dbus_string_get_length (result); 03160 03161 #define READ_END 0 03162 #define WRITE_END 1 03163 if (pipe (result_pipe) < 0) 03164 { 03165 dbus_set_error (error, _dbus_error_from_errno (errno), 03166 "Failed to create a pipe to call %s: %s", 03167 progpath, _dbus_strerror (errno)); 03168 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03169 progpath, _dbus_strerror (errno)); 03170 goto out; 03171 } 03172 if (pipe (errors_pipe) < 0) 03173 { 03174 dbus_set_error (error, _dbus_error_from_errno (errno), 03175 "Failed to create a pipe to call %s: %s", 03176 progpath, _dbus_strerror (errno)); 03177 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03178 progpath, _dbus_strerror (errno)); 03179 goto out; 03180 } 03181 03182 pid = fork (); 03183 if (pid < 0) 03184 { 03185 dbus_set_error (error, _dbus_error_from_errno (errno), 03186 "Failed to fork() to call %s: %s", 03187 progpath, _dbus_strerror (errno)); 03188 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03189 progpath, _dbus_strerror (errno)); 03190 goto out; 03191 } 03192 03193 if (pid == 0) 03194 { 03195 /* child process */ 03196 int maxfds; 03197 int fd; 03198 03199 fd = open ("/dev/null", O_RDWR); 03200 if (fd == -1) 03201 /* huh?! can't open /dev/null? */ 03202 _exit (1); 03203 03204 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03205 03206 /* set-up stdXXX */ 03207 close (result_pipe[READ_END]); 03208 close (errors_pipe[READ_END]); 03209 close (0); /* close stdin */ 03210 close (1); /* close stdout */ 03211 close (2); /* close stderr */ 03212 03213 if (dup2 (fd, 0) == -1) 03214 _exit (1); 03215 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03216 _exit (1); 03217 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03218 _exit (1); 03219 03220 maxfds = sysconf (_SC_OPEN_MAX); 03221 /* Pick something reasonable if for some reason sysconf 03222 * says unlimited. 03223 */ 03224 if (maxfds < 0) 03225 maxfds = 1024; 03226 /* close all inherited fds */ 03227 for (i = 3; i < maxfds; i++) 03228 close (i); 03229 03230 sigprocmask (SIG_SETMASK, &old_set, NULL); 03231 03232 /* If it looks fully-qualified, try execv first */ 03233 if (progpath[0] == '/') 03234 { 03235 execv (progpath, argv); 03236 /* Ok, that failed. Now if path_fallback is given, let's 03237 * try unqualified. This is mostly a hack to work 03238 * around systems which ship dbus-launch in /usr/bin 03239 * but everything else in /bin (because dbus-launch 03240 * depends on X11). 03241 */ 03242 if (path_fallback) 03243 /* We must have a slash, because we checked above */ 03244 execvp (strrchr (progpath, '/')+1, argv); 03245 } 03246 else 03247 execvp (progpath, argv); 03248 03249 /* still nothing, we failed */ 03250 _exit (1); 03251 } 03252 03253 /* parent process */ 03254 close (result_pipe[WRITE_END]); 03255 close (errors_pipe[WRITE_END]); 03256 result_pipe[WRITE_END] = -1; 03257 errors_pipe[WRITE_END] = -1; 03258 03259 ret = 0; 03260 do 03261 { 03262 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03263 } 03264 while (ret > 0); 03265 03266 /* reap the child process to avoid it lingering as zombie */ 03267 do 03268 { 03269 ret = waitpid (pid, &status, 0); 03270 } 03271 while (ret == -1 && errno == EINTR); 03272 03273 /* We succeeded if the process exited with status 0 and 03274 anything was read */ 03275 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03276 { 03277 /* The process ended with error */ 03278 DBusString error_message; 03279 if (!_dbus_string_init (&error_message)) 03280 { 03281 _DBUS_SET_OOM (error); 03282 goto out; 03283 } 03284 03285 ret = 0; 03286 do 03287 { 03288 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03289 } 03290 while (ret > 0); 03291 03292 _dbus_string_set_length (result, orig_len); 03293 if (_dbus_string_get_length (&error_message) > 0) 03294 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03295 "%s terminated abnormally with the following error: %s", 03296 progpath, _dbus_string_get_data (&error_message)); 03297 else 03298 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03299 "%s terminated abnormally without any error message", 03300 progpath); 03301 goto out; 03302 } 03303 03304 retval = TRUE; 03305 03306 out: 03307 sigprocmask (SIG_SETMASK, &old_set, NULL); 03308 03309 if (retval) 03310 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03311 else 03312 _DBUS_ASSERT_ERROR_IS_SET (error); 03313 03314 if (result_pipe[0] != -1) 03315 close (result_pipe[0]); 03316 if (result_pipe[1] != -1) 03317 close (result_pipe[1]); 03318 if (errors_pipe[0] != -1) 03319 close (errors_pipe[0]); 03320 if (errors_pipe[1] != -1) 03321 close (errors_pipe[1]); 03322 03323 return retval; 03324 } 03325 03337 dbus_bool_t 03338 _dbus_get_autolaunch_address (const char *scope, 03339 DBusString *address, 03340 DBusError *error) 03341 { 03342 #if 1 03343 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03344 * but that's done elsewhere, and if it worked, this function wouldn't 03345 * be called.) */ 03346 const char *display; 03347 static char *argv[6]; 03348 int i; 03349 DBusString uuid; 03350 dbus_bool_t retval; 03351 03352 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03353 retval = FALSE; 03354 03355 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03356 * dbus-launch-x11 is just going to fail. Rather than trying to 03357 * run it, we might as well bail out early with a nice error. */ 03358 display = _dbus_getenv ("DISPLAY"); 03359 03360 if (display == NULL || display[0] == '\0') 03361 { 03362 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03363 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03364 return FALSE; 03365 } 03366 03367 if (!_dbus_string_init (&uuid)) 03368 { 03369 _DBUS_SET_OOM (error); 03370 return FALSE; 03371 } 03372 03373 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03374 { 03375 _DBUS_SET_OOM (error); 03376 goto out; 03377 } 03378 03379 i = 0; 03380 argv[i] = "dbus-launch"; 03381 ++i; 03382 argv[i] = "--autolaunch"; 03383 ++i; 03384 argv[i] = _dbus_string_get_data (&uuid); 03385 ++i; 03386 argv[i] = "--binary-syntax"; 03387 ++i; 03388 argv[i] = "--close-stderr"; 03389 ++i; 03390 argv[i] = NULL; 03391 ++i; 03392 03393 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03394 03395 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03396 TRUE, 03397 argv, address, error); 03398 03399 out: 03400 _dbus_string_free (&uuid); 03401 return retval; 03402 #else 03403 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03404 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03405 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03406 return FALSE; 03407 #endif 03408 } 03409 03428 dbus_bool_t 03429 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03430 dbus_bool_t create_if_not_found, 03431 DBusError *error) 03432 { 03433 DBusString filename; 03434 dbus_bool_t b; 03435 03436 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03437 03438 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03439 if (b) 03440 return TRUE; 03441 03442 dbus_error_free (error); 03443 03444 /* Fallback to the system machine ID */ 03445 _dbus_string_init_const (&filename, "/etc/machine-id"); 03446 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03447 } 03448 03449 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03450 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03451 03458 dbus_bool_t 03459 _dbus_lookup_launchd_socket (DBusString *socket_path, 03460 const char *launchd_env_var, 03461 DBusError *error) 03462 { 03463 #ifdef DBUS_ENABLE_LAUNCHD 03464 char *argv[4]; 03465 int i; 03466 03467 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03468 03469 i = 0; 03470 argv[i] = "launchctl"; 03471 ++i; 03472 argv[i] = "getenv"; 03473 ++i; 03474 argv[i] = (char*)launchd_env_var; 03475 ++i; 03476 argv[i] = NULL; 03477 ++i; 03478 03479 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03480 03481 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03482 { 03483 return FALSE; 03484 } 03485 03486 /* no error, but no result either */ 03487 if (_dbus_string_get_length(socket_path) == 0) 03488 { 03489 return FALSE; 03490 } 03491 03492 /* strip the carriage-return */ 03493 _dbus_string_shorten(socket_path, 1); 03494 return TRUE; 03495 #else /* DBUS_ENABLE_LAUNCHD */ 03496 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03497 "can't lookup socket from launchd; launchd support not compiled in"); 03498 return FALSE; 03499 #endif 03500 } 03501 03502 #ifdef DBUS_ENABLE_LAUNCHD 03503 static dbus_bool_t 03504 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03505 { 03506 dbus_bool_t valid_socket; 03507 DBusString socket_path; 03508 03509 if (!_dbus_string_init (&socket_path)) 03510 { 03511 _DBUS_SET_OOM (error); 03512 return FALSE; 03513 } 03514 03515 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03516 03517 if (dbus_error_is_set(error)) 03518 { 03519 _dbus_string_free(&socket_path); 03520 return FALSE; 03521 } 03522 03523 if (!valid_socket) 03524 { 03525 dbus_set_error(error, "no socket path", 03526 "launchd did not provide a socket path, " 03527 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03528 _dbus_string_free(&socket_path); 03529 return FALSE; 03530 } 03531 if (!_dbus_string_append (address, "unix:path=")) 03532 { 03533 _DBUS_SET_OOM (error); 03534 _dbus_string_free(&socket_path); 03535 return FALSE; 03536 } 03537 if (!_dbus_string_copy (&socket_path, 0, address, 03538 _dbus_string_get_length (address))) 03539 { 03540 _DBUS_SET_OOM (error); 03541 _dbus_string_free(&socket_path); 03542 return FALSE; 03543 } 03544 03545 _dbus_string_free(&socket_path); 03546 return TRUE; 03547 } 03548 #endif 03549 03569 dbus_bool_t 03570 _dbus_lookup_session_address (dbus_bool_t *supported, 03571 DBusString *address, 03572 DBusError *error) 03573 { 03574 #ifdef DBUS_ENABLE_LAUNCHD 03575 *supported = TRUE; 03576 return _dbus_lookup_session_address_launchd (address, error); 03577 #else 03578 /* On non-Mac Unix platforms, if the session address isn't already 03579 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03580 * fall back to the autolaunch: global default; see 03581 * init_session_address in dbus/dbus-bus.c. */ 03582 *supported = FALSE; 03583 return TRUE; 03584 #endif 03585 } 03586 03604 dbus_bool_t 03605 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03606 { 03607 const char *xdg_data_home; 03608 const char *xdg_data_dirs; 03609 DBusString servicedir_path; 03610 03611 if (!_dbus_string_init (&servicedir_path)) 03612 return FALSE; 03613 03614 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03615 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03616 03617 if (xdg_data_home != NULL) 03618 { 03619 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03620 goto oom; 03621 } 03622 else 03623 { 03624 const DBusString *homedir; 03625 DBusString local_share; 03626 03627 if (!_dbus_homedir_from_current_process (&homedir)) 03628 goto oom; 03629 03630 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03631 goto oom; 03632 03633 _dbus_string_init_const (&local_share, "/.local/share"); 03634 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03635 goto oom; 03636 } 03637 03638 if (!_dbus_string_append (&servicedir_path, ":")) 03639 goto oom; 03640 03641 if (xdg_data_dirs != NULL) 03642 { 03643 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03644 goto oom; 03645 03646 if (!_dbus_string_append (&servicedir_path, ":")) 03647 goto oom; 03648 } 03649 else 03650 { 03651 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03652 goto oom; 03653 } 03654 03655 /* 03656 * add configured datadir to defaults 03657 * this may be the same as an xdg dir 03658 * however the config parser should take 03659 * care of duplicates 03660 */ 03661 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03662 goto oom; 03663 03664 if (!_dbus_split_paths_and_append (&servicedir_path, 03665 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03666 dirs)) 03667 goto oom; 03668 03669 _dbus_string_free (&servicedir_path); 03670 return TRUE; 03671 03672 oom: 03673 _dbus_string_free (&servicedir_path); 03674 return FALSE; 03675 } 03676 03677 03696 dbus_bool_t 03697 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03698 { 03699 const char *xdg_data_dirs; 03700 DBusString servicedir_path; 03701 03702 if (!_dbus_string_init (&servicedir_path)) 03703 return FALSE; 03704 03705 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03706 03707 if (xdg_data_dirs != NULL) 03708 { 03709 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03710 goto oom; 03711 03712 if (!_dbus_string_append (&servicedir_path, ":")) 03713 goto oom; 03714 } 03715 else 03716 { 03717 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03718 goto oom; 03719 } 03720 03721 /* 03722 * Add configured datadir to defaults. This may be the same as one 03723 * of the XDG directories. However, the config parser should take 03724 * care of the duplicates. 03725 * 03726 * Also, append /lib as counterpart of /usr/share on the root 03727 * directory (the root directory does not know /share), in order to 03728 * facilitate early boot system bus activation where /usr might not 03729 * be available. 03730 */ 03731 if (!_dbus_string_append (&servicedir_path, 03732 DBUS_DATADIR":" 03733 "/lib:")) 03734 goto oom; 03735 03736 if (!_dbus_split_paths_and_append (&servicedir_path, 03737 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03738 dirs)) 03739 goto oom; 03740 03741 _dbus_string_free (&servicedir_path); 03742 return TRUE; 03743 03744 oom: 03745 _dbus_string_free (&servicedir_path); 03746 return FALSE; 03747 } 03748 03757 dbus_bool_t 03758 _dbus_append_system_config_file (DBusString *str) 03759 { 03760 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03761 } 03762 03769 dbus_bool_t 03770 _dbus_append_session_config_file (DBusString *str) 03771 { 03772 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03773 } 03774 03782 void 03783 _dbus_flush_caches (void) 03784 { 03785 _dbus_user_database_flush_system (); 03786 } 03787 03801 dbus_bool_t 03802 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03803 DBusCredentials *credentials) 03804 { 03805 DBusString homedir; 03806 DBusString dotdir; 03807 dbus_uid_t uid; 03808 03809 _dbus_assert (credentials != NULL); 03810 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03811 03812 if (!_dbus_string_init (&homedir)) 03813 return FALSE; 03814 03815 uid = _dbus_credentials_get_unix_uid (credentials); 03816 _dbus_assert (uid != DBUS_UID_UNSET); 03817 03818 if (!_dbus_homedir_from_uid (uid, &homedir)) 03819 goto failed; 03820 03821 #ifdef DBUS_BUILD_TESTS 03822 { 03823 const char *override; 03824 03825 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03826 if (override != NULL && *override != '\0') 03827 { 03828 _dbus_string_set_length (&homedir, 0); 03829 if (!_dbus_string_append (&homedir, override)) 03830 goto failed; 03831 03832 _dbus_verbose ("Using fake homedir for testing: %s\n", 03833 _dbus_string_get_const_data (&homedir)); 03834 } 03835 else 03836 { 03837 static dbus_bool_t already_warned = FALSE; 03838 if (!already_warned) 03839 { 03840 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03841 already_warned = TRUE; 03842 } 03843 } 03844 } 03845 #endif 03846 03847 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03848 if (!_dbus_concat_dir_and_file (&homedir, 03849 &dotdir)) 03850 goto failed; 03851 03852 if (!_dbus_string_copy (&homedir, 0, 03853 directory, _dbus_string_get_length (directory))) { 03854 goto failed; 03855 } 03856 03857 _dbus_string_free (&homedir); 03858 return TRUE; 03859 03860 failed: 03861 _dbus_string_free (&homedir); 03862 return FALSE; 03863 } 03864 03865 //PENDING(kdab) docs 03866 dbus_bool_t 03867 _dbus_daemon_publish_session_bus_address (const char* addr, 03868 const char *scope) 03869 { 03870 return TRUE; 03871 } 03872 03873 //PENDING(kdab) docs 03874 void 03875 _dbus_daemon_unpublish_session_bus_address (void) 03876 { 03877 03878 } 03879 03886 dbus_bool_t 03887 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03888 { 03889 return errno == EAGAIN || errno == EWOULDBLOCK; 03890 } 03891 03899 dbus_bool_t 03900 _dbus_delete_directory (const DBusString *filename, 03901 DBusError *error) 03902 { 03903 const char *filename_c; 03904 03905 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03906 03907 filename_c = _dbus_string_get_const_data (filename); 03908 03909 if (rmdir (filename_c) != 0) 03910 { 03911 dbus_set_error (error, DBUS_ERROR_FAILED, 03912 "Failed to remove directory %s: %s\n", 03913 filename_c, _dbus_strerror (errno)); 03914 return FALSE; 03915 } 03916 03917 return TRUE; 03918 } 03919 03927 dbus_bool_t 03928 _dbus_socket_can_pass_unix_fd(int fd) { 03929 03930 #ifdef SCM_RIGHTS 03931 union { 03932 struct sockaddr sa; 03933 struct sockaddr_storage storage; 03934 struct sockaddr_un un; 03935 } sa_buf; 03936 03937 socklen_t sa_len = sizeof(sa_buf); 03938 03939 _DBUS_ZERO(sa_buf); 03940 03941 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03942 return FALSE; 03943 03944 return sa_buf.sa.sa_family == AF_UNIX; 03945 03946 #else 03947 return FALSE; 03948 03949 #endif 03950 } 03951 03952 03953 /* 03954 * replaces the term DBUS_PREFIX in configure_time_path by the 03955 * current dbus installation directory. On unix this function is a noop 03956 * 03957 * @param configure_time_path 03958 * @return real path 03959 */ 03960 const char * 03961 _dbus_replace_install_prefix (const char *configure_time_path) 03962 { 03963 return configure_time_path; 03964 } 03965 03966 /* tests in dbus-sysdeps-util.c */
1.7.5.1