|
D-Bus
1.5.10
|
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 return -1; 01213 } 01214 01215 tmp = ai; 01216 while (tmp) 01217 { 01218 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01219 { 01220 freeaddrinfo(ai); 01221 _DBUS_ASSERT_ERROR_IS_SET(error); 01222 return -1; 01223 } 01224 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01225 01226 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01227 { 01228 saved_errno = errno; 01229 _dbus_close(fd, NULL); 01230 fd = -1; 01231 tmp = tmp->ai_next; 01232 continue; 01233 } 01234 01235 break; 01236 } 01237 freeaddrinfo(ai); 01238 01239 if (fd == -1) 01240 { 01241 dbus_set_error (error, 01242 _dbus_error_from_errno (saved_errno), 01243 "Failed to connect to socket \"%s:%s\" %s", 01244 host, port, _dbus_strerror(saved_errno)); 01245 return -1; 01246 } 01247 01248 if (noncefile != NULL) 01249 { 01250 DBusString noncefileStr; 01251 dbus_bool_t ret; 01252 _dbus_string_init_const (&noncefileStr, noncefile); 01253 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01254 _dbus_string_free (&noncefileStr); 01255 01256 if (!ret) 01257 { 01258 _dbus_close (fd, NULL); 01259 return -1; 01260 } 01261 } 01262 01263 if (!_dbus_set_fd_nonblocking (fd, error)) 01264 { 01265 _dbus_close (fd, NULL); 01266 return -1; 01267 } 01268 01269 return fd; 01270 } 01271 01288 int 01289 _dbus_listen_tcp_socket (const char *host, 01290 const char *port, 01291 const char *family, 01292 DBusString *retport, 01293 int **fds_p, 01294 DBusError *error) 01295 { 01296 int saved_errno; 01297 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01298 struct addrinfo hints; 01299 struct addrinfo *ai, *tmp; 01300 unsigned int reuseaddr; 01301 01302 *fds_p = NULL; 01303 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01304 01305 _DBUS_ZERO (hints); 01306 01307 if (!family) 01308 hints.ai_family = AF_UNSPEC; 01309 else if (!strcmp(family, "ipv4")) 01310 hints.ai_family = AF_INET; 01311 else if (!strcmp(family, "ipv6")) 01312 hints.ai_family = AF_INET6; 01313 else 01314 { 01315 dbus_set_error (error, 01316 DBUS_ERROR_BAD_ADDRESS, 01317 "Unknown address family %s", family); 01318 return -1; 01319 } 01320 01321 hints.ai_protocol = IPPROTO_TCP; 01322 hints.ai_socktype = SOCK_STREAM; 01323 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01324 01325 redo_lookup_with_port: 01326 ai = NULL; 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 goto failed; 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 02414 int 02415 _dbus_poll (DBusPollFD *fds, 02416 int n_fds, 02417 int timeout_milliseconds) 02418 { 02419 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02420 /* This big thing is a constant expression and should get optimized 02421 * out of existence. So it's more robust than a configure check at 02422 * no cost. 02423 */ 02424 if (_DBUS_POLLIN == POLLIN && 02425 _DBUS_POLLPRI == POLLPRI && 02426 _DBUS_POLLOUT == POLLOUT && 02427 _DBUS_POLLERR == POLLERR && 02428 _DBUS_POLLHUP == POLLHUP && 02429 _DBUS_POLLNVAL == POLLNVAL && 02430 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02431 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02432 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02433 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02434 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02435 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02436 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02437 { 02438 return poll ((struct pollfd*) fds, 02439 n_fds, 02440 timeout_milliseconds); 02441 } 02442 else 02443 { 02444 /* We have to convert the DBusPollFD to an array of 02445 * struct pollfd, poll, and convert back. 02446 */ 02447 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02448 return -1; 02449 } 02450 #else /* ! HAVE_POLL */ 02451 02452 fd_set read_set, write_set, err_set; 02453 int max_fd = 0; 02454 int i; 02455 struct timeval tv; 02456 int ready; 02457 02458 FD_ZERO (&read_set); 02459 FD_ZERO (&write_set); 02460 FD_ZERO (&err_set); 02461 02462 for (i = 0; i < n_fds; i++) 02463 { 02464 DBusPollFD *fdp = &fds[i]; 02465 02466 if (fdp->events & _DBUS_POLLIN) 02467 FD_SET (fdp->fd, &read_set); 02468 02469 if (fdp->events & _DBUS_POLLOUT) 02470 FD_SET (fdp->fd, &write_set); 02471 02472 FD_SET (fdp->fd, &err_set); 02473 02474 max_fd = MAX (max_fd, fdp->fd); 02475 } 02476 02477 tv.tv_sec = timeout_milliseconds / 1000; 02478 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02479 02480 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02481 timeout_milliseconds < 0 ? NULL : &tv); 02482 02483 if (ready > 0) 02484 { 02485 for (i = 0; i < n_fds; i++) 02486 { 02487 DBusPollFD *fdp = &fds[i]; 02488 02489 fdp->revents = 0; 02490 02491 if (FD_ISSET (fdp->fd, &read_set)) 02492 fdp->revents |= _DBUS_POLLIN; 02493 02494 if (FD_ISSET (fdp->fd, &write_set)) 02495 fdp->revents |= _DBUS_POLLOUT; 02496 02497 if (FD_ISSET (fdp->fd, &err_set)) 02498 fdp->revents |= _DBUS_POLLERR; 02499 } 02500 } 02501 02502 return ready; 02503 #endif 02504 } 02505 02513 void 02514 _dbus_get_current_time (long *tv_sec, 02515 long *tv_usec) 02516 { 02517 #ifdef HAVE_MONOTONIC_CLOCK 02518 struct timespec ts; 02519 clock_gettime (CLOCK_MONOTONIC, &ts); 02520 02521 if (tv_sec) 02522 *tv_sec = ts.tv_sec; 02523 if (tv_usec) 02524 *tv_usec = ts.tv_nsec / 1000; 02525 #else 02526 struct timeval t; 02527 02528 gettimeofday (&t, NULL); 02529 02530 if (tv_sec) 02531 *tv_sec = t.tv_sec; 02532 if (tv_usec) 02533 *tv_usec = t.tv_usec; 02534 #endif 02535 } 02536 02545 dbus_bool_t 02546 _dbus_create_directory (const DBusString *filename, 02547 DBusError *error) 02548 { 02549 const char *filename_c; 02550 02551 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02552 02553 filename_c = _dbus_string_get_const_data (filename); 02554 02555 if (mkdir (filename_c, 0700) < 0) 02556 { 02557 if (errno == EEXIST) 02558 return TRUE; 02559 02560 dbus_set_error (error, DBUS_ERROR_FAILED, 02561 "Failed to create directory %s: %s\n", 02562 filename_c, _dbus_strerror (errno)); 02563 return FALSE; 02564 } 02565 else 02566 return TRUE; 02567 } 02568 02579 dbus_bool_t 02580 _dbus_concat_dir_and_file (DBusString *dir, 02581 const DBusString *next_component) 02582 { 02583 dbus_bool_t dir_ends_in_slash; 02584 dbus_bool_t file_starts_with_slash; 02585 02586 if (_dbus_string_get_length (dir) == 0 || 02587 _dbus_string_get_length (next_component) == 0) 02588 return TRUE; 02589 02590 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02591 _dbus_string_get_length (dir) - 1); 02592 02593 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02594 02595 if (dir_ends_in_slash && file_starts_with_slash) 02596 { 02597 _dbus_string_shorten (dir, 1); 02598 } 02599 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02600 { 02601 if (!_dbus_string_append_byte (dir, '/')) 02602 return FALSE; 02603 } 02604 02605 return _dbus_string_copy (next_component, 0, dir, 02606 _dbus_string_get_length (dir)); 02607 } 02608 02610 #define NANOSECONDS_PER_SECOND 1000000000 02611 02612 #define MICROSECONDS_PER_SECOND 1000000 02613 02614 #define MILLISECONDS_PER_SECOND 1000 02615 02616 #define NANOSECONDS_PER_MILLISECOND 1000000 02617 02618 #define MICROSECONDS_PER_MILLISECOND 1000 02619 02624 void 02625 _dbus_sleep_milliseconds (int milliseconds) 02626 { 02627 #ifdef HAVE_NANOSLEEP 02628 struct timespec req; 02629 struct timespec rem; 02630 02631 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02632 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02633 rem.tv_sec = 0; 02634 rem.tv_nsec = 0; 02635 02636 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02637 req = rem; 02638 #elif defined (HAVE_USLEEP) 02639 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02640 #else /* ! HAVE_USLEEP */ 02641 sleep (MAX (milliseconds / 1000, 1)); 02642 #endif 02643 } 02644 02645 static dbus_bool_t 02646 _dbus_generate_pseudorandom_bytes (DBusString *str, 02647 int n_bytes) 02648 { 02649 int old_len; 02650 char *p; 02651 02652 old_len = _dbus_string_get_length (str); 02653 02654 if (!_dbus_string_lengthen (str, n_bytes)) 02655 return FALSE; 02656 02657 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02658 02659 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02660 02661 return TRUE; 02662 } 02663 02672 dbus_bool_t 02673 _dbus_generate_random_bytes (DBusString *str, 02674 int n_bytes) 02675 { 02676 int old_len; 02677 int fd; 02678 02679 /* FALSE return means "no memory", if it could 02680 * mean something else then we'd need to return 02681 * a DBusError. So we always fall back to pseudorandom 02682 * if the I/O fails. 02683 */ 02684 02685 old_len = _dbus_string_get_length (str); 02686 fd = -1; 02687 02688 /* note, urandom on linux will fall back to pseudorandom */ 02689 fd = open ("/dev/urandom", O_RDONLY); 02690 if (fd < 0) 02691 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02692 02693 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02694 02695 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02696 { 02697 _dbus_close (fd, NULL); 02698 _dbus_string_set_length (str, old_len); 02699 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02700 } 02701 02702 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02703 n_bytes); 02704 02705 _dbus_close (fd, NULL); 02706 02707 return TRUE; 02708 } 02709 02715 void 02716 _dbus_exit (int code) 02717 { 02718 _exit (code); 02719 } 02720 02729 const char* 02730 _dbus_strerror (int error_number) 02731 { 02732 const char *msg; 02733 02734 msg = strerror (error_number); 02735 if (msg == NULL) 02736 msg = "unknown"; 02737 02738 return msg; 02739 } 02740 02744 void 02745 _dbus_disable_sigpipe (void) 02746 { 02747 signal (SIGPIPE, SIG_IGN); 02748 } 02749 02757 void 02758 _dbus_fd_set_close_on_exec (intptr_t fd) 02759 { 02760 int val; 02761 02762 val = fcntl (fd, F_GETFD, 0); 02763 02764 if (val < 0) 02765 return; 02766 02767 val |= FD_CLOEXEC; 02768 02769 fcntl (fd, F_SETFD, val); 02770 } 02771 02779 dbus_bool_t 02780 _dbus_close (int fd, 02781 DBusError *error) 02782 { 02783 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02784 02785 again: 02786 if (close (fd) < 0) 02787 { 02788 if (errno == EINTR) 02789 goto again; 02790 02791 dbus_set_error (error, _dbus_error_from_errno (errno), 02792 "Could not close fd %d", fd); 02793 return FALSE; 02794 } 02795 02796 return TRUE; 02797 } 02798 02806 int 02807 _dbus_dup(int fd, 02808 DBusError *error) 02809 { 02810 int new_fd; 02811 02812 #ifdef F_DUPFD_CLOEXEC 02813 dbus_bool_t cloexec_done; 02814 02815 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02816 cloexec_done = new_fd >= 0; 02817 02818 if (new_fd < 0 && errno == EINVAL) 02819 #endif 02820 { 02821 new_fd = fcntl(fd, F_DUPFD, 3); 02822 } 02823 02824 if (new_fd < 0) { 02825 02826 dbus_set_error (error, _dbus_error_from_errno (errno), 02827 "Could not duplicate fd %d", fd); 02828 return -1; 02829 } 02830 02831 #ifdef F_DUPFD_CLOEXEC 02832 if (!cloexec_done) 02833 #endif 02834 { 02835 _dbus_fd_set_close_on_exec(new_fd); 02836 } 02837 02838 return new_fd; 02839 } 02840 02848 dbus_bool_t 02849 _dbus_set_fd_nonblocking (int fd, 02850 DBusError *error) 02851 { 02852 int val; 02853 02854 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02855 02856 val = fcntl (fd, F_GETFL, 0); 02857 if (val < 0) 02858 { 02859 dbus_set_error (error, _dbus_error_from_errno (errno), 02860 "Failed to get flags from file descriptor %d: %s", 02861 fd, _dbus_strerror (errno)); 02862 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02863 _dbus_strerror (errno)); 02864 return FALSE; 02865 } 02866 02867 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02868 { 02869 dbus_set_error (error, _dbus_error_from_errno (errno), 02870 "Failed to set nonblocking flag of file descriptor %d: %s", 02871 fd, _dbus_strerror (errno)); 02872 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02873 fd, _dbus_strerror (errno)); 02874 02875 return FALSE; 02876 } 02877 02878 return TRUE; 02879 } 02880 02886 void 02887 _dbus_print_backtrace (void) 02888 { 02889 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02890 void *bt[500]; 02891 int bt_size; 02892 int i; 02893 char **syms; 02894 02895 bt_size = backtrace (bt, 500); 02896 02897 syms = backtrace_symbols (bt, bt_size); 02898 02899 i = 0; 02900 while (i < bt_size) 02901 { 02902 /* don't use dbus_warn since it can _dbus_abort() */ 02903 fprintf (stderr, " %s\n", syms[i]); 02904 ++i; 02905 } 02906 fflush (stderr); 02907 02908 free (syms); 02909 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02910 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02911 #else 02912 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02913 #endif 02914 } 02915 02928 dbus_bool_t 02929 _dbus_full_duplex_pipe (int *fd1, 02930 int *fd2, 02931 dbus_bool_t blocking, 02932 DBusError *error) 02933 { 02934 #ifdef HAVE_SOCKETPAIR 02935 int fds[2]; 02936 int retval; 02937 02938 #ifdef SOCK_CLOEXEC 02939 dbus_bool_t cloexec_done; 02940 02941 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 02942 cloexec_done = retval >= 0; 02943 02944 if (retval < 0 && errno == EINVAL) 02945 #endif 02946 { 02947 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 02948 } 02949 02950 if (retval < 0) 02951 { 02952 dbus_set_error (error, _dbus_error_from_errno (errno), 02953 "Could not create full-duplex pipe"); 02954 return FALSE; 02955 } 02956 02957 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02958 02959 #ifdef SOCK_CLOEXEC 02960 if (!cloexec_done) 02961 #endif 02962 { 02963 _dbus_fd_set_close_on_exec (fds[0]); 02964 _dbus_fd_set_close_on_exec (fds[1]); 02965 } 02966 02967 if (!blocking && 02968 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02969 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02970 { 02971 dbus_set_error (error, _dbus_error_from_errno (errno), 02972 "Could not set full-duplex pipe nonblocking"); 02973 02974 _dbus_close (fds[0], NULL); 02975 _dbus_close (fds[1], NULL); 02976 02977 return FALSE; 02978 } 02979 02980 *fd1 = fds[0]; 02981 *fd2 = fds[1]; 02982 02983 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 02984 *fd1, *fd2); 02985 02986 return TRUE; 02987 #else 02988 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 02989 dbus_set_error (error, DBUS_ERROR_FAILED, 02990 "_dbus_full_duplex_pipe() not implemented on this OS"); 02991 return FALSE; 02992 #endif 02993 } 02994 03003 int 03004 _dbus_printf_string_upper_bound (const char *format, 03005 va_list args) 03006 { 03007 char static_buf[1024]; 03008 int bufsize = sizeof (static_buf); 03009 int len; 03010 03011 len = vsnprintf (static_buf, bufsize, format, args); 03012 03013 /* If vsnprintf() returned non-negative, then either the string fits in 03014 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03015 * returns the number of characters that were needed, or this OS returns the 03016 * truncated length. 03017 * 03018 * We ignore the possibility that snprintf might just ignore the length and 03019 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03020 * If your libc is really that bad, come back when you have a better one. */ 03021 if (len == bufsize) 03022 { 03023 /* This could be the truncated length (Tru64 and IRIX have this bug), 03024 * or the real length could be coincidentally the same. Which is it? 03025 * If vsnprintf returns the truncated length, we'll go to the slow 03026 * path. */ 03027 if (vsnprintf (static_buf, 1, format, args) == 1) 03028 len = -1; 03029 } 03030 03031 /* If vsnprintf() returned negative, we have to do more work. 03032 * HP-UX returns negative. */ 03033 while (len < 0) 03034 { 03035 char *buf; 03036 03037 bufsize *= 2; 03038 03039 buf = dbus_malloc (bufsize); 03040 03041 if (buf == NULL) 03042 return -1; 03043 03044 len = vsnprintf (buf, bufsize, format, args); 03045 dbus_free (buf); 03046 03047 /* If the reported length is exactly the buffer size, round up to the 03048 * next size, in case vsnprintf has been returning the truncated 03049 * length */ 03050 if (len == bufsize) 03051 len = -1; 03052 } 03053 03054 return len; 03055 } 03056 03063 const char* 03064 _dbus_get_tmpdir(void) 03065 { 03066 static const char* tmpdir = NULL; 03067 03068 if (tmpdir == NULL) 03069 { 03070 /* TMPDIR is what glibc uses, then 03071 * glibc falls back to the P_tmpdir macro which 03072 * just expands to "/tmp" 03073 */ 03074 if (tmpdir == NULL) 03075 tmpdir = getenv("TMPDIR"); 03076 03077 /* These two env variables are probably 03078 * broken, but maybe some OS uses them? 03079 */ 03080 if (tmpdir == NULL) 03081 tmpdir = getenv("TMP"); 03082 if (tmpdir == NULL) 03083 tmpdir = getenv("TEMP"); 03084 03085 /* And this is the sane fallback. */ 03086 if (tmpdir == NULL) 03087 tmpdir = "/tmp"; 03088 } 03089 03090 _dbus_assert(tmpdir != NULL); 03091 03092 return tmpdir; 03093 } 03094 03114 static dbus_bool_t 03115 _read_subprocess_line_argv (const char *progpath, 03116 dbus_bool_t path_fallback, 03117 char * const *argv, 03118 DBusString *result, 03119 DBusError *error) 03120 { 03121 int result_pipe[2] = { -1, -1 }; 03122 int errors_pipe[2] = { -1, -1 }; 03123 pid_t pid; 03124 int ret; 03125 int status; 03126 int orig_len; 03127 int i; 03128 03129 dbus_bool_t retval; 03130 sigset_t new_set, old_set; 03131 03132 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03133 retval = FALSE; 03134 03135 /* We need to block any existing handlers for SIGCHLD temporarily; they 03136 * will cause waitpid() below to fail. 03137 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03138 */ 03139 sigemptyset (&new_set); 03140 sigaddset (&new_set, SIGCHLD); 03141 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03142 03143 orig_len = _dbus_string_get_length (result); 03144 03145 #define READ_END 0 03146 #define WRITE_END 1 03147 if (pipe (result_pipe) < 0) 03148 { 03149 dbus_set_error (error, _dbus_error_from_errno (errno), 03150 "Failed to create a pipe to call %s: %s", 03151 progpath, _dbus_strerror (errno)); 03152 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03153 progpath, _dbus_strerror (errno)); 03154 goto out; 03155 } 03156 if (pipe (errors_pipe) < 0) 03157 { 03158 dbus_set_error (error, _dbus_error_from_errno (errno), 03159 "Failed to create a pipe to call %s: %s", 03160 progpath, _dbus_strerror (errno)); 03161 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03162 progpath, _dbus_strerror (errno)); 03163 goto out; 03164 } 03165 03166 pid = fork (); 03167 if (pid < 0) 03168 { 03169 dbus_set_error (error, _dbus_error_from_errno (errno), 03170 "Failed to fork() to call %s: %s", 03171 progpath, _dbus_strerror (errno)); 03172 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03173 progpath, _dbus_strerror (errno)); 03174 goto out; 03175 } 03176 03177 if (pid == 0) 03178 { 03179 /* child process */ 03180 int maxfds; 03181 int fd; 03182 03183 fd = open ("/dev/null", O_RDWR); 03184 if (fd == -1) 03185 /* huh?! can't open /dev/null? */ 03186 _exit (1); 03187 03188 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03189 03190 /* set-up stdXXX */ 03191 close (result_pipe[READ_END]); 03192 close (errors_pipe[READ_END]); 03193 close (0); /* close stdin */ 03194 close (1); /* close stdout */ 03195 close (2); /* close stderr */ 03196 03197 if (dup2 (fd, 0) == -1) 03198 _exit (1); 03199 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03200 _exit (1); 03201 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03202 _exit (1); 03203 03204 maxfds = sysconf (_SC_OPEN_MAX); 03205 /* Pick something reasonable if for some reason sysconf 03206 * says unlimited. 03207 */ 03208 if (maxfds < 0) 03209 maxfds = 1024; 03210 /* close all inherited fds */ 03211 for (i = 3; i < maxfds; i++) 03212 close (i); 03213 03214 sigprocmask (SIG_SETMASK, &old_set, NULL); 03215 03216 /* If it looks fully-qualified, try execv first */ 03217 if (progpath[0] == '/') 03218 { 03219 execv (progpath, argv); 03220 /* Ok, that failed. Now if path_fallback is given, let's 03221 * try unqualified. This is mostly a hack to work 03222 * around systems which ship dbus-launch in /usr/bin 03223 * but everything else in /bin (because dbus-launch 03224 * depends on X11). 03225 */ 03226 if (path_fallback) 03227 /* We must have a slash, because we checked above */ 03228 execvp (strrchr (progpath, '/')+1, argv); 03229 } 03230 else 03231 execvp (progpath, argv); 03232 03233 /* still nothing, we failed */ 03234 _exit (1); 03235 } 03236 03237 /* parent process */ 03238 close (result_pipe[WRITE_END]); 03239 close (errors_pipe[WRITE_END]); 03240 result_pipe[WRITE_END] = -1; 03241 errors_pipe[WRITE_END] = -1; 03242 03243 ret = 0; 03244 do 03245 { 03246 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03247 } 03248 while (ret > 0); 03249 03250 /* reap the child process to avoid it lingering as zombie */ 03251 do 03252 { 03253 ret = waitpid (pid, &status, 0); 03254 } 03255 while (ret == -1 && errno == EINTR); 03256 03257 /* We succeeded if the process exited with status 0 and 03258 anything was read */ 03259 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03260 { 03261 /* The process ended with error */ 03262 DBusString error_message; 03263 if (!_dbus_string_init (&error_message)) 03264 { 03265 _DBUS_SET_OOM (error); 03266 goto out; 03267 } 03268 03269 ret = 0; 03270 do 03271 { 03272 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03273 } 03274 while (ret > 0); 03275 03276 _dbus_string_set_length (result, orig_len); 03277 if (_dbus_string_get_length (&error_message) > 0) 03278 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03279 "%s terminated abnormally with the following error: %s", 03280 progpath, _dbus_string_get_data (&error_message)); 03281 else 03282 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03283 "%s terminated abnormally without any error message", 03284 progpath); 03285 goto out; 03286 } 03287 03288 retval = TRUE; 03289 03290 out: 03291 sigprocmask (SIG_SETMASK, &old_set, NULL); 03292 03293 if (retval) 03294 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03295 else 03296 _DBUS_ASSERT_ERROR_IS_SET (error); 03297 03298 if (result_pipe[0] != -1) 03299 close (result_pipe[0]); 03300 if (result_pipe[1] != -1) 03301 close (result_pipe[1]); 03302 if (errors_pipe[0] != -1) 03303 close (errors_pipe[0]); 03304 if (errors_pipe[1] != -1) 03305 close (errors_pipe[1]); 03306 03307 return retval; 03308 } 03309 03321 dbus_bool_t 03322 _dbus_get_autolaunch_address (const char *scope, 03323 DBusString *address, 03324 DBusError *error) 03325 { 03326 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03327 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03328 * but that's done elsewhere, and if it worked, this function wouldn't 03329 * be called.) */ 03330 const char *display; 03331 static char *argv[6]; 03332 int i; 03333 DBusString uuid; 03334 dbus_bool_t retval; 03335 03336 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03337 retval = FALSE; 03338 03339 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03340 * dbus-launch-x11 is just going to fail. Rather than trying to 03341 * run it, we might as well bail out early with a nice error. */ 03342 display = _dbus_getenv ("DISPLAY"); 03343 03344 if (display == NULL || display[0] == '\0') 03345 { 03346 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03347 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03348 return FALSE; 03349 } 03350 03351 if (!_dbus_string_init (&uuid)) 03352 { 03353 _DBUS_SET_OOM (error); 03354 return FALSE; 03355 } 03356 03357 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03358 { 03359 _DBUS_SET_OOM (error); 03360 goto out; 03361 } 03362 03363 i = 0; 03364 argv[i] = "dbus-launch"; 03365 ++i; 03366 argv[i] = "--autolaunch"; 03367 ++i; 03368 argv[i] = _dbus_string_get_data (&uuid); 03369 ++i; 03370 argv[i] = "--binary-syntax"; 03371 ++i; 03372 argv[i] = "--close-stderr"; 03373 ++i; 03374 argv[i] = NULL; 03375 ++i; 03376 03377 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03378 03379 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03380 TRUE, 03381 argv, address, error); 03382 03383 out: 03384 _dbus_string_free (&uuid); 03385 return retval; 03386 #else 03387 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03388 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03389 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03390 return FALSE; 03391 #endif 03392 } 03393 03412 dbus_bool_t 03413 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03414 dbus_bool_t create_if_not_found, 03415 DBusError *error) 03416 { 03417 DBusString filename; 03418 dbus_bool_t b; 03419 03420 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03421 03422 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03423 if (b) 03424 return TRUE; 03425 03426 dbus_error_free (error); 03427 03428 /* Fallback to the system machine ID */ 03429 _dbus_string_init_const (&filename, "/etc/machine-id"); 03430 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03431 } 03432 03433 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03434 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03435 03442 dbus_bool_t 03443 _dbus_lookup_launchd_socket (DBusString *socket_path, 03444 const char *launchd_env_var, 03445 DBusError *error) 03446 { 03447 #ifdef DBUS_ENABLE_LAUNCHD 03448 char *argv[4]; 03449 int i; 03450 03451 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03452 03453 i = 0; 03454 argv[i] = "launchctl"; 03455 ++i; 03456 argv[i] = "getenv"; 03457 ++i; 03458 argv[i] = (char*)launchd_env_var; 03459 ++i; 03460 argv[i] = NULL; 03461 ++i; 03462 03463 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03464 03465 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03466 { 03467 return FALSE; 03468 } 03469 03470 /* no error, but no result either */ 03471 if (_dbus_string_get_length(socket_path) == 0) 03472 { 03473 return FALSE; 03474 } 03475 03476 /* strip the carriage-return */ 03477 _dbus_string_shorten(socket_path, 1); 03478 return TRUE; 03479 #else /* DBUS_ENABLE_LAUNCHD */ 03480 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03481 "can't lookup socket from launchd; launchd support not compiled in"); 03482 return FALSE; 03483 #endif 03484 } 03485 03486 #ifdef DBUS_ENABLE_LAUNCHD 03487 static dbus_bool_t 03488 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03489 { 03490 dbus_bool_t valid_socket; 03491 DBusString socket_path; 03492 03493 if (!_dbus_string_init (&socket_path)) 03494 { 03495 _DBUS_SET_OOM (error); 03496 return FALSE; 03497 } 03498 03499 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03500 03501 if (dbus_error_is_set(error)) 03502 { 03503 _dbus_string_free(&socket_path); 03504 return FALSE; 03505 } 03506 03507 if (!valid_socket) 03508 { 03509 dbus_set_error(error, "no socket path", 03510 "launchd did not provide a socket path, " 03511 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03512 _dbus_string_free(&socket_path); 03513 return FALSE; 03514 } 03515 if (!_dbus_string_append (address, "unix:path=")) 03516 { 03517 _DBUS_SET_OOM (error); 03518 _dbus_string_free(&socket_path); 03519 return FALSE; 03520 } 03521 if (!_dbus_string_copy (&socket_path, 0, address, 03522 _dbus_string_get_length (address))) 03523 { 03524 _DBUS_SET_OOM (error); 03525 _dbus_string_free(&socket_path); 03526 return FALSE; 03527 } 03528 03529 _dbus_string_free(&socket_path); 03530 return TRUE; 03531 } 03532 #endif 03533 03553 dbus_bool_t 03554 _dbus_lookup_session_address (dbus_bool_t *supported, 03555 DBusString *address, 03556 DBusError *error) 03557 { 03558 #ifdef DBUS_ENABLE_LAUNCHD 03559 *supported = TRUE; 03560 return _dbus_lookup_session_address_launchd (address, error); 03561 #else 03562 /* On non-Mac Unix platforms, if the session address isn't already 03563 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03564 * fall back to the autolaunch: global default; see 03565 * init_session_address in dbus/dbus-bus.c. */ 03566 *supported = FALSE; 03567 return TRUE; 03568 #endif 03569 } 03570 03588 dbus_bool_t 03589 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03590 { 03591 const char *xdg_data_home; 03592 const char *xdg_data_dirs; 03593 DBusString servicedir_path; 03594 03595 if (!_dbus_string_init (&servicedir_path)) 03596 return FALSE; 03597 03598 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03599 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03600 03601 if (xdg_data_home != NULL) 03602 { 03603 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03604 goto oom; 03605 } 03606 else 03607 { 03608 const DBusString *homedir; 03609 DBusString local_share; 03610 03611 if (!_dbus_homedir_from_current_process (&homedir)) 03612 goto oom; 03613 03614 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03615 goto oom; 03616 03617 _dbus_string_init_const (&local_share, "/.local/share"); 03618 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03619 goto oom; 03620 } 03621 03622 if (!_dbus_string_append (&servicedir_path, ":")) 03623 goto oom; 03624 03625 if (xdg_data_dirs != NULL) 03626 { 03627 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03628 goto oom; 03629 03630 if (!_dbus_string_append (&servicedir_path, ":")) 03631 goto oom; 03632 } 03633 else 03634 { 03635 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03636 goto oom; 03637 } 03638 03639 /* 03640 * add configured datadir to defaults 03641 * this may be the same as an xdg dir 03642 * however the config parser should take 03643 * care of duplicates 03644 */ 03645 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03646 goto oom; 03647 03648 if (!_dbus_split_paths_and_append (&servicedir_path, 03649 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03650 dirs)) 03651 goto oom; 03652 03653 _dbus_string_free (&servicedir_path); 03654 return TRUE; 03655 03656 oom: 03657 _dbus_string_free (&servicedir_path); 03658 return FALSE; 03659 } 03660 03661 03680 dbus_bool_t 03681 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03682 { 03683 /* 03684 * DBUS_DATADIR may be the same as one of the standard directories. However, 03685 * the config parser should take care of the duplicates. 03686 * 03687 * Also, append /lib as counterpart of /usr/share on the root 03688 * directory (the root directory does not know /share), in order to 03689 * facilitate early boot system bus activation where /usr might not 03690 * be available. 03691 */ 03692 static const char standard_search_path[] = 03693 "/usr/local/share:" 03694 "/usr/share:" 03695 DBUS_DATADIR ":" 03696 "/lib"; 03697 DBusString servicedir_path; 03698 03699 _dbus_string_init_const (&servicedir_path, standard_search_path); 03700 03701 return _dbus_split_paths_and_append (&servicedir_path, 03702 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03703 dirs); 03704 } 03705 03714 dbus_bool_t 03715 _dbus_append_system_config_file (DBusString *str) 03716 { 03717 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03718 } 03719 03726 dbus_bool_t 03727 _dbus_append_session_config_file (DBusString *str) 03728 { 03729 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03730 } 03731 03739 void 03740 _dbus_flush_caches (void) 03741 { 03742 _dbus_user_database_flush_system (); 03743 } 03744 03758 dbus_bool_t 03759 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03760 DBusCredentials *credentials) 03761 { 03762 DBusString homedir; 03763 DBusString dotdir; 03764 dbus_uid_t uid; 03765 03766 _dbus_assert (credentials != NULL); 03767 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03768 03769 if (!_dbus_string_init (&homedir)) 03770 return FALSE; 03771 03772 uid = _dbus_credentials_get_unix_uid (credentials); 03773 _dbus_assert (uid != DBUS_UID_UNSET); 03774 03775 if (!_dbus_homedir_from_uid (uid, &homedir)) 03776 goto failed; 03777 03778 #ifdef DBUS_BUILD_TESTS 03779 { 03780 const char *override; 03781 03782 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03783 if (override != NULL && *override != '\0') 03784 { 03785 _dbus_string_set_length (&homedir, 0); 03786 if (!_dbus_string_append (&homedir, override)) 03787 goto failed; 03788 03789 _dbus_verbose ("Using fake homedir for testing: %s\n", 03790 _dbus_string_get_const_data (&homedir)); 03791 } 03792 else 03793 { 03794 static dbus_bool_t already_warned = FALSE; 03795 if (!already_warned) 03796 { 03797 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03798 already_warned = TRUE; 03799 } 03800 } 03801 } 03802 #endif 03803 03804 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03805 if (!_dbus_concat_dir_and_file (&homedir, 03806 &dotdir)) 03807 goto failed; 03808 03809 if (!_dbus_string_copy (&homedir, 0, 03810 directory, _dbus_string_get_length (directory))) { 03811 goto failed; 03812 } 03813 03814 _dbus_string_free (&homedir); 03815 return TRUE; 03816 03817 failed: 03818 _dbus_string_free (&homedir); 03819 return FALSE; 03820 } 03821 03822 //PENDING(kdab) docs 03823 dbus_bool_t 03824 _dbus_daemon_publish_session_bus_address (const char* addr, 03825 const char *scope) 03826 { 03827 return TRUE; 03828 } 03829 03830 //PENDING(kdab) docs 03831 void 03832 _dbus_daemon_unpublish_session_bus_address (void) 03833 { 03834 03835 } 03836 03843 dbus_bool_t 03844 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03845 { 03846 return errno == EAGAIN || errno == EWOULDBLOCK; 03847 } 03848 03856 dbus_bool_t 03857 _dbus_delete_directory (const DBusString *filename, 03858 DBusError *error) 03859 { 03860 const char *filename_c; 03861 03862 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03863 03864 filename_c = _dbus_string_get_const_data (filename); 03865 03866 if (rmdir (filename_c) != 0) 03867 { 03868 dbus_set_error (error, DBUS_ERROR_FAILED, 03869 "Failed to remove directory %s: %s\n", 03870 filename_c, _dbus_strerror (errno)); 03871 return FALSE; 03872 } 03873 03874 return TRUE; 03875 } 03876 03884 dbus_bool_t 03885 _dbus_socket_can_pass_unix_fd(int fd) { 03886 03887 #ifdef SCM_RIGHTS 03888 union { 03889 struct sockaddr sa; 03890 struct sockaddr_storage storage; 03891 struct sockaddr_un un; 03892 } sa_buf; 03893 03894 socklen_t sa_len = sizeof(sa_buf); 03895 03896 _DBUS_ZERO(sa_buf); 03897 03898 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03899 return FALSE; 03900 03901 return sa_buf.sa.sa_family == AF_UNIX; 03902 03903 #else 03904 return FALSE; 03905 03906 #endif 03907 } 03908 03909 03910 /* 03911 * replaces the term DBUS_PREFIX in configure_time_path by the 03912 * current dbus installation directory. On unix this function is a noop 03913 * 03914 * @param configure_time_path 03915 * @return real path 03916 */ 03917 const char * 03918 _dbus_replace_install_prefix (const char *configure_time_path) 03919 { 03920 return configure_time_path; 03921 } 03922 03923 /* tests in dbus-sysdeps-util.c */
1.7.6.1