D-Bus
1.10.12
|
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-file.h" 00033 #include "dbus-transport.h" 00034 #include "dbus-string.h" 00035 #include "dbus-userdb.h" 00036 #include "dbus-list.h" 00037 #include "dbus-credentials.h" 00038 #include "dbus-nonce.h" 00039 00040 #include <sys/types.h> 00041 #include <stdlib.h> 00042 #include <string.h> 00043 #include <signal.h> 00044 #include <unistd.h> 00045 #include <stdio.h> 00046 #include <fcntl.h> 00047 #include <sys/socket.h> 00048 #include <dirent.h> 00049 #include <sys/un.h> 00050 #include <pwd.h> 00051 #include <time.h> 00052 #include <locale.h> 00053 #include <sys/time.h> 00054 #include <sys/stat.h> 00055 #include <sys/wait.h> 00056 #include <netinet/in.h> 00057 #include <netinet/tcp.h> 00058 #include <netdb.h> 00059 #include <grp.h> 00060 #include <arpa/inet.h> 00061 00062 #ifdef HAVE_ERRNO_H 00063 #include <errno.h> 00064 #endif 00065 #ifdef HAVE_WRITEV 00066 #include <sys/uio.h> 00067 #endif 00068 #ifdef HAVE_POLL 00069 #include <sys/poll.h> 00070 #endif 00071 #ifdef HAVE_BACKTRACE 00072 #include <execinfo.h> 00073 #endif 00074 #ifdef HAVE_GETPEERUCRED 00075 #include <ucred.h> 00076 #endif 00077 #ifdef HAVE_ALLOCA_H 00078 #include <alloca.h> 00079 #endif 00080 00081 #ifdef HAVE_ADT 00082 #include <bsm/adt.h> 00083 #endif 00084 00085 #ifdef HAVE_SYSTEMD 00086 #include <systemd/sd-daemon.h> 00087 #endif 00088 00089 #if !DBUS_USE_SYNC 00090 #include <pthread.h> 00091 #endif 00092 00093 #ifndef O_BINARY 00094 #define O_BINARY 0 00095 #endif 00096 00097 #ifndef AI_ADDRCONFIG 00098 #define AI_ADDRCONFIG 0 00099 #endif 00100 00101 #ifndef HAVE_SOCKLEN_T 00102 #define socklen_t int 00103 #endif 00104 00105 #if defined (__sun) || defined (__sun__) 00106 /* 00107 * CMS_SPACE etc. definitions for Solaris < 10, based on 00108 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html 00109 * via 00110 * http://wiki.opencsw.org/porting-faq#toc10 00111 * 00112 * These are only redefined for Solaris, for now: if your OS needs these too, 00113 * please file a bug. (Or preferably, improve your OS so they're not needed.) 00114 */ 00115 00116 # ifndef CMSG_ALIGN 00117 # ifdef __sun__ 00118 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len) 00119 # else 00120 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */ 00121 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \ 00122 ~(sizeof (long) - 1)) 00123 # endif 00124 # endif 00125 00126 # ifndef CMSG_SPACE 00127 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \ 00128 CMSG_ALIGN (len)) 00129 # endif 00130 00131 # ifndef CMSG_LEN 00132 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) 00133 # endif 00134 00135 #endif /* Solaris */ 00136 00151 dbus_bool_t 00152 _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags, 00153 const char **error_str_p) 00154 { 00155 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL, 00156 DBUS_FORCE_STDOUT_NULL, 00157 DBUS_FORCE_STDERR_NULL }; 00158 /* Should always get replaced with the real error before use */ 00159 const char *error_str = "Failed mysteriously"; 00160 int devnull = -1; 00161 int saved_errno; 00162 /* This function relies on the standard fds having their POSIX values. */ 00163 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0); 00164 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1); 00165 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2); 00166 int i; 00167 00168 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) 00169 { 00170 /* Because we rely on being single-threaded, and we want the 00171 * standard fds to not be close-on-exec, we don't set it 00172 * close-on-exec. */ 00173 if (devnull < i) 00174 devnull = open ("/dev/null", O_RDWR); 00175 00176 if (devnull < 0) 00177 { 00178 error_str = "Failed to open /dev/null"; 00179 goto out; 00180 } 00181 00182 /* We already opened all fds < i, so the only way this assertion 00183 * could fail is if another thread closed one, and we document 00184 * this function as not safe for multi-threading. */ 00185 _dbus_assert (devnull >= i); 00186 00187 if (devnull != i && (flags & relevant_flag[i]) != 0) 00188 { 00189 if (dup2 (devnull, i) < 0) 00190 { 00191 error_str = "Failed to dup2 /dev/null onto a standard fd"; 00192 goto out; 00193 } 00194 } 00195 } 00196 00197 error_str = NULL; 00198 00199 out: 00200 saved_errno = errno; 00201 00202 if (devnull > STDERR_FILENO) 00203 close (devnull); 00204 00205 if (error_str_p != NULL) 00206 *error_str_p = error_str; 00207 00208 errno = saved_errno; 00209 return (error_str == NULL); 00210 } 00211 00212 static dbus_bool_t _dbus_set_fd_nonblocking (int fd, 00213 DBusError *error); 00214 00215 static dbus_bool_t 00216 _dbus_open_socket (int *fd_p, 00217 int domain, 00218 int type, 00219 int protocol, 00220 DBusError *error) 00221 { 00222 #ifdef SOCK_CLOEXEC 00223 dbus_bool_t cloexec_done; 00224 00225 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol); 00226 cloexec_done = *fd_p >= 0; 00227 00228 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */ 00229 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE)) 00230 #endif 00231 { 00232 *fd_p = socket (domain, type, protocol); 00233 } 00234 00235 if (*fd_p >= 0) 00236 { 00237 #ifdef SOCK_CLOEXEC 00238 if (!cloexec_done) 00239 #endif 00240 { 00241 _dbus_fd_set_close_on_exec(*fd_p); 00242 } 00243 00244 _dbus_verbose ("socket fd %d opened\n", *fd_p); 00245 return TRUE; 00246 } 00247 else 00248 { 00249 dbus_set_error(error, 00250 _dbus_error_from_errno (errno), 00251 "Failed to open socket: %s", 00252 _dbus_strerror (errno)); 00253 return FALSE; 00254 } 00255 } 00256 00267 static dbus_bool_t 00268 _dbus_open_unix_socket (int *fd, 00269 DBusError *error) 00270 { 00271 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error); 00272 } 00273 00282 dbus_bool_t 00283 _dbus_close_socket (DBusSocket fd, 00284 DBusError *error) 00285 { 00286 return _dbus_close (fd.fd, error); 00287 } 00288 00298 int 00299 _dbus_read_socket (DBusSocket fd, 00300 DBusString *buffer, 00301 int count) 00302 { 00303 return _dbus_read (fd.fd, buffer, count); 00304 } 00305 00316 int 00317 _dbus_write_socket (DBusSocket fd, 00318 const DBusString *buffer, 00319 int start, 00320 int len) 00321 { 00322 #if HAVE_DECL_MSG_NOSIGNAL 00323 const char *data; 00324 int bytes_written; 00325 00326 data = _dbus_string_get_const_data_len (buffer, start, len); 00327 00328 again: 00329 00330 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL); 00331 00332 if (bytes_written < 0 && errno == EINTR) 00333 goto again; 00334 00335 return bytes_written; 00336 00337 #else 00338 return _dbus_write (fd.fd, buffer, start, len); 00339 #endif 00340 } 00341 00354 int 00355 _dbus_read_socket_with_unix_fds (DBusSocket fd, 00356 DBusString *buffer, 00357 int count, 00358 int *fds, 00359 int *n_fds) { 00360 #ifndef HAVE_UNIX_FD_PASSING 00361 int r; 00362 00363 if ((r = _dbus_read_socket(fd, buffer, count)) < 0) 00364 return r; 00365 00366 *n_fds = 0; 00367 return r; 00368 00369 #else 00370 int bytes_read; 00371 int start; 00372 struct msghdr m; 00373 struct iovec iov; 00374 00375 _dbus_assert (count >= 0); 00376 _dbus_assert (*n_fds >= 0); 00377 00378 start = _dbus_string_get_length (buffer); 00379 00380 if (!_dbus_string_lengthen (buffer, count)) 00381 { 00382 errno = ENOMEM; 00383 return -1; 00384 } 00385 00386 _DBUS_ZERO(iov); 00387 iov.iov_base = _dbus_string_get_data_len (buffer, start, count); 00388 iov.iov_len = count; 00389 00390 _DBUS_ZERO(m); 00391 m.msg_iov = &iov; 00392 m.msg_iovlen = 1; 00393 00394 /* Hmm, we have no clue how long the control data will actually be 00395 that is queued for us. The least we can do is assume that the 00396 caller knows. Hence let's make space for the number of fds that 00397 we shall read at max plus the cmsg header. */ 00398 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int)); 00399 00400 /* It's probably safe to assume that systems with SCM_RIGHTS also 00401 know alloca() */ 00402 m.msg_control = alloca(m.msg_controllen); 00403 memset(m.msg_control, 0, m.msg_controllen); 00404 00405 /* Do not include the padding at the end when we tell the kernel 00406 * how much we're willing to receive. This avoids getting 00407 * the padding filled with additional fds that we weren't expecting, 00408 * if a (potentially malicious) sender included them. (fd.o #83622) */ 00409 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int)); 00410 00411 again: 00412 00413 bytes_read = recvmsg (fd.fd, &m, 0 00414 #ifdef MSG_CMSG_CLOEXEC 00415 |MSG_CMSG_CLOEXEC 00416 #endif 00417 ); 00418 00419 if (bytes_read < 0) 00420 { 00421 if (errno == EINTR) 00422 goto again; 00423 else 00424 { 00425 /* put length back (note that this doesn't actually realloc anything) */ 00426 _dbus_string_set_length (buffer, start); 00427 return -1; 00428 } 00429 } 00430 else 00431 { 00432 struct cmsghdr *cm; 00433 dbus_bool_t found = FALSE; 00434 00435 if (m.msg_flags & MSG_CTRUNC) 00436 { 00437 /* Hmm, apparently the control data was truncated. The bad 00438 thing is that we might have completely lost a couple of fds 00439 without chance to recover them. Hence let's treat this as a 00440 serious error. */ 00441 00442 errno = ENOSPC; 00443 _dbus_string_set_length (buffer, start); 00444 return -1; 00445 } 00446 00447 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) 00448 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) 00449 { 00450 size_t i; 00451 int *payload = (int *) CMSG_DATA (cm); 00452 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0)); 00453 size_t payload_len_fds = payload_len_bytes / sizeof (int); 00454 size_t fds_to_use; 00455 00456 /* Every non-negative int fits in a size_t without truncation, 00457 * and we already know that *n_fds is non-negative, so 00458 * casting (size_t) *n_fds is OK */ 00459 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int)); 00460 00461 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds)) 00462 { 00463 /* The fds in the payload will fit in our buffer */ 00464 fds_to_use = payload_len_fds; 00465 } 00466 else 00467 { 00468 /* Too many fds in the payload. This shouldn't happen 00469 * any more because we're setting m.msg_controllen to 00470 * the exact number we can accept, but be safe and 00471 * truncate. */ 00472 fds_to_use = (size_t) *n_fds; 00473 00474 /* Close the excess fds to avoid DoS: if they stayed open, 00475 * someone could send us an extra fd per message 00476 * and we'd eventually run out. */ 00477 for (i = fds_to_use; i < payload_len_fds; i++) 00478 { 00479 close (payload[i]); 00480 } 00481 } 00482 00483 memcpy (fds, payload, fds_to_use * sizeof (int)); 00484 found = TRUE; 00485 /* This cannot overflow because we have chosen fds_to_use 00486 * to be <= *n_fds */ 00487 *n_fds = (int) fds_to_use; 00488 00489 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually 00490 worked, hence we need to go through this list and set 00491 CLOEXEC everywhere in any case */ 00492 for (i = 0; i < fds_to_use; i++) 00493 _dbus_fd_set_close_on_exec(fds[i]); 00494 00495 break; 00496 } 00497 00498 if (!found) 00499 *n_fds = 0; 00500 00501 /* put length back (doesn't actually realloc) */ 00502 _dbus_string_set_length (buffer, start + bytes_read); 00503 00504 #if 0 00505 if (bytes_read > 0) 00506 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00507 #endif 00508 00509 return bytes_read; 00510 } 00511 #endif 00512 } 00513 00514 int 00515 _dbus_write_socket_with_unix_fds(DBusSocket fd, 00516 const DBusString *buffer, 00517 int start, 00518 int len, 00519 const int *fds, 00520 int n_fds) { 00521 00522 #ifndef HAVE_UNIX_FD_PASSING 00523 00524 if (n_fds > 0) { 00525 errno = ENOTSUP; 00526 return -1; 00527 } 00528 00529 return _dbus_write_socket(fd, buffer, start, len); 00530 #else 00531 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds); 00532 #endif 00533 } 00534 00535 int 00536 _dbus_write_socket_with_unix_fds_two(DBusSocket fd, 00537 const DBusString *buffer1, 00538 int start1, 00539 int len1, 00540 const DBusString *buffer2, 00541 int start2, 00542 int len2, 00543 const int *fds, 00544 int n_fds) { 00545 00546 #ifndef HAVE_UNIX_FD_PASSING 00547 00548 if (n_fds > 0) { 00549 errno = ENOTSUP; 00550 return -1; 00551 } 00552 00553 return _dbus_write_socket_two(fd, 00554 buffer1, start1, len1, 00555 buffer2, start2, len2); 00556 #else 00557 00558 struct msghdr m; 00559 struct cmsghdr *cm; 00560 struct iovec iov[2]; 00561 int bytes_written; 00562 00563 _dbus_assert (len1 >= 0); 00564 _dbus_assert (len2 >= 0); 00565 _dbus_assert (n_fds >= 0); 00566 00567 _DBUS_ZERO(iov); 00568 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1); 00569 iov[0].iov_len = len1; 00570 00571 if (buffer2) 00572 { 00573 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2); 00574 iov[1].iov_len = len2; 00575 } 00576 00577 _DBUS_ZERO(m); 00578 m.msg_iov = iov; 00579 m.msg_iovlen = buffer2 ? 2 : 1; 00580 00581 if (n_fds > 0) 00582 { 00583 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int)); 00584 m.msg_control = alloca(m.msg_controllen); 00585 memset(m.msg_control, 0, m.msg_controllen); 00586 00587 cm = CMSG_FIRSTHDR(&m); 00588 cm->cmsg_level = SOL_SOCKET; 00589 cm->cmsg_type = SCM_RIGHTS; 00590 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int)); 00591 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int)); 00592 } 00593 00594 again: 00595 00596 bytes_written = sendmsg (fd.fd, &m, 0 00597 #if HAVE_DECL_MSG_NOSIGNAL 00598 |MSG_NOSIGNAL 00599 #endif 00600 ); 00601 00602 if (bytes_written < 0 && errno == EINTR) 00603 goto again; 00604 00605 #if 0 00606 if (bytes_written > 0) 00607 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00608 #endif 00609 00610 return bytes_written; 00611 #endif 00612 } 00613 00627 int 00628 _dbus_write_socket_two (DBusSocket fd, 00629 const DBusString *buffer1, 00630 int start1, 00631 int len1, 00632 const DBusString *buffer2, 00633 int start2, 00634 int len2) 00635 { 00636 #if HAVE_DECL_MSG_NOSIGNAL 00637 struct iovec vectors[2]; 00638 const char *data1; 00639 const char *data2; 00640 int bytes_written; 00641 struct msghdr m; 00642 00643 _dbus_assert (buffer1 != NULL); 00644 _dbus_assert (start1 >= 0); 00645 _dbus_assert (start2 >= 0); 00646 _dbus_assert (len1 >= 0); 00647 _dbus_assert (len2 >= 0); 00648 00649 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00650 00651 if (buffer2 != NULL) 00652 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00653 else 00654 { 00655 data2 = NULL; 00656 start2 = 0; 00657 len2 = 0; 00658 } 00659 00660 vectors[0].iov_base = (char*) data1; 00661 vectors[0].iov_len = len1; 00662 vectors[1].iov_base = (char*) data2; 00663 vectors[1].iov_len = len2; 00664 00665 _DBUS_ZERO(m); 00666 m.msg_iov = vectors; 00667 m.msg_iovlen = data2 ? 2 : 1; 00668 00669 again: 00670 00671 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL); 00672 00673 if (bytes_written < 0 && errno == EINTR) 00674 goto again; 00675 00676 return bytes_written; 00677 00678 #else 00679 return _dbus_write_two (fd.fd, buffer1, start1, len1, 00680 buffer2, start2, len2); 00681 #endif 00682 } 00683 00700 int 00701 _dbus_read (int fd, 00702 DBusString *buffer, 00703 int count) 00704 { 00705 int bytes_read; 00706 int start; 00707 char *data; 00708 00709 _dbus_assert (count >= 0); 00710 00711 start = _dbus_string_get_length (buffer); 00712 00713 if (!_dbus_string_lengthen (buffer, count)) 00714 { 00715 errno = ENOMEM; 00716 return -1; 00717 } 00718 00719 data = _dbus_string_get_data_len (buffer, start, count); 00720 00721 again: 00722 00723 bytes_read = read (fd, data, count); 00724 00725 if (bytes_read < 0) 00726 { 00727 if (errno == EINTR) 00728 goto again; 00729 else 00730 { 00731 /* put length back (note that this doesn't actually realloc anything) */ 00732 _dbus_string_set_length (buffer, start); 00733 return -1; 00734 } 00735 } 00736 else 00737 { 00738 /* put length back (doesn't actually realloc) */ 00739 _dbus_string_set_length (buffer, start + bytes_read); 00740 00741 #if 0 00742 if (bytes_read > 0) 00743 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00744 #endif 00745 00746 return bytes_read; 00747 } 00748 } 00749 00760 int 00761 _dbus_write (int fd, 00762 const DBusString *buffer, 00763 int start, 00764 int len) 00765 { 00766 const char *data; 00767 int bytes_written; 00768 00769 data = _dbus_string_get_const_data_len (buffer, start, len); 00770 00771 again: 00772 00773 bytes_written = write (fd, data, len); 00774 00775 if (bytes_written < 0 && errno == EINTR) 00776 goto again; 00777 00778 #if 0 00779 if (bytes_written > 0) 00780 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00781 #endif 00782 00783 return bytes_written; 00784 } 00785 00806 int 00807 _dbus_write_two (int fd, 00808 const DBusString *buffer1, 00809 int start1, 00810 int len1, 00811 const DBusString *buffer2, 00812 int start2, 00813 int len2) 00814 { 00815 _dbus_assert (buffer1 != NULL); 00816 _dbus_assert (start1 >= 0); 00817 _dbus_assert (start2 >= 0); 00818 _dbus_assert (len1 >= 0); 00819 _dbus_assert (len2 >= 0); 00820 00821 #ifdef HAVE_WRITEV 00822 { 00823 struct iovec vectors[2]; 00824 const char *data1; 00825 const char *data2; 00826 int bytes_written; 00827 00828 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00829 00830 if (buffer2 != NULL) 00831 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00832 else 00833 { 00834 data2 = NULL; 00835 start2 = 0; 00836 len2 = 0; 00837 } 00838 00839 vectors[0].iov_base = (char*) data1; 00840 vectors[0].iov_len = len1; 00841 vectors[1].iov_base = (char*) data2; 00842 vectors[1].iov_len = len2; 00843 00844 again: 00845 00846 bytes_written = writev (fd, 00847 vectors, 00848 data2 ? 2 : 1); 00849 00850 if (bytes_written < 0 && errno == EINTR) 00851 goto again; 00852 00853 return bytes_written; 00854 } 00855 #else /* HAVE_WRITEV */ 00856 { 00857 int ret1, ret2; 00858 00859 ret1 = _dbus_write (fd, buffer1, start1, len1); 00860 if (ret1 == len1 && buffer2 != NULL) 00861 { 00862 ret2 = _dbus_write (fd, buffer2, start2, len2); 00863 if (ret2 < 0) 00864 ret2 = 0; /* we can't report an error as the first write was OK */ 00865 00866 return ret1 + ret2; 00867 } 00868 else 00869 return ret1; 00870 } 00871 #endif /* !HAVE_WRITEV */ 00872 } 00873 00874 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00875 00905 int 00906 _dbus_connect_unix_socket (const char *path, 00907 dbus_bool_t abstract, 00908 DBusError *error) 00909 { 00910 int fd; 00911 size_t path_len; 00912 struct sockaddr_un addr; 00913 00914 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00915 00916 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00917 path, abstract); 00918 00919 00920 if (!_dbus_open_unix_socket (&fd, error)) 00921 { 00922 _DBUS_ASSERT_ERROR_IS_SET(error); 00923 return -1; 00924 } 00925 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00926 00927 _DBUS_ZERO (addr); 00928 addr.sun_family = AF_UNIX; 00929 path_len = strlen (path); 00930 00931 if (abstract) 00932 { 00933 #ifdef HAVE_ABSTRACT_SOCKETS 00934 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00935 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00936 00937 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00938 { 00939 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00940 "Abstract socket name too long\n"); 00941 _dbus_close (fd, NULL); 00942 return -1; 00943 } 00944 00945 strncpy (&addr.sun_path[1], path, path_len); 00946 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00947 #else /* HAVE_ABSTRACT_SOCKETS */ 00948 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00949 "Operating system does not support abstract socket namespace\n"); 00950 _dbus_close (fd, NULL); 00951 return -1; 00952 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00953 } 00954 else 00955 { 00956 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00957 { 00958 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00959 "Socket name too long\n"); 00960 _dbus_close (fd, NULL); 00961 return -1; 00962 } 00963 00964 strncpy (addr.sun_path, path, path_len); 00965 } 00966 00967 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00968 { 00969 dbus_set_error (error, 00970 _dbus_error_from_errno (errno), 00971 "Failed to connect to socket %s: %s", 00972 path, _dbus_strerror (errno)); 00973 00974 _dbus_close (fd, NULL); 00975 return -1; 00976 } 00977 00978 if (!_dbus_set_fd_nonblocking (fd, error)) 00979 { 00980 _DBUS_ASSERT_ERROR_IS_SET (error); 00981 00982 _dbus_close (fd, NULL); 00983 return -1; 00984 } 00985 00986 return fd; 00987 } 00988 01001 int 01002 _dbus_connect_exec (const char *path, 01003 char *const argv[], 01004 DBusError *error) 01005 { 01006 int fds[2]; 01007 pid_t pid; 01008 int retval; 01009 dbus_bool_t cloexec_done = 0; 01010 01011 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01012 01013 _dbus_verbose ("connecting to process %s\n", path); 01014 01015 #ifdef SOCK_CLOEXEC 01016 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 01017 cloexec_done = (retval >= 0); 01018 01019 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE)) 01020 #endif 01021 { 01022 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds); 01023 } 01024 01025 if (retval < 0) 01026 { 01027 dbus_set_error (error, 01028 _dbus_error_from_errno (errno), 01029 "Failed to create socket pair: %s", 01030 _dbus_strerror (errno)); 01031 return -1; 01032 } 01033 01034 if (!cloexec_done) 01035 { 01036 _dbus_fd_set_close_on_exec (fds[0]); 01037 _dbus_fd_set_close_on_exec (fds[1]); 01038 } 01039 01040 pid = fork (); 01041 if (pid < 0) 01042 { 01043 dbus_set_error (error, 01044 _dbus_error_from_errno (errno), 01045 "Failed to fork() to call %s: %s", 01046 path, _dbus_strerror (errno)); 01047 close (fds[0]); 01048 close (fds[1]); 01049 return -1; 01050 } 01051 01052 if (pid == 0) 01053 { 01054 /* child */ 01055 close (fds[0]); 01056 01057 dup2 (fds[1], STDIN_FILENO); 01058 dup2 (fds[1], STDOUT_FILENO); 01059 01060 if (fds[1] != STDIN_FILENO && 01061 fds[1] != STDOUT_FILENO) 01062 close (fds[1]); 01063 01064 /* Inherit STDERR and the controlling terminal from the 01065 parent */ 01066 01067 _dbus_close_all (); 01068 01069 execvp (path, argv); 01070 01071 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno)); 01072 01073 _exit(1); 01074 } 01075 01076 /* parent */ 01077 close (fds[1]); 01078 01079 if (!_dbus_set_fd_nonblocking (fds[0], error)) 01080 { 01081 _DBUS_ASSERT_ERROR_IS_SET (error); 01082 01083 close (fds[0]); 01084 return -1; 01085 } 01086 01087 return fds[0]; 01088 } 01089 01107 int 01108 _dbus_listen_unix_socket (const char *path, 01109 dbus_bool_t abstract, 01110 DBusError *error) 01111 { 01112 int listen_fd; 01113 struct sockaddr_un addr; 01114 size_t path_len; 01115 01116 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01117 01118 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 01119 path, abstract); 01120 01121 if (!_dbus_open_unix_socket (&listen_fd, error)) 01122 { 01123 _DBUS_ASSERT_ERROR_IS_SET(error); 01124 return -1; 01125 } 01126 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01127 01128 _DBUS_ZERO (addr); 01129 addr.sun_family = AF_UNIX; 01130 path_len = strlen (path); 01131 01132 if (abstract) 01133 { 01134 #ifdef HAVE_ABSTRACT_SOCKETS 01135 /* remember that abstract names aren't nul-terminated so we rely 01136 * on sun_path being filled in with zeroes above. 01137 */ 01138 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 01139 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 01140 01141 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 01142 { 01143 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01144 "Abstract socket name too long\n"); 01145 _dbus_close (listen_fd, NULL); 01146 return -1; 01147 } 01148 01149 strncpy (&addr.sun_path[1], path, path_len); 01150 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 01151 #else /* HAVE_ABSTRACT_SOCKETS */ 01152 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 01153 "Operating system does not support abstract socket namespace\n"); 01154 _dbus_close (listen_fd, NULL); 01155 return -1; 01156 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 01157 } 01158 else 01159 { 01160 /* Discussed security implications of this with Nalin, 01161 * and we couldn't think of where it would kick our ass, but 01162 * it still seems a bit sucky. It also has non-security suckage; 01163 * really we'd prefer to exit if the socket is already in use. 01164 * But there doesn't seem to be a good way to do this. 01165 * 01166 * Just to be extra careful, I threw in the stat() - clearly 01167 * the stat() can't *fix* any security issue, but it at least 01168 * avoids inadvertent/accidental data loss. 01169 */ 01170 { 01171 struct stat sb; 01172 01173 if (stat (path, &sb) == 0 && 01174 S_ISSOCK (sb.st_mode)) 01175 unlink (path); 01176 } 01177 01178 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 01179 { 01180 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01181 "Socket name too long\n"); 01182 _dbus_close (listen_fd, NULL); 01183 return -1; 01184 } 01185 01186 strncpy (addr.sun_path, path, path_len); 01187 } 01188 01189 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 01190 { 01191 dbus_set_error (error, _dbus_error_from_errno (errno), 01192 "Failed to bind socket \"%s\": %s", 01193 path, _dbus_strerror (errno)); 01194 _dbus_close (listen_fd, NULL); 01195 return -1; 01196 } 01197 01198 if (listen (listen_fd, 30 /* backlog */) < 0) 01199 { 01200 dbus_set_error (error, _dbus_error_from_errno (errno), 01201 "Failed to listen on socket \"%s\": %s", 01202 path, _dbus_strerror (errno)); 01203 _dbus_close (listen_fd, NULL); 01204 return -1; 01205 } 01206 01207 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01208 { 01209 _DBUS_ASSERT_ERROR_IS_SET (error); 01210 _dbus_close (listen_fd, NULL); 01211 return -1; 01212 } 01213 01214 /* Try opening up the permissions, but if we can't, just go ahead 01215 * and continue, maybe it will be good enough. 01216 */ 01217 if (!abstract && chmod (path, 0777) < 0) 01218 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01219 path); 01220 01221 return listen_fd; 01222 } 01223 01234 int 01235 _dbus_listen_systemd_sockets (DBusSocket **fds, 01236 DBusError *error) 01237 { 01238 #ifdef HAVE_SYSTEMD 01239 int r, n; 01240 int fd; 01241 DBusSocket *new_fds; 01242 01243 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01244 01245 n = sd_listen_fds (TRUE); 01246 if (n < 0) 01247 { 01248 dbus_set_error (error, _dbus_error_from_errno (-n), 01249 "Failed to acquire systemd socket: %s", 01250 _dbus_strerror (-n)); 01251 return -1; 01252 } 01253 01254 if (n <= 0) 01255 { 01256 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01257 "No socket received."); 01258 return -1; 01259 } 01260 01261 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01262 { 01263 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01264 if (r < 0) 01265 { 01266 dbus_set_error (error, _dbus_error_from_errno (-r), 01267 "Failed to verify systemd socket type: %s", 01268 _dbus_strerror (-r)); 01269 return -1; 01270 } 01271 01272 if (!r) 01273 { 01274 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01275 "Passed socket has wrong type."); 01276 return -1; 01277 } 01278 } 01279 01280 /* OK, the file descriptors are all good, so let's take posession of 01281 them then. */ 01282 01283 new_fds = dbus_new (DBusSocket, n); 01284 if (!new_fds) 01285 { 01286 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01287 "Failed to allocate file handle array."); 01288 goto fail; 01289 } 01290 01291 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01292 { 01293 if (!_dbus_set_fd_nonblocking (fd, error)) 01294 { 01295 _DBUS_ASSERT_ERROR_IS_SET (error); 01296 goto fail; 01297 } 01298 01299 new_fds[fd - SD_LISTEN_FDS_START].fd = fd; 01300 } 01301 01302 *fds = new_fds; 01303 return n; 01304 01305 fail: 01306 01307 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01308 { 01309 _dbus_close (fd, NULL); 01310 } 01311 01312 dbus_free (new_fds); 01313 return -1; 01314 #else 01315 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 01316 "dbus was compiled without systemd support"); 01317 return -1; 01318 #endif 01319 } 01320 01334 DBusSocket 01335 _dbus_connect_tcp_socket (const char *host, 01336 const char *port, 01337 const char *family, 01338 DBusError *error) 01339 { 01340 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01341 } 01342 01343 DBusSocket 01344 _dbus_connect_tcp_socket_with_nonce (const char *host, 01345 const char *port, 01346 const char *family, 01347 const char *noncefile, 01348 DBusError *error) 01349 { 01350 int saved_errno = 0; 01351 DBusSocket fd = DBUS_SOCKET_INIT; 01352 int res; 01353 struct addrinfo hints; 01354 struct addrinfo *ai, *tmp; 01355 01356 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01357 01358 _DBUS_ZERO (hints); 01359 01360 if (!family) 01361 hints.ai_family = AF_UNSPEC; 01362 else if (!strcmp(family, "ipv4")) 01363 hints.ai_family = AF_INET; 01364 else if (!strcmp(family, "ipv6")) 01365 hints.ai_family = AF_INET6; 01366 else 01367 { 01368 dbus_set_error (error, 01369 DBUS_ERROR_BAD_ADDRESS, 01370 "Unknown address family %s", family); 01371 return _dbus_socket_get_invalid (); 01372 } 01373 hints.ai_protocol = IPPROTO_TCP; 01374 hints.ai_socktype = SOCK_STREAM; 01375 hints.ai_flags = AI_ADDRCONFIG; 01376 01377 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01378 { 01379 dbus_set_error (error, 01380 _dbus_error_from_errno (errno), 01381 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01382 host, port, gai_strerror(res), res); 01383 return _dbus_socket_get_invalid (); 01384 } 01385 01386 tmp = ai; 01387 while (tmp) 01388 { 01389 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01390 { 01391 freeaddrinfo(ai); 01392 _DBUS_ASSERT_ERROR_IS_SET(error); 01393 return _dbus_socket_get_invalid (); 01394 } 01395 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01396 01397 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01398 { 01399 saved_errno = errno; 01400 _dbus_close (fd.fd, NULL); 01401 fd.fd = -1; 01402 tmp = tmp->ai_next; 01403 continue; 01404 } 01405 01406 break; 01407 } 01408 freeaddrinfo(ai); 01409 01410 if (fd.fd == -1) 01411 { 01412 dbus_set_error (error, 01413 _dbus_error_from_errno (saved_errno), 01414 "Failed to connect to socket \"%s:%s\" %s", 01415 host, port, _dbus_strerror(saved_errno)); 01416 return _dbus_socket_get_invalid (); 01417 } 01418 01419 if (noncefile != NULL) 01420 { 01421 DBusString noncefileStr; 01422 dbus_bool_t ret; 01423 _dbus_string_init_const (&noncefileStr, noncefile); 01424 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01425 _dbus_string_free (&noncefileStr); 01426 01427 if (!ret) 01428 { 01429 _dbus_close (fd.fd, NULL); 01430 return _dbus_socket_get_invalid (); 01431 } 01432 } 01433 01434 if (!_dbus_set_fd_nonblocking (fd.fd, error)) 01435 { 01436 _dbus_close (fd.fd, NULL); 01437 return _dbus_socket_get_invalid (); 01438 } 01439 01440 return fd; 01441 } 01442 01459 int 01460 _dbus_listen_tcp_socket (const char *host, 01461 const char *port, 01462 const char *family, 01463 DBusString *retport, 01464 DBusSocket **fds_p, 01465 DBusError *error) 01466 { 01467 int saved_errno; 01468 int nlisten_fd = 0, res, i; 01469 DBusSocket *listen_fd = NULL; 01470 struct addrinfo hints; 01471 struct addrinfo *ai, *tmp; 01472 unsigned int reuseaddr; 01473 01474 *fds_p = NULL; 01475 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01476 01477 _DBUS_ZERO (hints); 01478 01479 if (!family) 01480 hints.ai_family = AF_UNSPEC; 01481 else if (!strcmp(family, "ipv4")) 01482 hints.ai_family = AF_INET; 01483 else if (!strcmp(family, "ipv6")) 01484 hints.ai_family = AF_INET6; 01485 else 01486 { 01487 dbus_set_error (error, 01488 DBUS_ERROR_BAD_ADDRESS, 01489 "Unknown address family %s", family); 01490 return -1; 01491 } 01492 01493 hints.ai_protocol = IPPROTO_TCP; 01494 hints.ai_socktype = SOCK_STREAM; 01495 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01496 01497 redo_lookup_with_port: 01498 ai = NULL; 01499 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01500 { 01501 dbus_set_error (error, 01502 _dbus_error_from_errno (errno), 01503 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01504 host ? host : "*", port, gai_strerror(res), res); 01505 goto failed; 01506 } 01507 01508 tmp = ai; 01509 while (tmp) 01510 { 01511 int fd = -1, tcp_nodelay_on; 01512 DBusSocket *newlisten_fd; 01513 01514 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01515 { 01516 _DBUS_ASSERT_ERROR_IS_SET(error); 01517 goto failed; 01518 } 01519 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01520 01521 reuseaddr = 1; 01522 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01523 { 01524 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01525 host ? host : "*", port, _dbus_strerror (errno)); 01526 } 01527 01528 /* Nagle's algorithm imposes a huge delay on the initial messages 01529 going over TCP. */ 01530 tcp_nodelay_on = 1; 01531 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1) 01532 { 01533 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s", 01534 host ? host : "*", port, _dbus_strerror (errno)); 01535 } 01536 01537 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01538 { 01539 saved_errno = errno; 01540 _dbus_close(fd, NULL); 01541 if (saved_errno == EADDRINUSE) 01542 { 01543 /* Depending on kernel policy, binding to an IPv6 address 01544 might implicitly bind to a corresponding IPv4 01545 address or vice versa, resulting in EADDRINUSE for the 01546 other one (e.g. bindv6only=0 on Linux). 01547 01548 Also, after we "goto redo_lookup_with_port" after binding 01549 a port on one of the possible addresses, we will 01550 try to bind that same port on every address, including the 01551 same address again for a second time; that one will 01552 also fail with EADDRINUSE. 01553 01554 For both those reasons, ignore EADDRINUSE here */ 01555 tmp = tmp->ai_next; 01556 continue; 01557 } 01558 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01559 "Failed to bind socket \"%s:%s\": %s", 01560 host ? host : "*", port, _dbus_strerror (saved_errno)); 01561 goto failed; 01562 } 01563 01564 if (listen (fd, 30 /* backlog */) < 0) 01565 { 01566 saved_errno = errno; 01567 _dbus_close (fd, NULL); 01568 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01569 "Failed to listen on socket \"%s:%s\": %s", 01570 host ? host : "*", port, _dbus_strerror (saved_errno)); 01571 goto failed; 01572 } 01573 01574 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1)); 01575 if (!newlisten_fd) 01576 { 01577 saved_errno = errno; 01578 _dbus_close (fd, NULL); 01579 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01580 "Failed to allocate file handle array: %s", 01581 _dbus_strerror (saved_errno)); 01582 goto failed; 01583 } 01584 listen_fd = newlisten_fd; 01585 listen_fd[nlisten_fd].fd = fd; 01586 nlisten_fd++; 01587 01588 if (!_dbus_string_get_length(retport)) 01589 { 01590 /* If the user didn't specify a port, or used 0, then 01591 the kernel chooses a port. After the first address 01592 is bound to, we need to force all remaining addresses 01593 to use the same port */ 01594 if (!port || !strcmp(port, "0")) 01595 { 01596 int result; 01597 struct sockaddr_storage addr; 01598 socklen_t addrlen; 01599 char portbuf[50]; 01600 01601 addrlen = sizeof(addr); 01602 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01603 01604 if (result == -1 || 01605 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0, 01606 portbuf, sizeof(portbuf), 01607 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) 01608 { 01609 dbus_set_error (error, _dbus_error_from_errno (errno), 01610 "Failed to resolve port \"%s:%s\": %s (%s)", 01611 host ? host : "*", port, gai_strerror(res), res); 01612 goto failed; 01613 } 01614 if (!_dbus_string_append(retport, portbuf)) 01615 { 01616 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01617 goto failed; 01618 } 01619 01620 /* Release current address list & redo lookup */ 01621 port = _dbus_string_get_const_data(retport); 01622 freeaddrinfo(ai); 01623 goto redo_lookup_with_port; 01624 } 01625 else 01626 { 01627 if (!_dbus_string_append(retport, port)) 01628 { 01629 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01630 goto failed; 01631 } 01632 } 01633 } 01634 01635 tmp = tmp->ai_next; 01636 } 01637 freeaddrinfo(ai); 01638 ai = NULL; 01639 01640 if (!nlisten_fd) 01641 { 01642 errno = EADDRINUSE; 01643 dbus_set_error (error, _dbus_error_from_errno (errno), 01644 "Failed to bind socket \"%s:%s\": %s", 01645 host ? host : "*", port, _dbus_strerror (errno)); 01646 goto failed; 01647 } 01648 01649 for (i = 0 ; i < nlisten_fd ; i++) 01650 { 01651 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error)) 01652 { 01653 goto failed; 01654 } 01655 } 01656 01657 *fds_p = listen_fd; 01658 01659 return nlisten_fd; 01660 01661 failed: 01662 if (ai) 01663 freeaddrinfo(ai); 01664 for (i = 0 ; i < nlisten_fd ; i++) 01665 _dbus_close(listen_fd[i].fd, NULL); 01666 dbus_free(listen_fd); 01667 return -1; 01668 } 01669 01670 static dbus_bool_t 01671 write_credentials_byte (int server_fd, 01672 DBusError *error) 01673 { 01674 int bytes_written; 01675 char buf[1] = { '\0' }; 01676 #if defined(HAVE_CMSGCRED) 01677 union { 01678 struct cmsghdr hdr; 01679 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01680 } cmsg; 01681 struct iovec iov; 01682 struct msghdr msg; 01683 iov.iov_base = buf; 01684 iov.iov_len = 1; 01685 01686 _DBUS_ZERO(msg); 01687 msg.msg_iov = &iov; 01688 msg.msg_iovlen = 1; 01689 01690 msg.msg_control = (caddr_t) &cmsg; 01691 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01692 _DBUS_ZERO(cmsg); 01693 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01694 cmsg.hdr.cmsg_level = SOL_SOCKET; 01695 cmsg.hdr.cmsg_type = SCM_CREDS; 01696 #endif 01697 01698 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01699 01700 again: 01701 01702 #if defined(HAVE_CMSGCRED) 01703 bytes_written = sendmsg (server_fd, &msg, 0 01704 #if HAVE_DECL_MSG_NOSIGNAL 01705 |MSG_NOSIGNAL 01706 #endif 01707 ); 01708 01709 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg() 01710 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD 01711 * only allows that on AF_UNIX. Try just doing a send() instead. */ 01712 if (bytes_written < 0 && errno == EINVAL) 01713 #endif 01714 { 01715 bytes_written = send (server_fd, buf, 1, 0 01716 #if HAVE_DECL_MSG_NOSIGNAL 01717 |MSG_NOSIGNAL 01718 #endif 01719 ); 01720 } 01721 01722 if (bytes_written < 0 && errno == EINTR) 01723 goto again; 01724 01725 if (bytes_written < 0) 01726 { 01727 dbus_set_error (error, _dbus_error_from_errno (errno), 01728 "Failed to write credentials byte: %s", 01729 _dbus_strerror (errno)); 01730 return FALSE; 01731 } 01732 else if (bytes_written == 0) 01733 { 01734 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01735 "wrote zero bytes writing credentials byte"); 01736 return FALSE; 01737 } 01738 else 01739 { 01740 _dbus_assert (bytes_written == 1); 01741 _dbus_verbose ("wrote credentials byte\n"); 01742 return TRUE; 01743 } 01744 } 01745 01746 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */ 01747 static dbus_bool_t 01748 add_linux_security_label_to_credentials (int client_fd, 01749 DBusCredentials *credentials) 01750 { 01751 #if defined(__linux__) && defined(SO_PEERSEC) 01752 DBusString buf; 01753 socklen_t len = 1024; 01754 dbus_bool_t oom = FALSE; 01755 01756 if (!_dbus_string_init_preallocated (&buf, len) || 01757 !_dbus_string_set_length (&buf, len)) 01758 return FALSE; 01759 01760 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC, 01761 _dbus_string_get_data (&buf), &len) < 0) 01762 { 01763 int e = errno; 01764 01765 _dbus_verbose ("getsockopt failed with %s, len now %lu\n", 01766 _dbus_strerror (e), (unsigned long) len); 01767 01768 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf)) 01769 { 01770 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n", 01771 _dbus_strerror (e)); 01772 goto out; 01773 } 01774 01775 /* If not enough space, len is updated to be enough. 01776 * Try again with a large enough buffer. */ 01777 if (!_dbus_string_set_length (&buf, len)) 01778 { 01779 oom = TRUE; 01780 goto out; 01781 } 01782 01783 _dbus_verbose ("will try again with %lu\n", (unsigned long) len); 01784 } 01785 01786 if (len <= 0) 01787 { 01788 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n", 01789 (unsigned long) len); 01790 goto out; 01791 } 01792 01793 if (len > _dbus_string_get_length_uint (&buf)) 01794 { 01795 _dbus_verbose ("%lu > %u", (unsigned long) len, 01796 _dbus_string_get_length_uint (&buf)); 01797 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed"); 01798 } 01799 01800 if (_dbus_string_get_byte (&buf, len - 1) == 0) 01801 { 01802 /* the kernel included the trailing \0 in its count, 01803 * but DBusString always has an extra \0 after the data anyway */ 01804 _dbus_verbose ("subtracting trailing \\0\n"); 01805 len--; 01806 } 01807 01808 if (!_dbus_string_set_length (&buf, len)) 01809 { 01810 _dbus_assert_not_reached ("shortening string should not lead to OOM"); 01811 oom = TRUE; 01812 goto out; 01813 } 01814 01815 if (strlen (_dbus_string_get_const_data (&buf)) != len) 01816 { 01817 /* LSM people on the linux-security-module@ mailing list say this 01818 * should never happen: the label should be a bytestring with 01819 * an optional trailing \0 */ 01820 _dbus_verbose ("security label from kernel had an embedded \\0, " 01821 "ignoring it\n"); 01822 goto out; 01823 } 01824 01825 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n", 01826 (unsigned long) len, 01827 _dbus_string_get_const_data (&buf)); 01828 01829 if (!_dbus_credentials_add_linux_security_label (credentials, 01830 _dbus_string_get_const_data (&buf))) 01831 { 01832 oom = TRUE; 01833 goto out; 01834 } 01835 01836 out: 01837 _dbus_string_free (&buf); 01838 return !oom; 01839 #else 01840 /* no error */ 01841 return TRUE; 01842 #endif 01843 } 01844 01885 dbus_bool_t 01886 _dbus_read_credentials_socket (DBusSocket client_fd, 01887 DBusCredentials *credentials, 01888 DBusError *error) 01889 { 01890 struct msghdr msg; 01891 struct iovec iov; 01892 char buf; 01893 dbus_uid_t uid_read; 01894 dbus_pid_t pid_read; 01895 int bytes_read; 01896 01897 #ifdef HAVE_CMSGCRED 01898 union { 01899 struct cmsghdr hdr; 01900 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01901 } cmsg; 01902 #endif 01903 01904 /* The POSIX spec certainly doesn't promise this, but 01905 * we need these assertions to fail as soon as we're wrong about 01906 * it so we can do the porting fixups 01907 */ 01908 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01909 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01910 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01911 01912 uid_read = DBUS_UID_UNSET; 01913 pid_read = DBUS_PID_UNSET; 01914 01915 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01916 01917 _dbus_credentials_clear (credentials); 01918 01919 iov.iov_base = &buf; 01920 iov.iov_len = 1; 01921 01922 _DBUS_ZERO(msg); 01923 msg.msg_iov = &iov; 01924 msg.msg_iovlen = 1; 01925 01926 #if defined(HAVE_CMSGCRED) 01927 _DBUS_ZERO(cmsg); 01928 msg.msg_control = (caddr_t) &cmsg; 01929 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01930 #endif 01931 01932 again: 01933 bytes_read = recvmsg (client_fd.fd, &msg, 0); 01934 01935 if (bytes_read < 0) 01936 { 01937 if (errno == EINTR) 01938 goto again; 01939 01940 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01941 * normally only call read_credentials if the socket was ready 01942 * for reading 01943 */ 01944 01945 dbus_set_error (error, _dbus_error_from_errno (errno), 01946 "Failed to read credentials byte: %s", 01947 _dbus_strerror (errno)); 01948 return FALSE; 01949 } 01950 else if (bytes_read == 0) 01951 { 01952 /* this should not happen unless we are using recvmsg wrong, 01953 * so is essentially here for paranoia 01954 */ 01955 dbus_set_error (error, DBUS_ERROR_FAILED, 01956 "Failed to read credentials byte (zero-length read)"); 01957 return FALSE; 01958 } 01959 else if (buf != '\0') 01960 { 01961 dbus_set_error (error, DBUS_ERROR_FAILED, 01962 "Credentials byte was not nul"); 01963 return FALSE; 01964 } 01965 01966 _dbus_verbose ("read credentials byte\n"); 01967 01968 { 01969 #ifdef SO_PEERCRED 01970 /* Supported by at least Linux and OpenBSD, with minor differences. 01971 * 01972 * This mechanism passes the process ID through and does not require 01973 * the peer's cooperation, so we prefer it over all others. Notably, 01974 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD 01975 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all, 01976 * because this is much less fragile. 01977 */ 01978 #ifdef __OpenBSD__ 01979 struct sockpeercred cr; 01980 #else 01981 struct ucred cr; 01982 #endif 01983 int cr_len = sizeof (cr); 01984 01985 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0) 01986 { 01987 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n", 01988 _dbus_strerror (errno)); 01989 } 01990 else if (cr_len != sizeof (cr)) 01991 { 01992 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n", 01993 cr_len, (int) sizeof (cr)); 01994 } 01995 else 01996 { 01997 pid_read = cr.pid; 01998 uid_read = cr.uid; 01999 } 02000 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID) 02001 /* Another variant of the above - used on NetBSD 02002 */ 02003 struct unpcbid cr; 02004 socklen_t cr_len = sizeof (cr); 02005 02006 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0) 02007 { 02008 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n", 02009 _dbus_strerror (errno)); 02010 } 02011 else if (cr_len != sizeof (cr)) 02012 { 02013 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n", 02014 cr_len, (int) sizeof (cr)); 02015 } 02016 else 02017 { 02018 pid_read = cr.unp_pid; 02019 uid_read = cr.unp_euid; 02020 } 02021 #elif defined(HAVE_CMSGCRED) 02022 /* We only check for HAVE_CMSGCRED, but we're really assuming that the 02023 * presence of that struct implies SCM_CREDS. Supported by at least 02024 * FreeBSD and DragonflyBSD. 02025 * 02026 * This mechanism requires the peer to help us (it has to send us a 02027 * SCM_CREDS message) but it does pass the process ID through, 02028 * which makes it better than getpeereid(). 02029 */ 02030 struct cmsgcred *cred; 02031 struct cmsghdr *cmsgp; 02032 02033 for (cmsgp = CMSG_FIRSTHDR (&msg); 02034 cmsgp != NULL; 02035 cmsgp = CMSG_NXTHDR (&msg, cmsgp)) 02036 { 02037 if (cmsgp->cmsg_type == SCM_CREDS && 02038 cmsgp->cmsg_level == SOL_SOCKET && 02039 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred))) 02040 { 02041 cred = (struct cmsgcred *) CMSG_DATA (cmsgp); 02042 pid_read = cred->cmcred_pid; 02043 uid_read = cred->cmcred_euid; 02044 break; 02045 } 02046 } 02047 02048 #elif defined(HAVE_GETPEERUCRED) 02049 /* Supported in at least Solaris >= 10. It should probably be higher 02050 * up this list, because it carries the pid and we use this code path 02051 * for audit data. */ 02052 ucred_t * ucred = NULL; 02053 if (getpeerucred (client_fd.fd, &ucred) == 0) 02054 { 02055 pid_read = ucred_getpid (ucred); 02056 uid_read = ucred_geteuid (ucred); 02057 #ifdef HAVE_ADT 02058 /* generate audit session data based on socket ucred */ 02059 adt_session_data_t *adth = NULL; 02060 adt_export_data_t *data = NULL; 02061 size_t size = 0; 02062 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 02063 { 02064 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 02065 } 02066 else 02067 { 02068 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 02069 { 02070 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 02071 } 02072 else 02073 { 02074 size = adt_export_session_data (adth, &data); 02075 if (size <= 0) 02076 { 02077 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 02078 } 02079 else 02080 { 02081 _dbus_credentials_add_adt_audit_data (credentials, data, size); 02082 free (data); 02083 } 02084 } 02085 (void) adt_end_session (adth); 02086 } 02087 #endif /* HAVE_ADT */ 02088 } 02089 else 02090 { 02091 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 02092 } 02093 if (ucred != NULL) 02094 ucred_free (ucred); 02095 02096 /* ---------------------------------------------------------------- 02097 * When adding new mechanisms, please add them above this point 02098 * if they support passing the process ID through, or below if not. 02099 * ---------------------------------------------------------------- */ 02100 02101 #elif defined(HAVE_GETPEEREID) 02102 /* getpeereid() originates from D.J. Bernstein and is fairly 02103 * widely-supported. According to a web search, it might be present in 02104 * any/all of: 02105 * 02106 * - AIX? 02107 * - Blackberry? 02108 * - Cygwin 02109 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid) 02110 * - Mac OS X 02111 * - Minix 3.1.8+ 02112 * - MirBSD? 02113 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid) 02114 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid) 02115 * - QNX? 02116 */ 02117 uid_t euid; 02118 gid_t egid; 02119 if (getpeereid (client_fd.fd, &euid, &egid) == 0) 02120 { 02121 uid_read = euid; 02122 } 02123 else 02124 { 02125 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 02126 } 02127 #else /* no supported mechanism */ 02128 02129 #warning Socket credentials not supported on this Unix OS 02130 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus 02131 02132 /* Please add other operating systems known to support at least one of 02133 * the mechanisms above to this list, keeping alphabetical order. 02134 * Everything not in this list is best-effort. 02135 */ 02136 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ 02137 defined(__linux__) || \ 02138 defined(__OpenBSD__) || \ 02139 defined(__NetBSD__) 02140 # error Credentials passing not working on this OS is a regression! 02141 #endif 02142 02143 _dbus_verbose ("Socket credentials not supported on this OS\n"); 02144 #endif 02145 } 02146 02147 _dbus_verbose ("Credentials:" 02148 " pid "DBUS_PID_FORMAT 02149 " uid "DBUS_UID_FORMAT 02150 "\n", 02151 pid_read, 02152 uid_read); 02153 02154 if (pid_read != DBUS_PID_UNSET) 02155 { 02156 if (!_dbus_credentials_add_pid (credentials, pid_read)) 02157 { 02158 _DBUS_SET_OOM (error); 02159 return FALSE; 02160 } 02161 } 02162 02163 if (uid_read != DBUS_UID_UNSET) 02164 { 02165 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 02166 { 02167 _DBUS_SET_OOM (error); 02168 return FALSE; 02169 } 02170 } 02171 02172 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials)) 02173 { 02174 _DBUS_SET_OOM (error); 02175 return FALSE; 02176 } 02177 02178 return TRUE; 02179 } 02180 02198 dbus_bool_t 02199 _dbus_send_credentials_socket (DBusSocket server_fd, 02200 DBusError *error) 02201 { 02202 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02203 02204 if (write_credentials_byte (server_fd.fd, error)) 02205 return TRUE; 02206 else 02207 return FALSE; 02208 } 02209 02219 DBusSocket 02220 _dbus_accept (DBusSocket listen_fd) 02221 { 02222 DBusSocket client_fd; 02223 struct sockaddr addr; 02224 socklen_t addrlen; 02225 #ifdef HAVE_ACCEPT4 02226 dbus_bool_t cloexec_done; 02227 #endif 02228 02229 addrlen = sizeof (addr); 02230 02231 retry: 02232 02233 #ifdef HAVE_ACCEPT4 02234 /* 02235 * At compile-time, we assume that if accept4() is available in 02236 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still 02237 * not necessarily true that either is supported by the running kernel. 02238 */ 02239 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC); 02240 cloexec_done = client_fd.fd >= 0; 02241 02242 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL)) 02243 #endif 02244 { 02245 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen); 02246 } 02247 02248 if (client_fd.fd < 0) 02249 { 02250 if (errno == EINTR) 02251 goto retry; 02252 } 02253 02254 _dbus_verbose ("client fd %d accepted\n", client_fd.fd); 02255 02256 #ifdef HAVE_ACCEPT4 02257 if (!cloexec_done) 02258 #endif 02259 { 02260 _dbus_fd_set_close_on_exec(client_fd.fd); 02261 } 02262 02263 return client_fd; 02264 } 02265 02274 dbus_bool_t 02275 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 02276 { 02277 const char *directory; 02278 struct stat sb; 02279 02280 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02281 02282 directory = _dbus_string_get_const_data (dir); 02283 02284 if (stat (directory, &sb) < 0) 02285 { 02286 dbus_set_error (error, _dbus_error_from_errno (errno), 02287 "%s", _dbus_strerror (errno)); 02288 02289 return FALSE; 02290 } 02291 02292 if (sb.st_uid != geteuid ()) 02293 { 02294 dbus_set_error (error, DBUS_ERROR_FAILED, 02295 "%s directory is owned by user %lu, not %lu", 02296 directory, 02297 (unsigned long) sb.st_uid, 02298 (unsigned long) geteuid ()); 02299 return FALSE; 02300 } 02301 02302 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 02303 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 02304 { 02305 dbus_set_error (error, DBUS_ERROR_FAILED, 02306 "%s directory is not private to the user", directory); 02307 return FALSE; 02308 } 02309 02310 return TRUE; 02311 } 02312 02313 static dbus_bool_t 02314 fill_user_info_from_passwd (struct passwd *p, 02315 DBusUserInfo *info, 02316 DBusError *error) 02317 { 02318 _dbus_assert (p->pw_name != NULL); 02319 _dbus_assert (p->pw_dir != NULL); 02320 02321 info->uid = p->pw_uid; 02322 info->primary_gid = p->pw_gid; 02323 info->username = _dbus_strdup (p->pw_name); 02324 info->homedir = _dbus_strdup (p->pw_dir); 02325 02326 if (info->username == NULL || 02327 info->homedir == NULL) 02328 { 02329 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02330 return FALSE; 02331 } 02332 02333 return TRUE; 02334 } 02335 02336 static dbus_bool_t 02337 fill_user_info (DBusUserInfo *info, 02338 dbus_uid_t uid, 02339 const DBusString *username, 02340 DBusError *error) 02341 { 02342 const char *username_c; 02343 02344 /* exactly one of username/uid provided */ 02345 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 02346 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 02347 02348 info->uid = DBUS_UID_UNSET; 02349 info->primary_gid = DBUS_GID_UNSET; 02350 info->group_ids = NULL; 02351 info->n_group_ids = 0; 02352 info->username = NULL; 02353 info->homedir = NULL; 02354 02355 if (username != NULL) 02356 username_c = _dbus_string_get_const_data (username); 02357 else 02358 username_c = NULL; 02359 02360 /* For now assuming that the getpwnam() and getpwuid() flavors 02361 * are always symmetrical, if not we have to add more configure 02362 * checks 02363 */ 02364 02365 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 02366 { 02367 struct passwd *p; 02368 int result; 02369 size_t buflen; 02370 char *buf; 02371 struct passwd p_str; 02372 02373 /* retrieve maximum needed size for buf */ 02374 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 02375 02376 /* sysconf actually returns a long, but everything else expects size_t, 02377 * so just recast here. 02378 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 02379 */ 02380 if ((long) buflen <= 0) 02381 buflen = 1024; 02382 02383 result = -1; 02384 while (1) 02385 { 02386 buf = dbus_malloc (buflen); 02387 if (buf == NULL) 02388 { 02389 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02390 return FALSE; 02391 } 02392 02393 p = NULL; 02394 #ifdef HAVE_POSIX_GETPWNAM_R 02395 if (uid != DBUS_UID_UNSET) 02396 result = getpwuid_r (uid, &p_str, buf, buflen, 02397 &p); 02398 else 02399 result = getpwnam_r (username_c, &p_str, buf, buflen, 02400 &p); 02401 #else 02402 if (uid != DBUS_UID_UNSET) 02403 p = getpwuid_r (uid, &p_str, buf, buflen); 02404 else 02405 p = getpwnam_r (username_c, &p_str, buf, buflen); 02406 result = 0; 02407 #endif /* !HAVE_POSIX_GETPWNAM_R */ 02408 //Try a bigger buffer if ERANGE was returned 02409 if (result == ERANGE && buflen < 512 * 1024) 02410 { 02411 dbus_free (buf); 02412 buflen *= 2; 02413 } 02414 else 02415 { 02416 break; 02417 } 02418 } 02419 if (result == 0 && p == &p_str) 02420 { 02421 if (!fill_user_info_from_passwd (p, info, error)) 02422 { 02423 dbus_free (buf); 02424 return FALSE; 02425 } 02426 dbus_free (buf); 02427 } 02428 else 02429 { 02430 dbus_set_error (error, _dbus_error_from_errno (errno), 02431 "User \"%s\" unknown or no memory to allocate password entry\n", 02432 username_c ? username_c : "???"); 02433 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02434 dbus_free (buf); 02435 return FALSE; 02436 } 02437 } 02438 #else /* ! HAVE_GETPWNAM_R */ 02439 { 02440 /* I guess we're screwed on thread safety here */ 02441 struct passwd *p; 02442 02443 if (uid != DBUS_UID_UNSET) 02444 p = getpwuid (uid); 02445 else 02446 p = getpwnam (username_c); 02447 02448 if (p != NULL) 02449 { 02450 if (!fill_user_info_from_passwd (p, info, error)) 02451 { 02452 return FALSE; 02453 } 02454 } 02455 else 02456 { 02457 dbus_set_error (error, _dbus_error_from_errno (errno), 02458 "User \"%s\" unknown or no memory to allocate password entry\n", 02459 username_c ? username_c : "???"); 02460 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02461 return FALSE; 02462 } 02463 } 02464 #endif /* ! HAVE_GETPWNAM_R */ 02465 02466 /* Fill this in so we can use it to get groups */ 02467 username_c = info->username; 02468 02469 #ifdef HAVE_GETGROUPLIST 02470 { 02471 gid_t *buf; 02472 int buf_count; 02473 int i; 02474 int initial_buf_count; 02475 02476 initial_buf_count = 17; 02477 buf_count = initial_buf_count; 02478 buf = dbus_new (gid_t, buf_count); 02479 if (buf == NULL) 02480 { 02481 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02482 goto failed; 02483 } 02484 02485 if (getgrouplist (username_c, 02486 info->primary_gid, 02487 buf, &buf_count) < 0) 02488 { 02489 gid_t *new; 02490 /* Presumed cause of negative return code: buf has insufficient 02491 entries to hold the entire group list. The Linux behavior in this 02492 case is to pass back the actual number of groups in buf_count, but 02493 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02494 So as a hack, try to help out a bit by guessing a larger 02495 number of groups, within reason.. might still fail, of course, 02496 but we can at least print a more informative message. I looked up 02497 the "right way" to do this by downloading Apple's own source code 02498 for the "id" command, and it turns out that they use an 02499 undocumented library function getgrouplist_2 (!) which is not 02500 declared in any header in /usr/include (!!). That did not seem 02501 like the way to go here. 02502 */ 02503 if (buf_count == initial_buf_count) 02504 { 02505 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02506 } 02507 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02508 if (new == NULL) 02509 { 02510 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02511 dbus_free (buf); 02512 goto failed; 02513 } 02514 02515 buf = new; 02516 02517 errno = 0; 02518 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02519 { 02520 if (errno == 0) 02521 { 02522 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02523 username_c, buf_count, buf_count); 02524 } 02525 else 02526 { 02527 dbus_set_error (error, 02528 _dbus_error_from_errno (errno), 02529 "Failed to get groups for username \"%s\" primary GID " 02530 DBUS_GID_FORMAT ": %s\n", 02531 username_c, info->primary_gid, 02532 _dbus_strerror (errno)); 02533 dbus_free (buf); 02534 goto failed; 02535 } 02536 } 02537 } 02538 02539 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02540 if (info->group_ids == NULL) 02541 { 02542 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02543 dbus_free (buf); 02544 goto failed; 02545 } 02546 02547 for (i = 0; i < buf_count; ++i) 02548 info->group_ids[i] = buf[i]; 02549 02550 info->n_group_ids = buf_count; 02551 02552 dbus_free (buf); 02553 } 02554 #else /* HAVE_GETGROUPLIST */ 02555 { 02556 /* We just get the one group ID */ 02557 info->group_ids = dbus_new (dbus_gid_t, 1); 02558 if (info->group_ids == NULL) 02559 { 02560 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02561 goto failed; 02562 } 02563 02564 info->n_group_ids = 1; 02565 02566 (info->group_ids)[0] = info->primary_gid; 02567 } 02568 #endif /* HAVE_GETGROUPLIST */ 02569 02570 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02571 02572 return TRUE; 02573 02574 failed: 02575 _DBUS_ASSERT_ERROR_IS_SET (error); 02576 return FALSE; 02577 } 02578 02587 dbus_bool_t 02588 _dbus_user_info_fill (DBusUserInfo *info, 02589 const DBusString *username, 02590 DBusError *error) 02591 { 02592 return fill_user_info (info, DBUS_UID_UNSET, 02593 username, error); 02594 } 02595 02604 dbus_bool_t 02605 _dbus_user_info_fill_uid (DBusUserInfo *info, 02606 dbus_uid_t uid, 02607 DBusError *error) 02608 { 02609 return fill_user_info (info, uid, 02610 NULL, error); 02611 } 02612 02620 dbus_bool_t 02621 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02622 { 02623 /* The POSIX spec certainly doesn't promise this, but 02624 * we need these assertions to fail as soon as we're wrong about 02625 * it so we can do the porting fixups 02626 */ 02627 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02628 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02629 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02630 02631 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid())) 02632 return FALSE; 02633 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02634 return FALSE; 02635 02636 return TRUE; 02637 } 02638 02650 dbus_bool_t 02651 _dbus_append_user_from_current_process (DBusString *str) 02652 { 02653 return _dbus_string_append_uint (str, 02654 _dbus_geteuid ()); 02655 } 02656 02661 dbus_pid_t 02662 _dbus_getpid (void) 02663 { 02664 return getpid (); 02665 } 02666 02670 dbus_uid_t 02671 _dbus_getuid (void) 02672 { 02673 return getuid (); 02674 } 02675 02679 dbus_uid_t 02680 _dbus_geteuid (void) 02681 { 02682 return geteuid (); 02683 } 02684 02691 unsigned long 02692 _dbus_pid_for_log (void) 02693 { 02694 return getpid (); 02695 } 02696 02704 dbus_bool_t 02705 _dbus_parse_uid (const DBusString *uid_str, 02706 dbus_uid_t *uid) 02707 { 02708 int end; 02709 long val; 02710 02711 if (_dbus_string_get_length (uid_str) == 0) 02712 { 02713 _dbus_verbose ("UID string was zero length\n"); 02714 return FALSE; 02715 } 02716 02717 val = -1; 02718 end = 0; 02719 if (!_dbus_string_parse_int (uid_str, 0, &val, 02720 &end)) 02721 { 02722 _dbus_verbose ("could not parse string as a UID\n"); 02723 return FALSE; 02724 } 02725 02726 if (end != _dbus_string_get_length (uid_str)) 02727 { 02728 _dbus_verbose ("string contained trailing stuff after UID\n"); 02729 return FALSE; 02730 } 02731 02732 *uid = val; 02733 02734 return TRUE; 02735 } 02736 02737 #if !DBUS_USE_SYNC 02738 /* To be thread-safe by default on platforms that don't necessarily have 02739 * atomic operations (notably Debian armel, which is armv4t), we must 02740 * use a mutex that can be initialized statically, like this. 02741 * GLib >= 2.32 uses a similar system. 02742 */ 02743 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER; 02744 #endif 02745 02752 dbus_int32_t 02753 _dbus_atomic_inc (DBusAtomic *atomic) 02754 { 02755 #if DBUS_USE_SYNC 02756 return __sync_add_and_fetch(&atomic->value, 1)-1; 02757 #else 02758 dbus_int32_t res; 02759 02760 pthread_mutex_lock (&atomic_mutex); 02761 res = atomic->value; 02762 atomic->value += 1; 02763 pthread_mutex_unlock (&atomic_mutex); 02764 02765 return res; 02766 #endif 02767 } 02768 02775 dbus_int32_t 02776 _dbus_atomic_dec (DBusAtomic *atomic) 02777 { 02778 #if DBUS_USE_SYNC 02779 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02780 #else 02781 dbus_int32_t res; 02782 02783 pthread_mutex_lock (&atomic_mutex); 02784 res = atomic->value; 02785 atomic->value -= 1; 02786 pthread_mutex_unlock (&atomic_mutex); 02787 02788 return res; 02789 #endif 02790 } 02791 02799 dbus_int32_t 02800 _dbus_atomic_get (DBusAtomic *atomic) 02801 { 02802 #if DBUS_USE_SYNC 02803 __sync_synchronize (); 02804 return atomic->value; 02805 #else 02806 dbus_int32_t res; 02807 02808 pthread_mutex_lock (&atomic_mutex); 02809 res = atomic->value; 02810 pthread_mutex_unlock (&atomic_mutex); 02811 02812 return res; 02813 #endif 02814 } 02815 02824 int 02825 _dbus_poll (DBusPollFD *fds, 02826 int n_fds, 02827 int timeout_milliseconds) 02828 { 02829 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02830 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */ 02831 if (timeout_milliseconds < -1) 02832 { 02833 timeout_milliseconds = -1; 02834 } 02835 02836 return poll (fds, 02837 n_fds, 02838 timeout_milliseconds); 02839 #else /* ! HAVE_POLL */ 02840 /* Emulate poll() in terms of select() */ 02841 fd_set read_set, write_set, err_set; 02842 int max_fd = 0; 02843 int i; 02844 struct timeval tv; 02845 int ready; 02846 02847 FD_ZERO (&read_set); 02848 FD_ZERO (&write_set); 02849 FD_ZERO (&err_set); 02850 02851 for (i = 0; i < n_fds; i++) 02852 { 02853 DBusPollFD *fdp = &fds[i]; 02854 02855 if (fdp->events & _DBUS_POLLIN) 02856 FD_SET (fdp->fd, &read_set); 02857 02858 if (fdp->events & _DBUS_POLLOUT) 02859 FD_SET (fdp->fd, &write_set); 02860 02861 FD_SET (fdp->fd, &err_set); 02862 02863 max_fd = MAX (max_fd, fdp->fd); 02864 } 02865 02866 tv.tv_sec = timeout_milliseconds / 1000; 02867 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02868 02869 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02870 timeout_milliseconds < 0 ? NULL : &tv); 02871 02872 if (ready > 0) 02873 { 02874 for (i = 0; i < n_fds; i++) 02875 { 02876 DBusPollFD *fdp = &fds[i]; 02877 02878 fdp->revents = 0; 02879 02880 if (FD_ISSET (fdp->fd, &read_set)) 02881 fdp->revents |= _DBUS_POLLIN; 02882 02883 if (FD_ISSET (fdp->fd, &write_set)) 02884 fdp->revents |= _DBUS_POLLOUT; 02885 02886 if (FD_ISSET (fdp->fd, &err_set)) 02887 fdp->revents |= _DBUS_POLLERR; 02888 } 02889 } 02890 02891 return ready; 02892 #endif 02893 } 02894 02902 void 02903 _dbus_get_monotonic_time (long *tv_sec, 02904 long *tv_usec) 02905 { 02906 #ifdef HAVE_MONOTONIC_CLOCK 02907 struct timespec ts; 02908 clock_gettime (CLOCK_MONOTONIC, &ts); 02909 02910 if (tv_sec) 02911 *tv_sec = ts.tv_sec; 02912 if (tv_usec) 02913 *tv_usec = ts.tv_nsec / 1000; 02914 #else 02915 struct timeval t; 02916 02917 gettimeofday (&t, NULL); 02918 02919 if (tv_sec) 02920 *tv_sec = t.tv_sec; 02921 if (tv_usec) 02922 *tv_usec = t.tv_usec; 02923 #endif 02924 } 02925 02933 void 02934 _dbus_get_real_time (long *tv_sec, 02935 long *tv_usec) 02936 { 02937 struct timeval t; 02938 02939 gettimeofday (&t, NULL); 02940 02941 if (tv_sec) 02942 *tv_sec = t.tv_sec; 02943 if (tv_usec) 02944 *tv_usec = t.tv_usec; 02945 } 02946 02955 dbus_bool_t 02956 _dbus_create_directory (const DBusString *filename, 02957 DBusError *error) 02958 { 02959 const char *filename_c; 02960 02961 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02962 02963 filename_c = _dbus_string_get_const_data (filename); 02964 02965 if (mkdir (filename_c, 0700) < 0) 02966 { 02967 if (errno == EEXIST) 02968 return TRUE; 02969 02970 dbus_set_error (error, DBUS_ERROR_FAILED, 02971 "Failed to create directory %s: %s\n", 02972 filename_c, _dbus_strerror (errno)); 02973 return FALSE; 02974 } 02975 else 02976 return TRUE; 02977 } 02978 02989 dbus_bool_t 02990 _dbus_concat_dir_and_file (DBusString *dir, 02991 const DBusString *next_component) 02992 { 02993 dbus_bool_t dir_ends_in_slash; 02994 dbus_bool_t file_starts_with_slash; 02995 02996 if (_dbus_string_get_length (dir) == 0 || 02997 _dbus_string_get_length (next_component) == 0) 02998 return TRUE; 02999 03000 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 03001 _dbus_string_get_length (dir) - 1); 03002 03003 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 03004 03005 if (dir_ends_in_slash && file_starts_with_slash) 03006 { 03007 _dbus_string_shorten (dir, 1); 03008 } 03009 else if (!(dir_ends_in_slash || file_starts_with_slash)) 03010 { 03011 if (!_dbus_string_append_byte (dir, '/')) 03012 return FALSE; 03013 } 03014 03015 return _dbus_string_copy (next_component, 0, dir, 03016 _dbus_string_get_length (dir)); 03017 } 03018 03020 #define NANOSECONDS_PER_SECOND 1000000000 03021 03022 #define MICROSECONDS_PER_SECOND 1000000 03023 03024 #define MILLISECONDS_PER_SECOND 1000 03025 03026 #define NANOSECONDS_PER_MILLISECOND 1000000 03027 03028 #define MICROSECONDS_PER_MILLISECOND 1000 03029 03034 void 03035 _dbus_sleep_milliseconds (int milliseconds) 03036 { 03037 #ifdef HAVE_NANOSLEEP 03038 struct timespec req; 03039 struct timespec rem; 03040 03041 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 03042 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 03043 rem.tv_sec = 0; 03044 rem.tv_nsec = 0; 03045 03046 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 03047 req = rem; 03048 #elif defined (HAVE_USLEEP) 03049 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 03050 #else /* ! HAVE_USLEEP */ 03051 sleep (MAX (milliseconds / 1000, 1)); 03052 #endif 03053 } 03054 03064 dbus_bool_t 03065 _dbus_generate_random_bytes (DBusString *str, 03066 int n_bytes, 03067 DBusError *error) 03068 { 03069 int old_len; 03070 int fd; 03071 int result; 03072 03073 old_len = _dbus_string_get_length (str); 03074 fd = -1; 03075 03076 /* note, urandom on linux will fall back to pseudorandom */ 03077 fd = open ("/dev/urandom", O_RDONLY); 03078 03079 if (fd < 0) 03080 { 03081 dbus_set_error (error, _dbus_error_from_errno (errno), 03082 "Could not open /dev/urandom: %s", 03083 _dbus_strerror (errno)); 03084 return FALSE; 03085 } 03086 03087 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 03088 03089 result = _dbus_read (fd, str, n_bytes); 03090 03091 if (result != n_bytes) 03092 { 03093 if (result < 0) 03094 dbus_set_error (error, _dbus_error_from_errno (errno), 03095 "Could not read /dev/urandom: %s", 03096 _dbus_strerror (errno)); 03097 else 03098 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 03099 "Short read from /dev/urandom"); 03100 03101 _dbus_close (fd, NULL); 03102 _dbus_string_set_length (str, old_len); 03103 return FALSE; 03104 } 03105 03106 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 03107 n_bytes); 03108 03109 _dbus_close (fd, NULL); 03110 03111 return TRUE; 03112 } 03113 03119 void 03120 _dbus_exit (int code) 03121 { 03122 _exit (code); 03123 } 03124 03133 const char* 03134 _dbus_strerror (int error_number) 03135 { 03136 const char *msg; 03137 03138 msg = strerror (error_number); 03139 if (msg == NULL) 03140 msg = "unknown"; 03141 03142 return msg; 03143 } 03144 03148 void 03149 _dbus_disable_sigpipe (void) 03150 { 03151 signal (SIGPIPE, SIG_IGN); 03152 } 03153 03161 void 03162 _dbus_fd_set_close_on_exec (int fd) 03163 { 03164 int val; 03165 03166 val = fcntl (fd, F_GETFD, 0); 03167 03168 if (val < 0) 03169 return; 03170 03171 val |= FD_CLOEXEC; 03172 03173 fcntl (fd, F_SETFD, val); 03174 } 03175 03183 dbus_bool_t 03184 _dbus_close (int fd, 03185 DBusError *error) 03186 { 03187 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03188 03189 again: 03190 if (close (fd) < 0) 03191 { 03192 if (errno == EINTR) 03193 goto again; 03194 03195 dbus_set_error (error, _dbus_error_from_errno (errno), 03196 "Could not close fd %d", fd); 03197 return FALSE; 03198 } 03199 03200 return TRUE; 03201 } 03202 03211 int 03212 _dbus_dup(int fd, 03213 DBusError *error) 03214 { 03215 int new_fd; 03216 03217 #ifdef F_DUPFD_CLOEXEC 03218 dbus_bool_t cloexec_done; 03219 03220 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 03221 cloexec_done = new_fd >= 0; 03222 03223 if (new_fd < 0 && errno == EINVAL) 03224 #endif 03225 { 03226 new_fd = fcntl(fd, F_DUPFD, 3); 03227 } 03228 03229 if (new_fd < 0) { 03230 03231 dbus_set_error (error, _dbus_error_from_errno (errno), 03232 "Could not duplicate fd %d", fd); 03233 return -1; 03234 } 03235 03236 #ifdef F_DUPFD_CLOEXEC 03237 if (!cloexec_done) 03238 #endif 03239 { 03240 _dbus_fd_set_close_on_exec(new_fd); 03241 } 03242 03243 return new_fd; 03244 } 03245 03253 dbus_bool_t 03254 _dbus_set_socket_nonblocking (DBusSocket fd, 03255 DBusError *error) 03256 { 03257 return _dbus_set_fd_nonblocking (fd.fd, error); 03258 } 03259 03260 static dbus_bool_t 03261 _dbus_set_fd_nonblocking (int fd, 03262 DBusError *error) 03263 { 03264 int val; 03265 03266 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03267 03268 val = fcntl (fd, F_GETFL, 0); 03269 if (val < 0) 03270 { 03271 dbus_set_error (error, _dbus_error_from_errno (errno), 03272 "Failed to get flags from file descriptor %d: %s", 03273 fd, _dbus_strerror (errno)); 03274 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 03275 _dbus_strerror (errno)); 03276 return FALSE; 03277 } 03278 03279 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 03280 { 03281 dbus_set_error (error, _dbus_error_from_errno (errno), 03282 "Failed to set nonblocking flag of file descriptor %d: %s", 03283 fd, _dbus_strerror (errno)); 03284 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 03285 fd, _dbus_strerror (errno)); 03286 03287 return FALSE; 03288 } 03289 03290 return TRUE; 03291 } 03292 03298 void 03299 _dbus_print_backtrace (void) 03300 { 03301 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 03302 void *bt[500]; 03303 int bt_size; 03304 int i; 03305 char **syms; 03306 03307 bt_size = backtrace (bt, 500); 03308 03309 syms = backtrace_symbols (bt, bt_size); 03310 03311 i = 0; 03312 while (i < bt_size) 03313 { 03314 /* don't use dbus_warn since it can _dbus_abort() */ 03315 fprintf (stderr, " %s\n", syms[i]); 03316 ++i; 03317 } 03318 fflush (stderr); 03319 03320 free (syms); 03321 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 03322 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 03323 #else 03324 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 03325 #endif 03326 } 03327 03340 dbus_bool_t 03341 _dbus_socketpair (DBusSocket *fd1, 03342 DBusSocket *fd2, 03343 dbus_bool_t blocking, 03344 DBusError *error) 03345 { 03346 #ifdef HAVE_SOCKETPAIR 03347 int fds[2]; 03348 int retval; 03349 03350 #ifdef SOCK_CLOEXEC 03351 dbus_bool_t cloexec_done; 03352 03353 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 03354 cloexec_done = retval >= 0; 03355 03356 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE)) 03357 #endif 03358 { 03359 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 03360 } 03361 03362 if (retval < 0) 03363 { 03364 dbus_set_error (error, _dbus_error_from_errno (errno), 03365 "Could not create full-duplex pipe"); 03366 return FALSE; 03367 } 03368 03369 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03370 03371 #ifdef SOCK_CLOEXEC 03372 if (!cloexec_done) 03373 #endif 03374 { 03375 _dbus_fd_set_close_on_exec (fds[0]); 03376 _dbus_fd_set_close_on_exec (fds[1]); 03377 } 03378 03379 if (!blocking && 03380 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 03381 !_dbus_set_fd_nonblocking (fds[1], NULL))) 03382 { 03383 dbus_set_error (error, _dbus_error_from_errno (errno), 03384 "Could not set full-duplex pipe nonblocking"); 03385 03386 _dbus_close (fds[0], NULL); 03387 _dbus_close (fds[1], NULL); 03388 03389 return FALSE; 03390 } 03391 03392 fd1->fd = fds[0]; 03393 fd2->fd = fds[1]; 03394 03395 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 03396 fd1->fd, fd2->fd); 03397 03398 return TRUE; 03399 #else 03400 _dbus_warn ("_dbus_socketpair() not implemented on this OS\n"); 03401 dbus_set_error (error, DBUS_ERROR_FAILED, 03402 "_dbus_socketpair() not implemented on this OS"); 03403 return FALSE; 03404 #endif 03405 } 03406 03415 int 03416 _dbus_printf_string_upper_bound (const char *format, 03417 va_list args) 03418 { 03419 char static_buf[1024]; 03420 int bufsize = sizeof (static_buf); 03421 int len; 03422 va_list args_copy; 03423 03424 DBUS_VA_COPY (args_copy, args); 03425 len = vsnprintf (static_buf, bufsize, format, args_copy); 03426 va_end (args_copy); 03427 03428 /* If vsnprintf() returned non-negative, then either the string fits in 03429 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03430 * returns the number of characters that were needed, or this OS returns the 03431 * truncated length. 03432 * 03433 * We ignore the possibility that snprintf might just ignore the length and 03434 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03435 * If your libc is really that bad, come back when you have a better one. */ 03436 if (len == bufsize) 03437 { 03438 /* This could be the truncated length (Tru64 and IRIX have this bug), 03439 * or the real length could be coincidentally the same. Which is it? 03440 * If vsnprintf returns the truncated length, we'll go to the slow 03441 * path. */ 03442 DBUS_VA_COPY (args_copy, args); 03443 03444 if (vsnprintf (static_buf, 1, format, args_copy) == 1) 03445 len = -1; 03446 03447 va_end (args_copy); 03448 } 03449 03450 /* If vsnprintf() returned negative, we have to do more work. 03451 * HP-UX returns negative. */ 03452 while (len < 0) 03453 { 03454 char *buf; 03455 03456 bufsize *= 2; 03457 03458 buf = dbus_malloc (bufsize); 03459 03460 if (buf == NULL) 03461 return -1; 03462 03463 DBUS_VA_COPY (args_copy, args); 03464 len = vsnprintf (buf, bufsize, format, args_copy); 03465 va_end (args_copy); 03466 03467 dbus_free (buf); 03468 03469 /* If the reported length is exactly the buffer size, round up to the 03470 * next size, in case vsnprintf has been returning the truncated 03471 * length */ 03472 if (len == bufsize) 03473 len = -1; 03474 } 03475 03476 return len; 03477 } 03478 03485 const char* 03486 _dbus_get_tmpdir(void) 03487 { 03488 /* Protected by _DBUS_LOCK_sysdeps */ 03489 static const char* tmpdir = NULL; 03490 03491 if (!_DBUS_LOCK (sysdeps)) 03492 return NULL; 03493 03494 if (tmpdir == NULL) 03495 { 03496 /* TMPDIR is what glibc uses, then 03497 * glibc falls back to the P_tmpdir macro which 03498 * just expands to "/tmp" 03499 */ 03500 if (tmpdir == NULL) 03501 tmpdir = getenv("TMPDIR"); 03502 03503 /* These two env variables are probably 03504 * broken, but maybe some OS uses them? 03505 */ 03506 if (tmpdir == NULL) 03507 tmpdir = getenv("TMP"); 03508 if (tmpdir == NULL) 03509 tmpdir = getenv("TEMP"); 03510 03511 /* And this is the sane fallback. */ 03512 if (tmpdir == NULL) 03513 tmpdir = "/tmp"; 03514 } 03515 03516 _DBUS_UNLOCK (sysdeps); 03517 03518 _dbus_assert(tmpdir != NULL); 03519 03520 return tmpdir; 03521 } 03522 03523 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD) 03524 03543 static dbus_bool_t 03544 _read_subprocess_line_argv (const char *progpath, 03545 dbus_bool_t path_fallback, 03546 char * const *argv, 03547 DBusString *result, 03548 DBusError *error) 03549 { 03550 int result_pipe[2] = { -1, -1 }; 03551 int errors_pipe[2] = { -1, -1 }; 03552 pid_t pid; 03553 int ret; 03554 int status; 03555 int orig_len; 03556 03557 dbus_bool_t retval; 03558 sigset_t new_set, old_set; 03559 03560 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03561 retval = FALSE; 03562 03563 /* We need to block any existing handlers for SIGCHLD temporarily; they 03564 * will cause waitpid() below to fail. 03565 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03566 */ 03567 sigemptyset (&new_set); 03568 sigaddset (&new_set, SIGCHLD); 03569 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03570 03571 orig_len = _dbus_string_get_length (result); 03572 03573 #define READ_END 0 03574 #define WRITE_END 1 03575 if (pipe (result_pipe) < 0) 03576 { 03577 dbus_set_error (error, _dbus_error_from_errno (errno), 03578 "Failed to create a pipe to call %s: %s", 03579 progpath, _dbus_strerror (errno)); 03580 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03581 progpath, _dbus_strerror (errno)); 03582 goto out; 03583 } 03584 if (pipe (errors_pipe) < 0) 03585 { 03586 dbus_set_error (error, _dbus_error_from_errno (errno), 03587 "Failed to create a pipe to call %s: %s", 03588 progpath, _dbus_strerror (errno)); 03589 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03590 progpath, _dbus_strerror (errno)); 03591 goto out; 03592 } 03593 03594 pid = fork (); 03595 if (pid < 0) 03596 { 03597 dbus_set_error (error, _dbus_error_from_errno (errno), 03598 "Failed to fork() to call %s: %s", 03599 progpath, _dbus_strerror (errno)); 03600 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03601 progpath, _dbus_strerror (errno)); 03602 goto out; 03603 } 03604 03605 if (pid == 0) 03606 { 03607 /* child process */ 03608 int fd; 03609 03610 fd = open ("/dev/null", O_RDWR); 03611 if (fd == -1) 03612 /* huh?! can't open /dev/null? */ 03613 _exit (1); 03614 03615 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03616 03617 /* set-up stdXXX */ 03618 close (result_pipe[READ_END]); 03619 close (errors_pipe[READ_END]); 03620 03621 if (dup2 (fd, 0) == -1) /* setup stdin */ 03622 _exit (1); 03623 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */ 03624 _exit (1); 03625 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */ 03626 _exit (1); 03627 03628 _dbus_close_all (); 03629 03630 sigprocmask (SIG_SETMASK, &old_set, NULL); 03631 03632 /* If it looks fully-qualified, try execv first */ 03633 if (progpath[0] == '/') 03634 { 03635 execv (progpath, argv); 03636 /* Ok, that failed. Now if path_fallback is given, let's 03637 * try unqualified. This is mostly a hack to work 03638 * around systems which ship dbus-launch in /usr/bin 03639 * but everything else in /bin (because dbus-launch 03640 * depends on X11). 03641 */ 03642 if (path_fallback) 03643 /* We must have a slash, because we checked above */ 03644 execvp (strrchr (progpath, '/')+1, argv); 03645 } 03646 else 03647 execvp (progpath, argv); 03648 03649 /* still nothing, we failed */ 03650 _exit (1); 03651 } 03652 03653 /* parent process */ 03654 close (result_pipe[WRITE_END]); 03655 close (errors_pipe[WRITE_END]); 03656 result_pipe[WRITE_END] = -1; 03657 errors_pipe[WRITE_END] = -1; 03658 03659 ret = 0; 03660 do 03661 { 03662 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03663 } 03664 while (ret > 0); 03665 03666 /* reap the child process to avoid it lingering as zombie */ 03667 do 03668 { 03669 ret = waitpid (pid, &status, 0); 03670 } 03671 while (ret == -1 && errno == EINTR); 03672 03673 /* We succeeded if the process exited with status 0 and 03674 anything was read */ 03675 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03676 { 03677 /* The process ended with error */ 03678 DBusString error_message; 03679 if (!_dbus_string_init (&error_message)) 03680 { 03681 _DBUS_SET_OOM (error); 03682 goto out; 03683 } 03684 03685 ret = 0; 03686 do 03687 { 03688 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03689 } 03690 while (ret > 0); 03691 03692 _dbus_string_set_length (result, orig_len); 03693 if (_dbus_string_get_length (&error_message) > 0) 03694 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03695 "%s terminated abnormally with the following error: %s", 03696 progpath, _dbus_string_get_data (&error_message)); 03697 else 03698 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03699 "%s terminated abnormally without any error message", 03700 progpath); 03701 goto out; 03702 } 03703 03704 retval = TRUE; 03705 03706 out: 03707 sigprocmask (SIG_SETMASK, &old_set, NULL); 03708 03709 if (retval) 03710 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03711 else 03712 _DBUS_ASSERT_ERROR_IS_SET (error); 03713 03714 if (result_pipe[0] != -1) 03715 close (result_pipe[0]); 03716 if (result_pipe[1] != -1) 03717 close (result_pipe[1]); 03718 if (errors_pipe[0] != -1) 03719 close (errors_pipe[0]); 03720 if (errors_pipe[1] != -1) 03721 close (errors_pipe[1]); 03722 03723 return retval; 03724 } 03725 #endif 03726 03739 dbus_bool_t 03740 _dbus_get_autolaunch_address (const char *scope, 03741 DBusString *address, 03742 DBusError *error) 03743 { 03744 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03745 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03746 * but that's done elsewhere, and if it worked, this function wouldn't 03747 * be called.) */ 03748 const char *display; 03749 char *progpath; 03750 char *argv[6]; 03751 int i; 03752 DBusString uuid; 03753 dbus_bool_t retval; 03754 03755 if (_dbus_check_setuid ()) 03756 { 03757 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03758 "Unable to autolaunch when setuid"); 03759 return FALSE; 03760 } 03761 03762 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03763 retval = FALSE; 03764 03765 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03766 * dbus-launch-x11 is just going to fail. Rather than trying to 03767 * run it, we might as well bail out early with a nice error. 03768 * 03769 * This is not strictly true in a world where the user bus exists, 03770 * because dbus-launch --autolaunch knows how to connect to that - 03771 * but if we were going to connect to the user bus, we'd have done 03772 * so before trying autolaunch: in any case. */ 03773 display = _dbus_getenv ("DISPLAY"); 03774 03775 if (display == NULL || display[0] == '\0') 03776 { 03777 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03778 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03779 return FALSE; 03780 } 03781 03782 if (!_dbus_string_init (&uuid)) 03783 { 03784 _DBUS_SET_OOM (error); 03785 return FALSE; 03786 } 03787 03788 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error)) 03789 { 03790 goto out; 03791 } 03792 03793 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 03794 if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL) 03795 progpath = TEST_BUS_LAUNCH_BINARY; 03796 else 03797 #endif 03798 progpath = DBUS_BINDIR "/dbus-launch"; 03799 /* 03800 * argv[0] is always dbus-launch, that's the name what we'll 03801 * get from /proc, or ps(1), regardless what the progpath is, 03802 * see fd.o#69716 03803 */ 03804 i = 0; 03805 argv[i] = "dbus-launch"; 03806 ++i; 03807 argv[i] = "--autolaunch"; 03808 ++i; 03809 argv[i] = _dbus_string_get_data (&uuid); 03810 ++i; 03811 argv[i] = "--binary-syntax"; 03812 ++i; 03813 argv[i] = "--close-stderr"; 03814 ++i; 03815 argv[i] = NULL; 03816 ++i; 03817 03818 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03819 03820 retval = _read_subprocess_line_argv (progpath, 03821 TRUE, 03822 argv, address, error); 03823 03824 out: 03825 _dbus_string_free (&uuid); 03826 return retval; 03827 #else 03828 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03829 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03830 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03831 return FALSE; 03832 #endif 03833 } 03834 03853 dbus_bool_t 03854 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03855 dbus_bool_t create_if_not_found, 03856 DBusError *error) 03857 { 03858 DBusString filename; 03859 dbus_bool_t b; 03860 03861 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03862 03863 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03864 if (b) 03865 return TRUE; 03866 03867 dbus_error_free (error); 03868 03869 /* Fallback to the system machine ID */ 03870 _dbus_string_init_const (&filename, "/etc/machine-id"); 03871 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03872 03873 if (b) 03874 { 03875 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not 03876 * complain if that isn't possible for whatever reason */ 03877 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03878 _dbus_write_uuid_file (&filename, machine_id, NULL); 03879 03880 return TRUE; 03881 } 03882 03883 if (!create_if_not_found) 03884 return FALSE; 03885 03886 /* if none found, try to make a new one */ 03887 dbus_error_free (error); 03888 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03889 03890 if (!_dbus_generate_uuid (machine_id, error)) 03891 return FALSE; 03892 03893 return _dbus_write_uuid_file (&filename, machine_id, error); 03894 } 03895 03903 dbus_bool_t 03904 _dbus_lookup_launchd_socket (DBusString *socket_path, 03905 const char *launchd_env_var, 03906 DBusError *error) 03907 { 03908 #ifdef DBUS_ENABLE_LAUNCHD 03909 char *argv[4]; 03910 int i; 03911 03912 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03913 03914 if (_dbus_check_setuid ()) 03915 { 03916 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03917 "Unable to find launchd socket when setuid"); 03918 return FALSE; 03919 } 03920 03921 i = 0; 03922 argv[i] = "launchctl"; 03923 ++i; 03924 argv[i] = "getenv"; 03925 ++i; 03926 argv[i] = (char*)launchd_env_var; 03927 ++i; 03928 argv[i] = NULL; 03929 ++i; 03930 03931 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03932 03933 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03934 { 03935 return FALSE; 03936 } 03937 03938 /* no error, but no result either */ 03939 if (_dbus_string_get_length(socket_path) == 0) 03940 { 03941 return FALSE; 03942 } 03943 03944 /* strip the carriage-return */ 03945 _dbus_string_shorten(socket_path, 1); 03946 return TRUE; 03947 #else /* DBUS_ENABLE_LAUNCHD */ 03948 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03949 "can't lookup socket from launchd; launchd support not compiled in"); 03950 return FALSE; 03951 #endif 03952 } 03953 03954 #ifdef DBUS_ENABLE_LAUNCHD 03955 static dbus_bool_t 03956 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03957 { 03958 dbus_bool_t valid_socket; 03959 DBusString socket_path; 03960 03961 if (_dbus_check_setuid ()) 03962 { 03963 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03964 "Unable to find launchd socket when setuid"); 03965 return FALSE; 03966 } 03967 03968 if (!_dbus_string_init (&socket_path)) 03969 { 03970 _DBUS_SET_OOM (error); 03971 return FALSE; 03972 } 03973 03974 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03975 03976 if (dbus_error_is_set(error)) 03977 { 03978 _dbus_string_free(&socket_path); 03979 return FALSE; 03980 } 03981 03982 if (!valid_socket) 03983 { 03984 dbus_set_error(error, "no socket path", 03985 "launchd did not provide a socket path, " 03986 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03987 _dbus_string_free(&socket_path); 03988 return FALSE; 03989 } 03990 if (!_dbus_string_append (address, "unix:path=")) 03991 { 03992 _DBUS_SET_OOM (error); 03993 _dbus_string_free(&socket_path); 03994 return FALSE; 03995 } 03996 if (!_dbus_string_copy (&socket_path, 0, address, 03997 _dbus_string_get_length (address))) 03998 { 03999 _DBUS_SET_OOM (error); 04000 _dbus_string_free(&socket_path); 04001 return FALSE; 04002 } 04003 04004 _dbus_string_free(&socket_path); 04005 return TRUE; 04006 } 04007 #endif 04008 04009 dbus_bool_t 04010 _dbus_lookup_user_bus (dbus_bool_t *supported, 04011 DBusString *address, 04012 DBusError *error) 04013 { 04014 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR"); 04015 dbus_bool_t ret = FALSE; 04016 struct stat stbuf; 04017 DBusString user_bus_path; 04018 04019 if (runtime_dir == NULL) 04020 { 04021 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment"); 04022 *supported = FALSE; 04023 return TRUE; /* Cannot use it, but not an error */ 04024 } 04025 04026 if (!_dbus_string_init (&user_bus_path)) 04027 { 04028 _DBUS_SET_OOM (error); 04029 return FALSE; 04030 } 04031 04032 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir)) 04033 { 04034 _DBUS_SET_OOM (error); 04035 goto out; 04036 } 04037 04038 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1) 04039 { 04040 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s", 04041 _dbus_strerror (errno)); 04042 *supported = FALSE; 04043 ret = TRUE; /* Cannot use it, but not an error */ 04044 goto out; 04045 } 04046 04047 if (stbuf.st_uid != getuid ()) 04048 { 04049 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld", 04050 (long) stbuf.st_uid, (long) getuid ()); 04051 *supported = FALSE; 04052 ret = TRUE; /* Cannot use it, but not an error */ 04053 goto out; 04054 } 04055 04056 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK) 04057 { 04058 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo", 04059 (long) stbuf.st_mode); 04060 *supported = FALSE; 04061 ret = TRUE; /* Cannot use it, but not an error */ 04062 goto out; 04063 } 04064 04065 if (!_dbus_string_append (address, "unix:path=") || 04066 !_dbus_address_append_escaped (address, &user_bus_path)) 04067 { 04068 _DBUS_SET_OOM (error); 04069 goto out; 04070 } 04071 04072 *supported = TRUE; 04073 ret = TRUE; 04074 04075 out: 04076 _dbus_string_free (&user_bus_path); 04077 return ret; 04078 } 04079 04099 dbus_bool_t 04100 _dbus_lookup_session_address (dbus_bool_t *supported, 04101 DBusString *address, 04102 DBusError *error) 04103 { 04104 #ifdef DBUS_ENABLE_LAUNCHD 04105 *supported = TRUE; 04106 return _dbus_lookup_session_address_launchd (address, error); 04107 #else 04108 *supported = FALSE; 04109 04110 if (!_dbus_lookup_user_bus (supported, address, error)) 04111 return FALSE; 04112 else if (*supported) 04113 return TRUE; 04114 04115 /* On non-Mac Unix platforms, if the session address isn't already 04116 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the 04117 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the 04118 * autolaunch: global default; see init_session_address in 04119 * dbus/dbus-bus.c. */ 04120 return TRUE; 04121 #endif 04122 } 04123 04131 void 04132 _dbus_flush_caches (void) 04133 { 04134 _dbus_user_database_flush_system (); 04135 } 04136 04150 dbus_bool_t 04151 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 04152 DBusCredentials *credentials) 04153 { 04154 DBusString homedir; 04155 DBusString dotdir; 04156 dbus_uid_t uid; 04157 04158 _dbus_assert (credentials != NULL); 04159 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 04160 04161 if (!_dbus_string_init (&homedir)) 04162 return FALSE; 04163 04164 uid = _dbus_credentials_get_unix_uid (credentials); 04165 _dbus_assert (uid != DBUS_UID_UNSET); 04166 04167 if (!_dbus_homedir_from_uid (uid, &homedir)) 04168 goto failed; 04169 04170 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 04171 { 04172 const char *override; 04173 04174 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 04175 if (override != NULL && *override != '\0') 04176 { 04177 _dbus_string_set_length (&homedir, 0); 04178 if (!_dbus_string_append (&homedir, override)) 04179 goto failed; 04180 04181 _dbus_verbose ("Using fake homedir for testing: %s\n", 04182 _dbus_string_get_const_data (&homedir)); 04183 } 04184 else 04185 { 04186 /* Not strictly thread-safe, but if we fail at thread-safety here, 04187 * the worst that will happen is some extra warnings. */ 04188 static dbus_bool_t already_warned = FALSE; 04189 if (!already_warned) 04190 { 04191 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 04192 already_warned = TRUE; 04193 } 04194 } 04195 } 04196 #endif 04197 04198 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 04199 if (!_dbus_concat_dir_and_file (&homedir, 04200 &dotdir)) 04201 goto failed; 04202 04203 if (!_dbus_string_copy (&homedir, 0, 04204 directory, _dbus_string_get_length (directory))) { 04205 goto failed; 04206 } 04207 04208 _dbus_string_free (&homedir); 04209 return TRUE; 04210 04211 failed: 04212 _dbus_string_free (&homedir); 04213 return FALSE; 04214 } 04215 04216 //PENDING(kdab) docs 04217 dbus_bool_t 04218 _dbus_daemon_publish_session_bus_address (const char* addr, 04219 const char *scope) 04220 { 04221 return TRUE; 04222 } 04223 04224 //PENDING(kdab) docs 04225 void 04226 _dbus_daemon_unpublish_session_bus_address (void) 04227 { 04228 04229 } 04230 04237 dbus_bool_t 04238 _dbus_get_is_errno_eagain_or_ewouldblock (int e) 04239 { 04240 return e == EAGAIN || e == EWOULDBLOCK; 04241 } 04242 04250 dbus_bool_t 04251 _dbus_delete_directory (const DBusString *filename, 04252 DBusError *error) 04253 { 04254 const char *filename_c; 04255 04256 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 04257 04258 filename_c = _dbus_string_get_const_data (filename); 04259 04260 if (rmdir (filename_c) != 0) 04261 { 04262 dbus_set_error (error, DBUS_ERROR_FAILED, 04263 "Failed to remove directory %s: %s\n", 04264 filename_c, _dbus_strerror (errno)); 04265 return FALSE; 04266 } 04267 04268 return TRUE; 04269 } 04270 04278 dbus_bool_t 04279 _dbus_socket_can_pass_unix_fd (DBusSocket fd) 04280 { 04281 #ifdef SCM_RIGHTS 04282 union { 04283 struct sockaddr sa; 04284 struct sockaddr_storage storage; 04285 struct sockaddr_un un; 04286 } sa_buf; 04287 04288 socklen_t sa_len = sizeof(sa_buf); 04289 04290 _DBUS_ZERO(sa_buf); 04291 04292 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0) 04293 return FALSE; 04294 04295 return sa_buf.sa.sa_family == AF_UNIX; 04296 04297 #else 04298 return FALSE; 04299 04300 #endif 04301 } 04302 04307 void 04308 _dbus_close_all (void) 04309 { 04310 int maxfds, i; 04311 04312 #ifdef __linux__ 04313 DIR *d; 04314 04315 /* On Linux we can optimize this a bit if /proc is available. If it 04316 isn't available, fall back to the brute force way. */ 04317 04318 d = opendir ("/proc/self/fd"); 04319 if (d) 04320 { 04321 for (;;) 04322 { 04323 struct dirent buf, *de; 04324 int k, fd; 04325 long l; 04326 char *e = NULL; 04327 04328 k = readdir_r (d, &buf, &de); 04329 if (k != 0 || !de) 04330 break; 04331 04332 if (de->d_name[0] == '.') 04333 continue; 04334 04335 errno = 0; 04336 l = strtol (de->d_name, &e, 10); 04337 if (errno != 0 || e == NULL || *e != '\0') 04338 continue; 04339 04340 fd = (int) l; 04341 if (fd < 3) 04342 continue; 04343 04344 if (fd == dirfd (d)) 04345 continue; 04346 04347 close (fd); 04348 } 04349 04350 closedir (d); 04351 return; 04352 } 04353 #endif 04354 04355 maxfds = sysconf (_SC_OPEN_MAX); 04356 04357 /* Pick something reasonable if for some reason sysconf says 04358 * unlimited. 04359 */ 04360 if (maxfds < 0) 04361 maxfds = 1024; 04362 04363 /* close all inherited fds */ 04364 for (i = 3; i < maxfds; i++) 04365 close (i); 04366 } 04367 04377 dbus_bool_t 04378 _dbus_check_setuid (void) 04379 { 04380 /* TODO: get __libc_enable_secure exported from glibc. 04381 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1 04382 */ 04383 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE) 04384 { 04385 /* See glibc/include/unistd.h */ 04386 extern int __libc_enable_secure; 04387 return __libc_enable_secure; 04388 } 04389 #elif defined(HAVE_ISSETUGID) 04390 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */ 04391 return issetugid (); 04392 #else 04393 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ 04394 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ 04395 04396 /* We call into this function from _dbus_threads_init_platform_specific() 04397 * to make sure these are initialized before we start threading. */ 04398 static dbus_bool_t check_setuid_initialised; 04399 static dbus_bool_t is_setuid; 04400 04401 if (_DBUS_UNLIKELY (!check_setuid_initialised)) 04402 { 04403 #ifdef HAVE_GETRESUID 04404 if (getresuid (&ruid, &euid, &suid) != 0 || 04405 getresgid (&rgid, &egid, &sgid) != 0) 04406 #endif /* HAVE_GETRESUID */ 04407 { 04408 suid = ruid = getuid (); 04409 sgid = rgid = getgid (); 04410 euid = geteuid (); 04411 egid = getegid (); 04412 } 04413 04414 check_setuid_initialised = TRUE; 04415 is_setuid = (ruid != euid || ruid != suid || 04416 rgid != egid || rgid != sgid); 04417 04418 } 04419 return is_setuid; 04420 #endif 04421 } 04422 04430 dbus_bool_t 04431 _dbus_append_address_from_socket (DBusSocket fd, 04432 DBusString *address, 04433 DBusError *error) 04434 { 04435 union { 04436 struct sockaddr sa; 04437 struct sockaddr_storage storage; 04438 struct sockaddr_un un; 04439 struct sockaddr_in ipv4; 04440 struct sockaddr_in6 ipv6; 04441 } socket; 04442 char hostip[INET6_ADDRSTRLEN]; 04443 int size = sizeof (socket); 04444 DBusString path_str; 04445 04446 if (getsockname (fd.fd, &socket.sa, &size)) 04447 goto err; 04448 04449 switch (socket.sa.sa_family) 04450 { 04451 case AF_UNIX: 04452 if (socket.un.sun_path[0]=='\0') 04453 { 04454 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1])); 04455 if (_dbus_string_append (address, "unix:abstract=") && 04456 _dbus_address_append_escaped (address, &path_str)) 04457 return TRUE; 04458 } 04459 else 04460 { 04461 _dbus_string_init_const (&path_str, socket.un.sun_path); 04462 if (_dbus_string_append (address, "unix:path=") && 04463 _dbus_address_append_escaped (address, &path_str)) 04464 return TRUE; 04465 } 04466 break; 04467 case AF_INET: 04468 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip))) 04469 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u", 04470 hostip, ntohs (socket.ipv4.sin_port))) 04471 return TRUE; 04472 break; 04473 #ifdef AF_INET6 04474 case AF_INET6: 04475 _dbus_string_init_const (&path_str, hostip); 04476 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip))) 04477 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=", 04478 ntohs (socket.ipv6.sin6_port)) && 04479 _dbus_address_append_escaped (address, &path_str)) 04480 return TRUE; 04481 break; 04482 #endif 04483 default: 04484 dbus_set_error (error, 04485 _dbus_error_from_errno (EINVAL), 04486 "Failed to read address from socket: Unknown socket type."); 04487 return FALSE; 04488 } 04489 err: 04490 dbus_set_error (error, 04491 _dbus_error_from_errno (errno), 04492 "Failed to open socket: %s", 04493 _dbus_strerror (errno)); 04494 return FALSE; 04495 } 04496 04497 int 04498 _dbus_save_socket_errno (void) 04499 { 04500 return errno; 04501 } 04502 04503 void 04504 _dbus_restore_socket_errno (int saved_errno) 04505 { 04506 errno = saved_errno; 04507 } 04508 04509 /* tests in dbus-sysdeps-util.c */