D-Bus 1.2.24
|
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 #define _GNU_SOURCE 00026 00027 #include "dbus-internals.h" 00028 #include "dbus-sysdeps.h" 00029 #include "dbus-sysdeps-unix.h" 00030 #include "dbus-threads.h" 00031 #include "dbus-protocol.h" 00032 #include "dbus-transport.h" 00033 #include "dbus-string.h" 00034 #include "dbus-userdb.h" 00035 #include "dbus-list.h" 00036 #include "dbus-credentials.h" 00037 00038 #include <sys/types.h> 00039 #include <stdlib.h> 00040 #include <string.h> 00041 #include <signal.h> 00042 #include <unistd.h> 00043 #include <stdio.h> 00044 #include <fcntl.h> 00045 #include <sys/socket.h> 00046 #include <dirent.h> 00047 #include <sys/un.h> 00048 #include <pwd.h> 00049 #include <time.h> 00050 #include <locale.h> 00051 #include <sys/time.h> 00052 #include <sys/stat.h> 00053 #include <sys/wait.h> 00054 #include <netinet/in.h> 00055 #include <netdb.h> 00056 #include <grp.h> 00057 00058 #ifdef HAVE_ERRNO_H 00059 #include <errno.h> 00060 #endif 00061 #ifdef HAVE_WRITEV 00062 #include <sys/uio.h> 00063 #endif 00064 #ifdef HAVE_POLL 00065 #include <sys/poll.h> 00066 #endif 00067 #ifdef HAVE_BACKTRACE 00068 #include <execinfo.h> 00069 #endif 00070 #ifdef HAVE_GETPEERUCRED 00071 #include <ucred.h> 00072 #endif 00073 00074 #ifdef HAVE_ADT 00075 #include <bsm/adt.h> 00076 #endif 00077 00078 #ifndef O_BINARY 00079 #define O_BINARY 0 00080 #endif 00081 00082 #ifndef AI_ADDRCONFIG 00083 #define AI_ADDRCONFIG 0 00084 #endif 00085 00086 #ifndef HAVE_SOCKLEN_T 00087 #define socklen_t int 00088 #endif 00089 00090 static dbus_bool_t 00091 _dbus_open_socket (int *fd_p, 00092 int domain, 00093 int type, 00094 int protocol, 00095 DBusError *error) 00096 { 00097 *fd_p = socket (domain, type, protocol); 00098 if (*fd_p >= 0) 00099 { 00100 _dbus_verbose ("socket fd %d opened\n", *fd_p); 00101 return TRUE; 00102 } 00103 else 00104 { 00105 dbus_set_error(error, 00106 _dbus_error_from_errno (errno), 00107 "Failed to open socket: %s", 00108 _dbus_strerror (errno)); 00109 return FALSE; 00110 } 00111 } 00112 00113 dbus_bool_t 00114 _dbus_open_tcp_socket (int *fd, 00115 DBusError *error) 00116 { 00117 return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error); 00118 } 00119 00127 dbus_bool_t 00128 _dbus_open_unix_socket (int *fd, 00129 DBusError *error) 00130 { 00131 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error); 00132 } 00133 00142 dbus_bool_t 00143 _dbus_close_socket (int fd, 00144 DBusError *error) 00145 { 00146 return _dbus_close (fd, error); 00147 } 00148 00158 int 00159 _dbus_read_socket (int fd, 00160 DBusString *buffer, 00161 int count) 00162 { 00163 return _dbus_read (fd, buffer, count); 00164 } 00165 00176 int 00177 _dbus_write_socket (int fd, 00178 const DBusString *buffer, 00179 int start, 00180 int len) 00181 { 00182 return _dbus_write (fd, buffer, start, len); 00183 } 00184 00195 int 00196 _dbus_pipe_write (DBusPipe *pipe, 00197 const DBusString *buffer, 00198 int start, 00199 int len, 00200 DBusError *error) 00201 { 00202 int written; 00203 00204 written = _dbus_write (pipe->fd_or_handle, buffer, start, len); 00205 if (written < 0) 00206 { 00207 dbus_set_error (error, DBUS_ERROR_FAILED, 00208 "Writing to pipe: %s\n", 00209 _dbus_strerror (errno)); 00210 } 00211 return written; 00212 } 00213 00221 int 00222 _dbus_pipe_close (DBusPipe *pipe, 00223 DBusError *error) 00224 { 00225 if (_dbus_close (pipe->fd_or_handle, error) < 0) 00226 { 00227 return -1; 00228 } 00229 else 00230 { 00231 _dbus_pipe_invalidate (pipe); 00232 return 0; 00233 } 00234 } 00235 00249 int 00250 _dbus_write_socket_two (int fd, 00251 const DBusString *buffer1, 00252 int start1, 00253 int len1, 00254 const DBusString *buffer2, 00255 int start2, 00256 int len2) 00257 { 00258 return _dbus_write_two (fd, buffer1, start1, len1, 00259 buffer2, start2, len2); 00260 } 00261 00262 00279 int 00280 _dbus_read (int fd, 00281 DBusString *buffer, 00282 int count) 00283 { 00284 int bytes_read; 00285 int start; 00286 char *data; 00287 00288 _dbus_assert (count >= 0); 00289 00290 start = _dbus_string_get_length (buffer); 00291 00292 if (!_dbus_string_lengthen (buffer, count)) 00293 { 00294 errno = ENOMEM; 00295 return -1; 00296 } 00297 00298 data = _dbus_string_get_data_len (buffer, start, count); 00299 00300 again: 00301 00302 bytes_read = read (fd, data, count); 00303 00304 if (bytes_read < 0) 00305 { 00306 if (errno == EINTR) 00307 goto again; 00308 else 00309 { 00310 /* put length back (note that this doesn't actually realloc anything) */ 00311 _dbus_string_set_length (buffer, start); 00312 return -1; 00313 } 00314 } 00315 else 00316 { 00317 /* put length back (doesn't actually realloc) */ 00318 _dbus_string_set_length (buffer, start + bytes_read); 00319 00320 #if 0 00321 if (bytes_read > 0) 00322 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00323 #endif 00324 00325 return bytes_read; 00326 } 00327 } 00328 00339 int 00340 _dbus_write (int fd, 00341 const DBusString *buffer, 00342 int start, 00343 int len) 00344 { 00345 const char *data; 00346 int bytes_written; 00347 00348 data = _dbus_string_get_const_data_len (buffer, start, len); 00349 00350 again: 00351 00352 bytes_written = write (fd, data, len); 00353 00354 if (bytes_written < 0 && errno == EINTR) 00355 goto again; 00356 00357 #if 0 00358 if (bytes_written > 0) 00359 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00360 #endif 00361 00362 return bytes_written; 00363 } 00364 00385 int 00386 _dbus_write_two (int fd, 00387 const DBusString *buffer1, 00388 int start1, 00389 int len1, 00390 const DBusString *buffer2, 00391 int start2, 00392 int len2) 00393 { 00394 _dbus_assert (buffer1 != NULL); 00395 _dbus_assert (start1 >= 0); 00396 _dbus_assert (start2 >= 0); 00397 _dbus_assert (len1 >= 0); 00398 _dbus_assert (len2 >= 0); 00399 00400 #ifdef HAVE_WRITEV 00401 { 00402 struct iovec vectors[2]; 00403 const char *data1; 00404 const char *data2; 00405 int bytes_written; 00406 00407 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00408 00409 if (buffer2 != NULL) 00410 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00411 else 00412 { 00413 data2 = NULL; 00414 start2 = 0; 00415 len2 = 0; 00416 } 00417 00418 vectors[0].iov_base = (char*) data1; 00419 vectors[0].iov_len = len1; 00420 vectors[1].iov_base = (char*) data2; 00421 vectors[1].iov_len = len2; 00422 00423 again: 00424 00425 bytes_written = writev (fd, 00426 vectors, 00427 data2 ? 2 : 1); 00428 00429 if (bytes_written < 0 && errno == EINTR) 00430 goto again; 00431 00432 return bytes_written; 00433 } 00434 #else /* HAVE_WRITEV */ 00435 { 00436 int ret1; 00437 00438 ret1 = _dbus_write (fd, buffer1, start1, len1); 00439 if (ret1 == len1 && buffer2 != NULL) 00440 { 00441 ret2 = _dbus_write (fd, buffer2, start2, len2); 00442 if (ret2 < 0) 00443 ret2 = 0; /* we can't report an error as the first write was OK */ 00444 00445 return ret1 + ret2; 00446 } 00447 else 00448 return ret1; 00449 } 00450 #endif /* !HAVE_WRITEV */ 00451 } 00452 00453 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00454 00482 int 00483 _dbus_connect_unix_socket (const char *path, 00484 dbus_bool_t abstract, 00485 DBusError *error) 00486 { 00487 int fd; 00488 size_t path_len; 00489 struct sockaddr_un addr; 00490 00491 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00492 00493 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00494 path, abstract); 00495 00496 00497 if (!_dbus_open_unix_socket (&fd, error)) 00498 { 00499 _DBUS_ASSERT_ERROR_IS_SET(error); 00500 return -1; 00501 } 00502 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00503 00504 _DBUS_ZERO (addr); 00505 addr.sun_family = AF_UNIX; 00506 path_len = strlen (path); 00507 00508 if (abstract) 00509 { 00510 #ifdef HAVE_ABSTRACT_SOCKETS 00511 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00512 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00513 00514 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00515 { 00516 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00517 "Abstract socket name too long\n"); 00518 _dbus_close (fd, NULL); 00519 return -1; 00520 } 00521 00522 strncpy (&addr.sun_path[1], path, path_len); 00523 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00524 #else /* HAVE_ABSTRACT_SOCKETS */ 00525 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00526 "Operating system does not support abstract socket namespace\n"); 00527 _dbus_close (fd, NULL); 00528 return -1; 00529 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00530 } 00531 else 00532 { 00533 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00534 { 00535 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00536 "Socket name too long\n"); 00537 _dbus_close (fd, NULL); 00538 return -1; 00539 } 00540 00541 strncpy (addr.sun_path, path, path_len); 00542 } 00543 00544 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00545 { 00546 dbus_set_error (error, 00547 _dbus_error_from_errno (errno), 00548 "Failed to connect to socket %s: %s", 00549 path, _dbus_strerror (errno)); 00550 00551 _dbus_close (fd, NULL); 00552 fd = -1; 00553 00554 return -1; 00555 } 00556 00557 if (!_dbus_set_fd_nonblocking (fd, error)) 00558 { 00559 _DBUS_ASSERT_ERROR_IS_SET (error); 00560 00561 _dbus_close (fd, NULL); 00562 fd = -1; 00563 00564 return -1; 00565 } 00566 00567 return fd; 00568 } 00569 00579 static dbus_bool_t 00580 _dbus_set_local_creds (int fd, dbus_bool_t on) 00581 { 00582 dbus_bool_t retval = TRUE; 00583 00584 #if defined(HAVE_CMSGCRED) 00585 /* NOOP just to make sure only one codepath is used 00586 * and to prefer CMSGCRED 00587 */ 00588 #elif defined(LOCAL_CREDS) 00589 int val = on ? 1 : 0; 00590 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) 00591 { 00592 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); 00593 retval = FALSE; 00594 } 00595 else 00596 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", 00597 on ? "enabled" : "disabled", fd); 00598 #endif 00599 00600 return retval; 00601 } 00602 00618 int 00619 _dbus_listen_unix_socket (const char *path, 00620 dbus_bool_t abstract, 00621 DBusError *error) 00622 { 00623 int listen_fd; 00624 struct sockaddr_un addr; 00625 size_t path_len; 00626 00627 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00628 00629 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 00630 path, abstract); 00631 00632 if (!_dbus_open_unix_socket (&listen_fd, error)) 00633 { 00634 _DBUS_ASSERT_ERROR_IS_SET(error); 00635 return -1; 00636 } 00637 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00638 00639 _DBUS_ZERO (addr); 00640 addr.sun_family = AF_UNIX; 00641 path_len = strlen (path); 00642 00643 if (abstract) 00644 { 00645 #ifdef HAVE_ABSTRACT_SOCKETS 00646 /* remember that abstract names aren't nul-terminated so we rely 00647 * on sun_path being filled in with zeroes above. 00648 */ 00649 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00650 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00651 00652 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00653 { 00654 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00655 "Abstract socket name too long\n"); 00656 _dbus_close (listen_fd, NULL); 00657 return -1; 00658 } 00659 00660 strncpy (&addr.sun_path[1], path, path_len); 00661 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00662 #else /* HAVE_ABSTRACT_SOCKETS */ 00663 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00664 "Operating system does not support abstract socket namespace\n"); 00665 _dbus_close (listen_fd, NULL); 00666 return -1; 00667 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00668 } 00669 else 00670 { 00671 /* Discussed security implications of this with Nalin, 00672 * and we couldn't think of where it would kick our ass, but 00673 * it still seems a bit sucky. It also has non-security suckage; 00674 * really we'd prefer to exit if the socket is already in use. 00675 * But there doesn't seem to be a good way to do this. 00676 * 00677 * Just to be extra careful, I threw in the stat() - clearly 00678 * the stat() can't *fix* any security issue, but it at least 00679 * avoids inadvertent/accidental data loss. 00680 */ 00681 { 00682 struct stat sb; 00683 00684 if (stat (path, &sb) == 0 && 00685 S_ISSOCK (sb.st_mode)) 00686 unlink (path); 00687 } 00688 00689 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00690 { 00691 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00692 "Abstract socket name too long\n"); 00693 _dbus_close (listen_fd, NULL); 00694 return -1; 00695 } 00696 00697 strncpy (addr.sun_path, path, path_len); 00698 } 00699 00700 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00701 { 00702 dbus_set_error (error, _dbus_error_from_errno (errno), 00703 "Failed to bind socket \"%s\": %s", 00704 path, _dbus_strerror (errno)); 00705 _dbus_close (listen_fd, NULL); 00706 return -1; 00707 } 00708 00709 if (listen (listen_fd, 30 /* backlog */) < 0) 00710 { 00711 dbus_set_error (error, _dbus_error_from_errno (errno), 00712 "Failed to listen on socket \"%s\": %s", 00713 path, _dbus_strerror (errno)); 00714 _dbus_close (listen_fd, NULL); 00715 return -1; 00716 } 00717 00718 if (!_dbus_set_local_creds (listen_fd, TRUE)) 00719 { 00720 dbus_set_error (error, _dbus_error_from_errno (errno), 00721 "Failed to enable LOCAL_CREDS on socket \"%s\": %s", 00722 path, _dbus_strerror (errno)); 00723 close (listen_fd); 00724 return -1; 00725 } 00726 00727 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 00728 { 00729 _DBUS_ASSERT_ERROR_IS_SET (error); 00730 _dbus_close (listen_fd, NULL); 00731 return -1; 00732 } 00733 00734 /* Try opening up the permissions, but if we can't, just go ahead 00735 * and continue, maybe it will be good enough. 00736 */ 00737 if (!abstract && chmod (path, 0777) < 0) 00738 _dbus_warn ("Could not set mode 0777 on socket %s\n", 00739 path); 00740 00741 return listen_fd; 00742 } 00743 00755 int 00756 _dbus_connect_tcp_socket (const char *host, 00757 const char *port, 00758 const char *family, 00759 DBusError *error) 00760 { 00761 int fd = -1, res; 00762 struct addrinfo hints; 00763 struct addrinfo *ai, *tmp; 00764 00765 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00766 00767 if (!_dbus_open_tcp_socket (&fd, error)) 00768 { 00769 _DBUS_ASSERT_ERROR_IS_SET(error); 00770 return -1; 00771 } 00772 00773 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00774 00775 _DBUS_ZERO (hints); 00776 00777 if (!family) 00778 hints.ai_family = AF_UNSPEC; 00779 else if (!strcmp(family, "ipv4")) 00780 hints.ai_family = AF_INET; 00781 else if (!strcmp(family, "ipv6")) 00782 hints.ai_family = AF_INET6; 00783 else 00784 { 00785 dbus_set_error (error, 00786 _dbus_error_from_errno (errno), 00787 "Unknown address family %s", family); 00788 return -1; 00789 } 00790 hints.ai_protocol = IPPROTO_TCP; 00791 hints.ai_socktype = SOCK_STREAM; 00792 hints.ai_flags = AI_ADDRCONFIG; 00793 00794 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 00795 { 00796 dbus_set_error (error, 00797 _dbus_error_from_errno (errno), 00798 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 00799 host, port, gai_strerror(res), res); 00800 _dbus_close (fd, NULL); 00801 return -1; 00802 } 00803 00804 tmp = ai; 00805 while (tmp) 00806 { 00807 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 00808 { 00809 freeaddrinfo(ai); 00810 _DBUS_ASSERT_ERROR_IS_SET(error); 00811 return -1; 00812 } 00813 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00814 00815 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 00816 { 00817 _dbus_close(fd, NULL); 00818 fd = -1; 00819 tmp = tmp->ai_next; 00820 continue; 00821 } 00822 00823 break; 00824 } 00825 freeaddrinfo(ai); 00826 00827 if (fd == -1) 00828 { 00829 dbus_set_error (error, 00830 _dbus_error_from_errno (errno), 00831 "Failed to connect to socket \"%s:%s\" %s", 00832 host, port, _dbus_strerror(errno)); 00833 return -1; 00834 } 00835 00836 00837 if (!_dbus_set_fd_nonblocking (fd, error)) 00838 { 00839 _dbus_close (fd, NULL); 00840 fd = -1; 00841 00842 return -1; 00843 } 00844 00845 return fd; 00846 } 00847 00862 int 00863 _dbus_listen_tcp_socket (const char *host, 00864 const char *port, 00865 const char *family, 00866 DBusString *retport, 00867 int **fds_p, 00868 DBusError *error) 00869 { 00870 int nlisten_fd = 0, *listen_fd = NULL, res, i; 00871 struct addrinfo hints; 00872 struct addrinfo *ai, *tmp; 00873 00874 *fds_p = NULL; 00875 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00876 00877 _DBUS_ZERO (hints); 00878 00879 if (!family) 00880 hints.ai_family = AF_UNSPEC; 00881 else if (!strcmp(family, "ipv4")) 00882 hints.ai_family = AF_INET; 00883 else if (!strcmp(family, "ipv6")) 00884 hints.ai_family = AF_INET6; 00885 else 00886 { 00887 dbus_set_error (error, 00888 _dbus_error_from_errno (errno), 00889 "Unknown address family %s", family); 00890 return -1; 00891 } 00892 00893 hints.ai_protocol = IPPROTO_TCP; 00894 hints.ai_socktype = SOCK_STREAM; 00895 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 00896 00897 redo_lookup_with_port: 00898 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 00899 { 00900 dbus_set_error (error, 00901 _dbus_error_from_errno (errno), 00902 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 00903 host ? host : "*", port, gai_strerror(res), res); 00904 return -1; 00905 } 00906 00907 tmp = ai; 00908 while (tmp) 00909 { 00910 int fd = -1, *newlisten_fd; 00911 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 00912 { 00913 _DBUS_ASSERT_ERROR_IS_SET(error); 00914 goto failed; 00915 } 00916 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00917 00918 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 00919 { 00920 _dbus_close(fd, NULL); 00921 if (errno == EADDRINUSE) 00922 { 00923 /* Depending on kernel policy, it may or may not 00924 be neccessary to bind to both IPv4 & 6 addresses 00925 so ignore EADDRINUSE here */ 00926 tmp = tmp->ai_next; 00927 continue; 00928 } 00929 dbus_set_error (error, _dbus_error_from_errno (errno), 00930 "Failed to bind socket \"%s:%s\": %s", 00931 host ? host : "*", port, _dbus_strerror (errno)); 00932 goto failed; 00933 } 00934 00935 if (listen (fd, 30 /* backlog */) < 0) 00936 { 00937 _dbus_close (fd, NULL); 00938 dbus_set_error (error, _dbus_error_from_errno (errno), 00939 "Failed to listen on socket \"%s:%s\": %s", 00940 host ? host : "*", port, _dbus_strerror (errno)); 00941 goto failed; 00942 } 00943 00944 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 00945 if (!newlisten_fd) 00946 { 00947 _dbus_close (fd, NULL); 00948 dbus_set_error (error, _dbus_error_from_errno (errno), 00949 "Failed to allocate file handle array: %s", 00950 _dbus_strerror (errno)); 00951 goto failed; 00952 } 00953 listen_fd = newlisten_fd; 00954 listen_fd[nlisten_fd] = fd; 00955 nlisten_fd++; 00956 00957 if (!_dbus_string_get_length(retport)) 00958 { 00959 /* If the user didn't specify a port, or used 0, then 00960 the kernel chooses a port. After the first address 00961 is bound to, we need to force all remaining addresses 00962 to use the same port */ 00963 if (!port || !strcmp(port, "0")) 00964 { 00965 struct sockaddr_storage addr; 00966 socklen_t addrlen; 00967 char portbuf[50]; 00968 00969 addrlen = sizeof(addr); 00970 getsockname(fd, (struct sockaddr*) &addr, &addrlen); 00971 00972 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0, 00973 portbuf, sizeof(portbuf), 00974 NI_NUMERICHOST)) != 0) 00975 { 00976 dbus_set_error (error, _dbus_error_from_errno (errno), 00977 "Failed to resolve port \"%s:%s\": %s (%s)", 00978 host ? host : "*", port, gai_strerror(res), res); 00979 goto failed; 00980 } 00981 if (!_dbus_string_append(retport, portbuf)) 00982 { 00983 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00984 goto failed; 00985 } 00986 00987 /* Release current address list & redo lookup */ 00988 port = _dbus_string_get_const_data(retport); 00989 freeaddrinfo(ai); 00990 goto redo_lookup_with_port; 00991 } 00992 else 00993 { 00994 if (!_dbus_string_append(retport, port)) 00995 { 00996 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00997 goto failed; 00998 } 00999 } 01000 } 01001 01002 tmp = tmp->ai_next; 01003 } 01004 freeaddrinfo(ai); 01005 ai = NULL; 01006 01007 if (!nlisten_fd) 01008 { 01009 errno = EADDRINUSE; 01010 dbus_set_error (error, _dbus_error_from_errno (errno), 01011 "Failed to bind socket \"%s:%s\": %s", 01012 host ? host : "*", port, _dbus_strerror (errno)); 01013 return -1; 01014 } 01015 01016 for (i = 0 ; i < nlisten_fd ; i++) 01017 { 01018 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01019 { 01020 goto failed; 01021 } 01022 } 01023 01024 *fds_p = listen_fd; 01025 01026 return nlisten_fd; 01027 01028 failed: 01029 if (ai) 01030 freeaddrinfo(ai); 01031 for (i = 0 ; i < nlisten_fd ; i++) 01032 _dbus_close(listen_fd[i], NULL); 01033 dbus_free(listen_fd); 01034 return -1; 01035 } 01036 01037 static dbus_bool_t 01038 write_credentials_byte (int server_fd, 01039 DBusError *error) 01040 { 01041 int bytes_written; 01042 char buf[1] = { '\0' }; 01043 #if defined(HAVE_CMSGCRED) 01044 union { 01045 struct cmsghdr hdr; 01046 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01047 } cmsg; 01048 struct iovec iov; 01049 struct msghdr msg; 01050 iov.iov_base = buf; 01051 iov.iov_len = 1; 01052 01053 memset (&msg, 0, sizeof (msg)); 01054 msg.msg_iov = &iov; 01055 msg.msg_iovlen = 1; 01056 01057 msg.msg_control = (caddr_t) &cmsg; 01058 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01059 memset (&cmsg, 0, sizeof (cmsg)); 01060 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01061 cmsg.hdr.cmsg_level = SOL_SOCKET; 01062 cmsg.hdr.cmsg_type = SCM_CREDS; 01063 #endif 01064 01065 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01066 01067 again: 01068 01069 #if defined(HAVE_CMSGCRED) 01070 bytes_written = sendmsg (server_fd, &msg, 0); 01071 #else 01072 bytes_written = write (server_fd, buf, 1); 01073 #endif 01074 01075 if (bytes_written < 0 && errno == EINTR) 01076 goto again; 01077 01078 if (bytes_written < 0) 01079 { 01080 dbus_set_error (error, _dbus_error_from_errno (errno), 01081 "Failed to write credentials byte: %s", 01082 _dbus_strerror (errno)); 01083 return FALSE; 01084 } 01085 else if (bytes_written == 0) 01086 { 01087 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01088 "wrote zero bytes writing credentials byte"); 01089 return FALSE; 01090 } 01091 else 01092 { 01093 _dbus_assert (bytes_written == 1); 01094 _dbus_verbose ("wrote credentials byte\n"); 01095 return TRUE; 01096 } 01097 } 01098 01120 dbus_bool_t 01121 _dbus_read_credentials_socket (int client_fd, 01122 DBusCredentials *credentials, 01123 DBusError *error) 01124 { 01125 struct msghdr msg; 01126 struct iovec iov; 01127 char buf; 01128 dbus_uid_t uid_read; 01129 dbus_pid_t pid_read; 01130 int bytes_read; 01131 01132 #ifdef HAVE_CMSGCRED 01133 union { 01134 struct cmsghdr hdr; 01135 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01136 } cmsg; 01137 01138 #elif defined(LOCAL_CREDS) 01139 struct { 01140 struct cmsghdr hdr; 01141 struct sockcred cred; 01142 } cmsg; 01143 #endif 01144 01145 uid_read = DBUS_UID_UNSET; 01146 pid_read = DBUS_PID_UNSET; 01147 01148 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01149 01150 /* The POSIX spec certainly doesn't promise this, but 01151 * we need these assertions to fail as soon as we're wrong about 01152 * it so we can do the porting fixups 01153 */ 01154 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01155 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01156 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01157 01158 _dbus_credentials_clear (credentials); 01159 01160 /* Systems supporting LOCAL_CREDS are configured to have this feature 01161 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01162 * the connection. Therefore, the received message must carry the 01163 * credentials information without doing anything special. 01164 */ 01165 01166 iov.iov_base = &buf; 01167 iov.iov_len = 1; 01168 01169 memset (&msg, 0, sizeof (msg)); 01170 msg.msg_iov = &iov; 01171 msg.msg_iovlen = 1; 01172 01173 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01174 memset (&cmsg, 0, sizeof (cmsg)); 01175 msg.msg_control = (caddr_t) &cmsg; 01176 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01177 #endif 01178 01179 again: 01180 bytes_read = recvmsg (client_fd, &msg, 0); 01181 01182 if (bytes_read < 0) 01183 { 01184 if (errno == EINTR) 01185 goto again; 01186 01187 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01188 * normally only call read_credentials if the socket was ready 01189 * for reading 01190 */ 01191 01192 dbus_set_error (error, _dbus_error_from_errno (errno), 01193 "Failed to read credentials byte: %s", 01194 _dbus_strerror (errno)); 01195 return FALSE; 01196 } 01197 else if (bytes_read == 0) 01198 { 01199 /* this should not happen unless we are using recvmsg wrong, 01200 * so is essentially here for paranoia 01201 */ 01202 dbus_set_error (error, DBUS_ERROR_FAILED, 01203 "Failed to read credentials byte (zero-length read)"); 01204 return FALSE; 01205 } 01206 else if (buf != '\0') 01207 { 01208 dbus_set_error (error, DBUS_ERROR_FAILED, 01209 "Credentials byte was not nul"); 01210 return FALSE; 01211 } 01212 01213 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01214 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01215 || cmsg.hdr.cmsg_type != SCM_CREDS) 01216 { 01217 dbus_set_error (error, DBUS_ERROR_FAILED, 01218 "Message from recvmsg() was not SCM_CREDS"); 01219 return FALSE; 01220 } 01221 #endif 01222 01223 _dbus_verbose ("read credentials byte\n"); 01224 01225 { 01226 #ifdef SO_PEERCRED 01227 struct ucred cr; 01228 int cr_len = sizeof (cr); 01229 01230 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01231 cr_len == sizeof (cr)) 01232 { 01233 pid_read = cr.pid; 01234 uid_read = cr.uid; 01235 } 01236 else 01237 { 01238 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01239 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01240 } 01241 #elif defined(HAVE_CMSGCRED) 01242 struct cmsgcred *cred; 01243 01244 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01245 pid_read = cred->cmcred_pid; 01246 uid_read = cred->cmcred_euid; 01247 #elif defined(LOCAL_CREDS) 01248 pid_read = DBUS_PID_UNSET; 01249 uid_read = cmsg.cred.sc_uid; 01250 /* Since we have already got the credentials from this socket, we can 01251 * disable its LOCAL_CREDS flag if it was ever set. */ 01252 _dbus_set_local_creds (client_fd, FALSE); 01253 #elif defined(HAVE_GETPEEREID) 01254 uid_t euid; 01255 gid_t egid; 01256 if (getpeereid (client_fd, &euid, &egid) == 0) 01257 { 01258 uid_read = euid; 01259 } 01260 else 01261 { 01262 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01263 } 01264 #elif defined(HAVE_GETPEERUCRED) 01265 ucred_t * ucred = NULL; 01266 if (getpeerucred (client_fd, &ucred) == 0) 01267 { 01268 pid_read = ucred_getpid (ucred); 01269 uid_read = ucred_geteuid (ucred); 01270 #ifdef HAVE_ADT 01271 /* generate audit session data based on socket ucred */ 01272 adt_session_data_t *adth = NULL; 01273 adt_export_data_t *data = NULL; 01274 size_t size = 0; 01275 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01276 { 01277 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01278 } 01279 else 01280 { 01281 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01282 { 01283 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01284 } 01285 else 01286 { 01287 size = adt_export_session_data (adth, &data); 01288 if (size <= 0) 01289 { 01290 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01291 } 01292 else 01293 { 01294 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01295 free (data); 01296 } 01297 } 01298 (void) adt_end_session (adth); 01299 } 01300 #endif /* HAVE_ADT */ 01301 } 01302 else 01303 { 01304 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01305 } 01306 if (ucred != NULL) 01307 ucred_free (ucred); 01308 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01309 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01310 #endif 01311 } 01312 01313 _dbus_verbose ("Credentials:" 01314 " pid "DBUS_PID_FORMAT 01315 " uid "DBUS_UID_FORMAT 01316 "\n", 01317 pid_read, 01318 uid_read); 01319 01320 if (pid_read != DBUS_PID_UNSET) 01321 { 01322 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01323 { 01324 _DBUS_SET_OOM (error); 01325 return FALSE; 01326 } 01327 } 01328 01329 if (uid_read != DBUS_UID_UNSET) 01330 { 01331 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01332 { 01333 _DBUS_SET_OOM (error); 01334 return FALSE; 01335 } 01336 } 01337 01338 return TRUE; 01339 } 01340 01358 dbus_bool_t 01359 _dbus_send_credentials_socket (int server_fd, 01360 DBusError *error) 01361 { 01362 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01363 01364 if (write_credentials_byte (server_fd, error)) 01365 return TRUE; 01366 else 01367 return FALSE; 01368 } 01369 01377 int 01378 _dbus_accept (int listen_fd) 01379 { 01380 int client_fd; 01381 struct sockaddr addr; 01382 socklen_t addrlen; 01383 01384 addrlen = sizeof (addr); 01385 01386 retry: 01387 client_fd = accept (listen_fd, &addr, &addrlen); 01388 01389 if (client_fd < 0) 01390 { 01391 if (errno == EINTR) 01392 goto retry; 01393 } 01394 01395 _dbus_verbose ("client fd %d accepted\n", client_fd); 01396 01397 return client_fd; 01398 } 01399 01408 dbus_bool_t 01409 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01410 { 01411 const char *directory; 01412 struct stat sb; 01413 01414 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01415 01416 directory = _dbus_string_get_const_data (dir); 01417 01418 if (stat (directory, &sb) < 0) 01419 { 01420 dbus_set_error (error, _dbus_error_from_errno (errno), 01421 "%s", _dbus_strerror (errno)); 01422 01423 return FALSE; 01424 } 01425 01426 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01427 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01428 { 01429 dbus_set_error (error, DBUS_ERROR_FAILED, 01430 "%s directory is not private to the user", directory); 01431 return FALSE; 01432 } 01433 01434 return TRUE; 01435 } 01436 01437 static dbus_bool_t 01438 fill_user_info_from_passwd (struct passwd *p, 01439 DBusUserInfo *info, 01440 DBusError *error) 01441 { 01442 _dbus_assert (p->pw_name != NULL); 01443 _dbus_assert (p->pw_dir != NULL); 01444 01445 info->uid = p->pw_uid; 01446 info->primary_gid = p->pw_gid; 01447 info->username = _dbus_strdup (p->pw_name); 01448 info->homedir = _dbus_strdup (p->pw_dir); 01449 01450 if (info->username == NULL || 01451 info->homedir == NULL) 01452 { 01453 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01454 return FALSE; 01455 } 01456 01457 return TRUE; 01458 } 01459 01460 static dbus_bool_t 01461 fill_user_info (DBusUserInfo *info, 01462 dbus_uid_t uid, 01463 const DBusString *username, 01464 DBusError *error) 01465 { 01466 const char *username_c; 01467 01468 /* exactly one of username/uid provided */ 01469 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 01470 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 01471 01472 info->uid = DBUS_UID_UNSET; 01473 info->primary_gid = DBUS_GID_UNSET; 01474 info->group_ids = NULL; 01475 info->n_group_ids = 0; 01476 info->username = NULL; 01477 info->homedir = NULL; 01478 01479 if (username != NULL) 01480 username_c = _dbus_string_get_const_data (username); 01481 else 01482 username_c = NULL; 01483 01484 /* For now assuming that the getpwnam() and getpwuid() flavors 01485 * are always symmetrical, if not we have to add more configure 01486 * checks 01487 */ 01488 01489 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 01490 { 01491 struct passwd *p; 01492 int result; 01493 size_t buflen; 01494 char *buf; 01495 struct passwd p_str; 01496 01497 /* retrieve maximum needed size for buf */ 01498 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 01499 01500 /* sysconf actually returns a long, but everything else expects size_t, 01501 * so just recast here. 01502 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 01503 */ 01504 if ((long) buflen <= 0) 01505 buflen = 1024; 01506 01507 result = -1; 01508 while (1) 01509 { 01510 buf = dbus_malloc (buflen); 01511 if (buf == NULL) 01512 { 01513 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01514 return FALSE; 01515 } 01516 01517 p = NULL; 01518 #ifdef HAVE_POSIX_GETPWNAM_R 01519 if (uid != DBUS_UID_UNSET) 01520 result = getpwuid_r (uid, &p_str, buf, buflen, 01521 &p); 01522 else 01523 result = getpwnam_r (username_c, &p_str, buf, buflen, 01524 &p); 01525 #else 01526 if (uid != DBUS_UID_UNSET) 01527 p = getpwuid_r (uid, &p_str, buf, buflen); 01528 else 01529 p = getpwnam_r (username_c, &p_str, buf, buflen); 01530 result = 0; 01531 #endif /* !HAVE_POSIX_GETPWNAM_R */ 01532 //Try a bigger buffer if ERANGE was returned 01533 if (result == ERANGE && buflen < 512 * 1024) 01534 { 01535 dbus_free (buf); 01536 buflen *= 2; 01537 } 01538 else 01539 { 01540 break; 01541 } 01542 } 01543 if (result == 0 && p == &p_str) 01544 { 01545 if (!fill_user_info_from_passwd (p, info, error)) 01546 { 01547 dbus_free (buf); 01548 return FALSE; 01549 } 01550 dbus_free (buf); 01551 } 01552 else 01553 { 01554 dbus_set_error (error, _dbus_error_from_errno (errno), 01555 "User \"%s\" unknown or no memory to allocate password entry\n", 01556 username_c ? username_c : "???"); 01557 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 01558 dbus_free (buf); 01559 return FALSE; 01560 } 01561 } 01562 #else /* ! HAVE_GETPWNAM_R */ 01563 { 01564 /* I guess we're screwed on thread safety here */ 01565 struct passwd *p; 01566 01567 if (uid != DBUS_UID_UNSET) 01568 p = getpwuid (uid); 01569 else 01570 p = getpwnam (username_c); 01571 01572 if (p != NULL) 01573 { 01574 if (!fill_user_info_from_passwd (p, info, error)) 01575 { 01576 return FALSE; 01577 } 01578 } 01579 else 01580 { 01581 dbus_set_error (error, _dbus_error_from_errno (errno), 01582 "User \"%s\" unknown or no memory to allocate password entry\n", 01583 username_c ? username_c : "???"); 01584 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 01585 return FALSE; 01586 } 01587 } 01588 #endif /* ! HAVE_GETPWNAM_R */ 01589 01590 /* Fill this in so we can use it to get groups */ 01591 username_c = info->username; 01592 01593 #ifdef HAVE_GETGROUPLIST 01594 { 01595 gid_t *buf; 01596 int buf_count; 01597 int i; 01598 int initial_buf_count; 01599 01600 initial_buf_count = 17; 01601 buf_count = initial_buf_count; 01602 buf = dbus_new (gid_t, buf_count); 01603 if (buf == NULL) 01604 { 01605 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01606 goto failed; 01607 } 01608 01609 if (getgrouplist (username_c, 01610 info->primary_gid, 01611 buf, &buf_count) < 0) 01612 { 01613 gid_t *new; 01614 /* Presumed cause of negative return code: buf has insufficient 01615 entries to hold the entire group list. The Linux behavior in this 01616 case is to pass back the actual number of groups in buf_count, but 01617 on Mac OS X 10.5, buf_count is unhelpfully left alone. 01618 So as a hack, try to help out a bit by guessing a larger 01619 number of groups, within reason.. might still fail, of course, 01620 but we can at least print a more informative message. I looked up 01621 the "right way" to do this by downloading Apple's own source code 01622 for the "id" command, and it turns out that they use an 01623 undocumented library function getgrouplist_2 (!) which is not 01624 declared in any header in /usr/include (!!). That did not seem 01625 like the way to go here. 01626 */ 01627 if (buf_count == initial_buf_count) 01628 { 01629 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 01630 } 01631 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 01632 if (new == NULL) 01633 { 01634 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01635 dbus_free (buf); 01636 goto failed; 01637 } 01638 01639 buf = new; 01640 01641 errno = 0; 01642 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 01643 { 01644 if (errno == 0) 01645 { 01646 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 01647 username_c, buf_count, buf_count); 01648 } 01649 else 01650 { 01651 dbus_set_error (error, 01652 _dbus_error_from_errno (errno), 01653 "Failed to get groups for username \"%s\" primary GID " 01654 DBUS_GID_FORMAT ": %s\n", 01655 username_c, info->primary_gid, 01656 _dbus_strerror (errno)); 01657 dbus_free (buf); 01658 goto failed; 01659 } 01660 } 01661 } 01662 01663 info->group_ids = dbus_new (dbus_gid_t, buf_count); 01664 if (info->group_ids == NULL) 01665 { 01666 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01667 dbus_free (buf); 01668 goto failed; 01669 } 01670 01671 for (i = 0; i < buf_count; ++i) 01672 info->group_ids[i] = buf[i]; 01673 01674 info->n_group_ids = buf_count; 01675 01676 dbus_free (buf); 01677 } 01678 #else /* HAVE_GETGROUPLIST */ 01679 { 01680 /* We just get the one group ID */ 01681 info->group_ids = dbus_new (dbus_gid_t, 1); 01682 if (info->group_ids == NULL) 01683 { 01684 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01685 goto failed; 01686 } 01687 01688 info->n_group_ids = 1; 01689 01690 (info->group_ids)[0] = info->primary_gid; 01691 } 01692 #endif /* HAVE_GETGROUPLIST */ 01693 01694 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01695 01696 return TRUE; 01697 01698 failed: 01699 _DBUS_ASSERT_ERROR_IS_SET (error); 01700 return FALSE; 01701 } 01702 01711 dbus_bool_t 01712 _dbus_user_info_fill (DBusUserInfo *info, 01713 const DBusString *username, 01714 DBusError *error) 01715 { 01716 return fill_user_info (info, DBUS_UID_UNSET, 01717 username, error); 01718 } 01719 01728 dbus_bool_t 01729 _dbus_user_info_fill_uid (DBusUserInfo *info, 01730 dbus_uid_t uid, 01731 DBusError *error) 01732 { 01733 return fill_user_info (info, uid, 01734 NULL, error); 01735 } 01736 01744 dbus_bool_t 01745 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 01746 { 01747 /* The POSIX spec certainly doesn't promise this, but 01748 * we need these assertions to fail as soon as we're wrong about 01749 * it so we can do the porting fixups 01750 */ 01751 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01752 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01753 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01754 01755 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 01756 return FALSE; 01757 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 01758 return FALSE; 01759 01760 return TRUE; 01761 } 01762 01774 dbus_bool_t 01775 _dbus_append_user_from_current_process (DBusString *str) 01776 { 01777 return _dbus_string_append_uint (str, 01778 _dbus_geteuid ()); 01779 } 01780 01785 dbus_pid_t 01786 _dbus_getpid (void) 01787 { 01788 return getpid (); 01789 } 01790 01794 dbus_uid_t 01795 _dbus_getuid (void) 01796 { 01797 return getuid (); 01798 } 01799 01803 dbus_uid_t 01804 _dbus_geteuid (void) 01805 { 01806 return geteuid (); 01807 } 01808 01815 unsigned long 01816 _dbus_pid_for_log (void) 01817 { 01818 return getpid (); 01819 } 01820 01828 dbus_bool_t 01829 _dbus_parse_uid (const DBusString *uid_str, 01830 dbus_uid_t *uid) 01831 { 01832 int end; 01833 long val; 01834 01835 if (_dbus_string_get_length (uid_str) == 0) 01836 { 01837 _dbus_verbose ("UID string was zero length\n"); 01838 return FALSE; 01839 } 01840 01841 val = -1; 01842 end = 0; 01843 if (!_dbus_string_parse_int (uid_str, 0, &val, 01844 &end)) 01845 { 01846 _dbus_verbose ("could not parse string as a UID\n"); 01847 return FALSE; 01848 } 01849 01850 if (end != _dbus_string_get_length (uid_str)) 01851 { 01852 _dbus_verbose ("string contained trailing stuff after UID\n"); 01853 return FALSE; 01854 } 01855 01856 *uid = val; 01857 01858 return TRUE; 01859 } 01860 01861 01862 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 01863 01864 #if DBUS_USE_ATOMIC_INT_486_COND 01865 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */ 01866 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */ 01867 static inline dbus_int32_t 01868 atomic_exchange_and_add (DBusAtomic *atomic, 01869 volatile dbus_int32_t val) 01870 { 01871 register dbus_int32_t result; 01872 01873 __asm__ __volatile__ ("lock; xaddl %0,%1" 01874 : "=r" (result), "=m" (atomic->value) 01875 : "0" (val), "m" (atomic->value)); 01876 return result; 01877 } 01878 #endif 01879 01888 dbus_int32_t 01889 _dbus_atomic_inc (DBusAtomic *atomic) 01890 { 01891 #if DBUS_USE_ATOMIC_INT_486_COND 01892 return atomic_exchange_and_add (atomic, 1); 01893 #else 01894 dbus_int32_t res; 01895 _DBUS_LOCK (atomic); 01896 res = atomic->value; 01897 atomic->value += 1; 01898 _DBUS_UNLOCK (atomic); 01899 return res; 01900 #endif 01901 } 01902 01911 dbus_int32_t 01912 _dbus_atomic_dec (DBusAtomic *atomic) 01913 { 01914 #if DBUS_USE_ATOMIC_INT_486_COND 01915 return atomic_exchange_and_add (atomic, -1); 01916 #else 01917 dbus_int32_t res; 01918 01919 _DBUS_LOCK (atomic); 01920 res = atomic->value; 01921 atomic->value -= 1; 01922 _DBUS_UNLOCK (atomic); 01923 return res; 01924 #endif 01925 } 01926 01927 #ifdef DBUS_BUILD_TESTS 01928 01931 dbus_gid_t 01932 _dbus_getgid (void) 01933 { 01934 return getgid (); 01935 } 01936 #endif 01937 01946 int 01947 _dbus_poll (DBusPollFD *fds, 01948 int n_fds, 01949 int timeout_milliseconds) 01950 { 01951 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 01952 /* This big thing is a constant expression and should get optimized 01953 * out of existence. So it's more robust than a configure check at 01954 * no cost. 01955 */ 01956 if (_DBUS_POLLIN == POLLIN && 01957 _DBUS_POLLPRI == POLLPRI && 01958 _DBUS_POLLOUT == POLLOUT && 01959 _DBUS_POLLERR == POLLERR && 01960 _DBUS_POLLHUP == POLLHUP && 01961 _DBUS_POLLNVAL == POLLNVAL && 01962 sizeof (DBusPollFD) == sizeof (struct pollfd) && 01963 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 01964 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 01965 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 01966 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 01967 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 01968 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 01969 { 01970 return poll ((struct pollfd*) fds, 01971 n_fds, 01972 timeout_milliseconds); 01973 } 01974 else 01975 { 01976 /* We have to convert the DBusPollFD to an array of 01977 * struct pollfd, poll, and convert back. 01978 */ 01979 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 01980 return -1; 01981 } 01982 #else /* ! HAVE_POLL */ 01983 01984 fd_set read_set, write_set, err_set; 01985 int max_fd = 0; 01986 int i; 01987 struct timeval tv; 01988 int ready; 01989 01990 FD_ZERO (&read_set); 01991 FD_ZERO (&write_set); 01992 FD_ZERO (&err_set); 01993 01994 for (i = 0; i < n_fds; i++) 01995 { 01996 DBusPollFD *fdp = &fds[i]; 01997 01998 if (fdp->events & _DBUS_POLLIN) 01999 FD_SET (fdp->fd, &read_set); 02000 02001 if (fdp->events & _DBUS_POLLOUT) 02002 FD_SET (fdp->fd, &write_set); 02003 02004 FD_SET (fdp->fd, &err_set); 02005 02006 max_fd = MAX (max_fd, fdp->fd); 02007 } 02008 02009 tv.tv_sec = timeout_milliseconds / 1000; 02010 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02011 02012 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02013 timeout_milliseconds < 0 ? NULL : &tv); 02014 02015 if (ready > 0) 02016 { 02017 for (i = 0; i < n_fds; i++) 02018 { 02019 DBusPollFD *fdp = &fds[i]; 02020 02021 fdp->revents = 0; 02022 02023 if (FD_ISSET (fdp->fd, &read_set)) 02024 fdp->revents |= _DBUS_POLLIN; 02025 02026 if (FD_ISSET (fdp->fd, &write_set)) 02027 fdp->revents |= _DBUS_POLLOUT; 02028 02029 if (FD_ISSET (fdp->fd, &err_set)) 02030 fdp->revents |= _DBUS_POLLERR; 02031 } 02032 } 02033 02034 return ready; 02035 #endif 02036 } 02037 02045 void 02046 _dbus_get_current_time (long *tv_sec, 02047 long *tv_usec) 02048 { 02049 struct timeval t; 02050 02051 #ifdef HAVE_MONOTONIC_CLOCK 02052 struct timespec ts; 02053 clock_gettime (CLOCK_MONOTONIC, &ts); 02054 02055 if (tv_sec) 02056 *tv_sec = ts.tv_sec; 02057 if (tv_usec) 02058 *tv_usec = ts.tv_nsec / 1000; 02059 #else 02060 gettimeofday (&t, NULL); 02061 02062 if (tv_sec) 02063 *tv_sec = t.tv_sec; 02064 if (tv_usec) 02065 *tv_usec = t.tv_usec; 02066 #endif 02067 } 02068 02079 dbus_bool_t 02080 _dbus_file_get_contents (DBusString *str, 02081 const DBusString *filename, 02082 DBusError *error) 02083 { 02084 int fd; 02085 struct stat sb; 02086 int orig_len; 02087 int total; 02088 const char *filename_c; 02089 02090 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02091 02092 filename_c = _dbus_string_get_const_data (filename); 02093 02094 /* O_BINARY useful on Cygwin */ 02095 fd = open (filename_c, O_RDONLY | O_BINARY); 02096 if (fd < 0) 02097 { 02098 dbus_set_error (error, _dbus_error_from_errno (errno), 02099 "Failed to open \"%s\": %s", 02100 filename_c, 02101 _dbus_strerror (errno)); 02102 return FALSE; 02103 } 02104 02105 _dbus_verbose ("file fd %d opened\n", fd); 02106 02107 if (fstat (fd, &sb) < 0) 02108 { 02109 dbus_set_error (error, _dbus_error_from_errno (errno), 02110 "Failed to stat \"%s\": %s", 02111 filename_c, 02112 _dbus_strerror (errno)); 02113 02114 _dbus_verbose ("fstat() failed: %s", 02115 _dbus_strerror (errno)); 02116 02117 _dbus_close (fd, NULL); 02118 02119 return FALSE; 02120 } 02121 02122 if (sb.st_size > _DBUS_ONE_MEGABYTE) 02123 { 02124 dbus_set_error (error, DBUS_ERROR_FAILED, 02125 "File size %lu of \"%s\" is too large.", 02126 (unsigned long) sb.st_size, filename_c); 02127 _dbus_close (fd, NULL); 02128 return FALSE; 02129 } 02130 02131 total = 0; 02132 orig_len = _dbus_string_get_length (str); 02133 if (sb.st_size > 0 && S_ISREG (sb.st_mode)) 02134 { 02135 int bytes_read; 02136 02137 while (total < (int) sb.st_size) 02138 { 02139 bytes_read = _dbus_read (fd, str, 02140 sb.st_size - total); 02141 if (bytes_read <= 0) 02142 { 02143 dbus_set_error (error, _dbus_error_from_errno (errno), 02144 "Error reading \"%s\": %s", 02145 filename_c, 02146 _dbus_strerror (errno)); 02147 02148 _dbus_verbose ("read() failed: %s", 02149 _dbus_strerror (errno)); 02150 02151 _dbus_close (fd, NULL); 02152 _dbus_string_set_length (str, orig_len); 02153 return FALSE; 02154 } 02155 else 02156 total += bytes_read; 02157 } 02158 02159 _dbus_close (fd, NULL); 02160 return TRUE; 02161 } 02162 else if (sb.st_size != 0) 02163 { 02164 _dbus_verbose ("Can only open regular files at the moment.\n"); 02165 dbus_set_error (error, DBUS_ERROR_FAILED, 02166 "\"%s\" is not a regular file", 02167 filename_c); 02168 _dbus_close (fd, NULL); 02169 return FALSE; 02170 } 02171 else 02172 { 02173 _dbus_close (fd, NULL); 02174 return TRUE; 02175 } 02176 } 02177 02187 dbus_bool_t 02188 _dbus_string_save_to_file (const DBusString *str, 02189 const DBusString *filename, 02190 DBusError *error) 02191 { 02192 int fd; 02193 int bytes_to_write; 02194 const char *filename_c; 02195 DBusString tmp_filename; 02196 const char *tmp_filename_c; 02197 int total; 02198 dbus_bool_t need_unlink; 02199 dbus_bool_t retval; 02200 02201 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02202 02203 fd = -1; 02204 retval = FALSE; 02205 need_unlink = FALSE; 02206 02207 if (!_dbus_string_init (&tmp_filename)) 02208 { 02209 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02210 return FALSE; 02211 } 02212 02213 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0)) 02214 { 02215 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02216 _dbus_string_free (&tmp_filename); 02217 return FALSE; 02218 } 02219 02220 if (!_dbus_string_append (&tmp_filename, ".")) 02221 { 02222 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02223 _dbus_string_free (&tmp_filename); 02224 return FALSE; 02225 } 02226 02227 #define N_TMP_FILENAME_RANDOM_BYTES 8 02228 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES)) 02229 { 02230 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02231 _dbus_string_free (&tmp_filename); 02232 return FALSE; 02233 } 02234 02235 filename_c = _dbus_string_get_const_data (filename); 02236 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename); 02237 02238 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT, 02239 0600); 02240 if (fd < 0) 02241 { 02242 dbus_set_error (error, _dbus_error_from_errno (errno), 02243 "Could not create %s: %s", tmp_filename_c, 02244 _dbus_strerror (errno)); 02245 goto out; 02246 } 02247 02248 _dbus_verbose ("tmp file fd %d opened\n", fd); 02249 02250 need_unlink = TRUE; 02251 02252 total = 0; 02253 bytes_to_write = _dbus_string_get_length (str); 02254 02255 while (total < bytes_to_write) 02256 { 02257 int bytes_written; 02258 02259 bytes_written = _dbus_write (fd, str, total, 02260 bytes_to_write - total); 02261 02262 if (bytes_written <= 0) 02263 { 02264 dbus_set_error (error, _dbus_error_from_errno (errno), 02265 "Could not write to %s: %s", tmp_filename_c, 02266 _dbus_strerror (errno)); 02267 02268 goto out; 02269 } 02270 02271 total += bytes_written; 02272 } 02273 02274 if (fsync(fd)) 02275 { 02276 dbus_set_error (error, _dbus_error_from_errno (errno), 02277 "Could not synchronize file %s: %s", 02278 tmp_filename_c, _dbus_strerror (errno)); 02279 02280 goto out; 02281 } 02282 02283 if (!_dbus_close (fd, NULL)) 02284 { 02285 dbus_set_error (error, _dbus_error_from_errno (errno), 02286 "Could not close file %s: %s", 02287 tmp_filename_c, _dbus_strerror (errno)); 02288 02289 goto out; 02290 } 02291 02292 fd = -1; 02293 02294 if (rename (tmp_filename_c, filename_c) < 0) 02295 { 02296 dbus_set_error (error, _dbus_error_from_errno (errno), 02297 "Could not rename %s to %s: %s", 02298 tmp_filename_c, filename_c, 02299 _dbus_strerror (errno)); 02300 02301 goto out; 02302 } 02303 02304 need_unlink = FALSE; 02305 02306 retval = TRUE; 02307 02308 out: 02309 /* close first, then unlink, to prevent ".nfs34234235" garbage 02310 * files 02311 */ 02312 02313 if (fd >= 0) 02314 _dbus_close (fd, NULL); 02315 02316 if (need_unlink && unlink (tmp_filename_c) < 0) 02317 _dbus_verbose ("Failed to unlink temp file %s: %s\n", 02318 tmp_filename_c, _dbus_strerror (errno)); 02319 02320 _dbus_string_free (&tmp_filename); 02321 02322 if (!retval) 02323 _DBUS_ASSERT_ERROR_IS_SET (error); 02324 02325 return retval; 02326 } 02327 02334 dbus_bool_t 02335 _dbus_make_file_world_readable(const DBusString *filename, 02336 DBusError *error) 02337 { 02338 const char *filename_c; 02339 02340 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02341 02342 filename_c = _dbus_string_get_const_data (filename); 02343 if (chmod (filename_c, 0644) == -1) 02344 { 02345 dbus_set_error (error, 02346 DBUS_ERROR_FAILED, 02347 "Could not change permissions of file %s: %s\n", 02348 filename_c, 02349 _dbus_strerror (errno)); 02350 return FALSE; 02351 } 02352 return TRUE; 02353 } 02354 02361 dbus_bool_t 02362 _dbus_create_file_exclusively (const DBusString *filename, 02363 DBusError *error) 02364 { 02365 int fd; 02366 const char *filename_c; 02367 02368 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02369 02370 filename_c = _dbus_string_get_const_data (filename); 02371 02372 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT, 02373 0600); 02374 if (fd < 0) 02375 { 02376 dbus_set_error (error, 02377 DBUS_ERROR_FAILED, 02378 "Could not create file %s: %s\n", 02379 filename_c, 02380 _dbus_strerror (errno)); 02381 return FALSE; 02382 } 02383 02384 _dbus_verbose ("exclusive file fd %d opened\n", fd); 02385 02386 if (!_dbus_close (fd, NULL)) 02387 { 02388 dbus_set_error (error, 02389 DBUS_ERROR_FAILED, 02390 "Could not close file %s: %s\n", 02391 filename_c, 02392 _dbus_strerror (errno)); 02393 return FALSE; 02394 } 02395 02396 return TRUE; 02397 } 02398 02407 dbus_bool_t 02408 _dbus_delete_file (const DBusString *filename, 02409 DBusError *error) 02410 { 02411 const char *filename_c; 02412 02413 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02414 02415 filename_c = _dbus_string_get_const_data (filename); 02416 02417 if (unlink (filename_c) < 0) 02418 { 02419 dbus_set_error (error, DBUS_ERROR_FAILED, 02420 "Failed to delete file %s: %s\n", 02421 filename_c, _dbus_strerror (errno)); 02422 return FALSE; 02423 } 02424 else 02425 return TRUE; 02426 } 02427 02436 dbus_bool_t 02437 _dbus_create_directory (const DBusString *filename, 02438 DBusError *error) 02439 { 02440 const char *filename_c; 02441 02442 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02443 02444 filename_c = _dbus_string_get_const_data (filename); 02445 02446 if (mkdir (filename_c, 0700) < 0) 02447 { 02448 if (errno == EEXIST) 02449 return TRUE; 02450 02451 dbus_set_error (error, DBUS_ERROR_FAILED, 02452 "Failed to create directory %s: %s\n", 02453 filename_c, _dbus_strerror (errno)); 02454 return FALSE; 02455 } 02456 else 02457 return TRUE; 02458 } 02459 02470 dbus_bool_t 02471 _dbus_concat_dir_and_file (DBusString *dir, 02472 const DBusString *next_component) 02473 { 02474 dbus_bool_t dir_ends_in_slash; 02475 dbus_bool_t file_starts_with_slash; 02476 02477 if (_dbus_string_get_length (dir) == 0 || 02478 _dbus_string_get_length (next_component) == 0) 02479 return TRUE; 02480 02481 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02482 _dbus_string_get_length (dir) - 1); 02483 02484 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02485 02486 if (dir_ends_in_slash && file_starts_with_slash) 02487 { 02488 _dbus_string_shorten (dir, 1); 02489 } 02490 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02491 { 02492 if (!_dbus_string_append_byte (dir, '/')) 02493 return FALSE; 02494 } 02495 02496 return _dbus_string_copy (next_component, 0, dir, 02497 _dbus_string_get_length (dir)); 02498 } 02499 02501 #define NANOSECONDS_PER_SECOND 1000000000 02502 02503 #define MICROSECONDS_PER_SECOND 1000000 02504 02505 #define MILLISECONDS_PER_SECOND 1000 02506 02507 #define NANOSECONDS_PER_MILLISECOND 1000000 02508 02509 #define MICROSECONDS_PER_MILLISECOND 1000 02510 02515 void 02516 _dbus_sleep_milliseconds (int milliseconds) 02517 { 02518 #ifdef HAVE_NANOSLEEP 02519 struct timespec req; 02520 struct timespec rem; 02521 02522 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02523 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02524 rem.tv_sec = 0; 02525 rem.tv_nsec = 0; 02526 02527 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02528 req = rem; 02529 #elif defined (HAVE_USLEEP) 02530 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02531 #else /* ! HAVE_USLEEP */ 02532 sleep (MAX (milliseconds / 1000, 1)); 02533 #endif 02534 } 02535 02536 static dbus_bool_t 02537 _dbus_generate_pseudorandom_bytes (DBusString *str, 02538 int n_bytes) 02539 { 02540 int old_len; 02541 char *p; 02542 02543 old_len = _dbus_string_get_length (str); 02544 02545 if (!_dbus_string_lengthen (str, n_bytes)) 02546 return FALSE; 02547 02548 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02549 02550 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02551 02552 return TRUE; 02553 } 02554 02563 dbus_bool_t 02564 _dbus_generate_random_bytes (DBusString *str, 02565 int n_bytes) 02566 { 02567 int old_len; 02568 int fd; 02569 02570 /* FALSE return means "no memory", if it could 02571 * mean something else then we'd need to return 02572 * a DBusError. So we always fall back to pseudorandom 02573 * if the I/O fails. 02574 */ 02575 02576 old_len = _dbus_string_get_length (str); 02577 fd = -1; 02578 02579 /* note, urandom on linux will fall back to pseudorandom */ 02580 fd = open ("/dev/urandom", O_RDONLY); 02581 if (fd < 0) 02582 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02583 02584 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02585 02586 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02587 { 02588 _dbus_close (fd, NULL); 02589 _dbus_string_set_length (str, old_len); 02590 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02591 } 02592 02593 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02594 n_bytes); 02595 02596 _dbus_close (fd, NULL); 02597 02598 return TRUE; 02599 } 02600 02606 void 02607 _dbus_exit (int code) 02608 { 02609 _exit (code); 02610 } 02611 02620 const char* 02621 _dbus_strerror (int error_number) 02622 { 02623 const char *msg; 02624 02625 msg = strerror (error_number); 02626 if (msg == NULL) 02627 msg = "unknown"; 02628 02629 return msg; 02630 } 02631 02635 void 02636 _dbus_disable_sigpipe (void) 02637 { 02638 signal (SIGPIPE, SIG_IGN); 02639 } 02640 02648 void 02649 _dbus_fd_set_close_on_exec (int fd) 02650 { 02651 int val; 02652 02653 val = fcntl (fd, F_GETFD, 0); 02654 02655 if (val < 0) 02656 return; 02657 02658 val |= FD_CLOEXEC; 02659 02660 fcntl (fd, F_SETFD, val); 02661 } 02662 02670 dbus_bool_t 02671 _dbus_close (int fd, 02672 DBusError *error) 02673 { 02674 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02675 02676 again: 02677 if (close (fd) < 0) 02678 { 02679 if (errno == EINTR) 02680 goto again; 02681 02682 dbus_set_error (error, _dbus_error_from_errno (errno), 02683 "Could not close fd %d", fd); 02684 return FALSE; 02685 } 02686 02687 return TRUE; 02688 } 02689 02697 dbus_bool_t 02698 _dbus_set_fd_nonblocking (int fd, 02699 DBusError *error) 02700 { 02701 int val; 02702 02703 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02704 02705 val = fcntl (fd, F_GETFL, 0); 02706 if (val < 0) 02707 { 02708 dbus_set_error (error, _dbus_error_from_errno (errno), 02709 "Failed to get flags from file descriptor %d: %s", 02710 fd, _dbus_strerror (errno)); 02711 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02712 _dbus_strerror (errno)); 02713 return FALSE; 02714 } 02715 02716 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02717 { 02718 dbus_set_error (error, _dbus_error_from_errno (errno), 02719 "Failed to set nonblocking flag of file descriptor %d: %s", 02720 fd, _dbus_strerror (errno)); 02721 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02722 fd, _dbus_strerror (errno)); 02723 02724 return FALSE; 02725 } 02726 02727 return TRUE; 02728 } 02729 02735 void 02736 _dbus_print_backtrace (void) 02737 { 02738 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 02739 void *bt[500]; 02740 int bt_size; 02741 int i; 02742 char **syms; 02743 02744 bt_size = backtrace (bt, 500); 02745 02746 syms = backtrace_symbols (bt, bt_size); 02747 02748 i = 0; 02749 while (i < bt_size) 02750 { 02751 /* don't use dbus_warn since it can _dbus_abort() */ 02752 fprintf (stderr, " %s\n", syms[i]); 02753 ++i; 02754 } 02755 fflush (stderr); 02756 02757 free (syms); 02758 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 02759 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 02760 #else 02761 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 02762 #endif 02763 } 02764 02780 dbus_bool_t 02781 _dbus_full_duplex_pipe (int *fd1, 02782 int *fd2, 02783 dbus_bool_t blocking, 02784 DBusError *error) 02785 { 02786 #ifdef HAVE_SOCKETPAIR 02787 int fds[2]; 02788 02789 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02790 02791 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0) 02792 { 02793 dbus_set_error (error, _dbus_error_from_errno (errno), 02794 "Could not create full-duplex pipe"); 02795 return FALSE; 02796 } 02797 02798 if (!blocking && 02799 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 02800 !_dbus_set_fd_nonblocking (fds[1], NULL))) 02801 { 02802 dbus_set_error (error, _dbus_error_from_errno (errno), 02803 "Could not set full-duplex pipe nonblocking"); 02804 02805 _dbus_close (fds[0], NULL); 02806 _dbus_close (fds[1], NULL); 02807 02808 return FALSE; 02809 } 02810 02811 *fd1 = fds[0]; 02812 *fd2 = fds[1]; 02813 02814 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 02815 *fd1, *fd2); 02816 02817 return TRUE; 02818 #else 02819 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 02820 dbus_set_error (error, DBUS_ERROR_FAILED, 02821 "_dbus_full_duplex_pipe() not implemented on this OS"); 02822 return FALSE; 02823 #endif 02824 } 02825 02834 int 02835 _dbus_printf_string_upper_bound (const char *format, 02836 va_list args) 02837 { 02838 char c; 02839 return vsnprintf (&c, 1, format, args); 02840 } 02841 02848 const char* 02849 _dbus_get_tmpdir(void) 02850 { 02851 static const char* tmpdir = NULL; 02852 02853 if (tmpdir == NULL) 02854 { 02855 /* TMPDIR is what glibc uses, then 02856 * glibc falls back to the P_tmpdir macro which 02857 * just expands to "/tmp" 02858 */ 02859 if (tmpdir == NULL) 02860 tmpdir = getenv("TMPDIR"); 02861 02862 /* These two env variables are probably 02863 * broken, but maybe some OS uses them? 02864 */ 02865 if (tmpdir == NULL) 02866 tmpdir = getenv("TMP"); 02867 if (tmpdir == NULL) 02868 tmpdir = getenv("TEMP"); 02869 02870 /* And this is the sane fallback. */ 02871 if (tmpdir == NULL) 02872 tmpdir = "/tmp"; 02873 } 02874 02875 _dbus_assert(tmpdir != NULL); 02876 02877 return tmpdir; 02878 } 02879 02899 static dbus_bool_t 02900 _read_subprocess_line_argv (const char *progpath, 02901 dbus_bool_t path_fallback, 02902 char * const *argv, 02903 DBusString *result, 02904 DBusError *error) 02905 { 02906 int result_pipe[2] = { -1, -1 }; 02907 int errors_pipe[2] = { -1, -1 }; 02908 pid_t pid; 02909 int ret; 02910 int status; 02911 int orig_len; 02912 int i; 02913 02914 dbus_bool_t retval; 02915 sigset_t new_set, old_set; 02916 02917 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02918 retval = FALSE; 02919 02920 /* We need to block any existing handlers for SIGCHLD temporarily; they 02921 * will cause waitpid() below to fail. 02922 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 02923 */ 02924 sigemptyset (&new_set); 02925 sigaddset (&new_set, SIGCHLD); 02926 sigprocmask (SIG_BLOCK, &new_set, &old_set); 02927 02928 orig_len = _dbus_string_get_length (result); 02929 02930 #define READ_END 0 02931 #define WRITE_END 1 02932 if (pipe (result_pipe) < 0) 02933 { 02934 dbus_set_error (error, _dbus_error_from_errno (errno), 02935 "Failed to create a pipe to call %s: %s", 02936 progpath, _dbus_strerror (errno)); 02937 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 02938 progpath, _dbus_strerror (errno)); 02939 goto out; 02940 } 02941 if (pipe (errors_pipe) < 0) 02942 { 02943 dbus_set_error (error, _dbus_error_from_errno (errno), 02944 "Failed to create a pipe to call %s: %s", 02945 progpath, _dbus_strerror (errno)); 02946 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 02947 progpath, _dbus_strerror (errno)); 02948 goto out; 02949 } 02950 02951 pid = fork (); 02952 if (pid < 0) 02953 { 02954 dbus_set_error (error, _dbus_error_from_errno (errno), 02955 "Failed to fork() to call %s: %s", 02956 progpath, _dbus_strerror (errno)); 02957 _dbus_verbose ("Failed to fork() to call %s: %s\n", 02958 progpath, _dbus_strerror (errno)); 02959 goto out; 02960 } 02961 02962 if (pid == 0) 02963 { 02964 /* child process */ 02965 int maxfds; 02966 int fd; 02967 02968 fd = open ("/dev/null", O_RDWR); 02969 if (fd == -1) 02970 /* huh?! can't open /dev/null? */ 02971 _exit (1); 02972 02973 _dbus_verbose ("/dev/null fd %d opened\n", fd); 02974 02975 /* set-up stdXXX */ 02976 close (result_pipe[READ_END]); 02977 close (errors_pipe[READ_END]); 02978 close (0); /* close stdin */ 02979 close (1); /* close stdout */ 02980 close (2); /* close stderr */ 02981 02982 if (dup2 (fd, 0) == -1) 02983 _exit (1); 02984 if (dup2 (result_pipe[WRITE_END], 1) == -1) 02985 _exit (1); 02986 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 02987 _exit (1); 02988 02989 maxfds = sysconf (_SC_OPEN_MAX); 02990 /* Pick something reasonable if for some reason sysconf 02991 * says unlimited. 02992 */ 02993 if (maxfds < 0) 02994 maxfds = 1024; 02995 /* close all inherited fds */ 02996 for (i = 3; i < maxfds; i++) 02997 close (i); 02998 02999 sigprocmask (SIG_SETMASK, &old_set, NULL); 03000 03001 /* If it looks fully-qualified, try execv first */ 03002 if (progpath[0] == '/') 03003 { 03004 execv (progpath, argv); 03005 /* Ok, that failed. Now if path_fallback is given, let's 03006 * try unqualified. This is mostly a hack to work 03007 * around systems which ship dbus-launch in /usr/bin 03008 * but everything else in /bin (because dbus-launch 03009 * depends on X11). 03010 */ 03011 if (path_fallback) 03012 /* We must have a slash, because we checked above */ 03013 execvp (strrchr (progpath, '/')+1, argv); 03014 } 03015 else 03016 execvp (progpath, argv); 03017 03018 /* still nothing, we failed */ 03019 _exit (1); 03020 } 03021 03022 /* parent process */ 03023 close (result_pipe[WRITE_END]); 03024 close (errors_pipe[WRITE_END]); 03025 result_pipe[WRITE_END] = -1; 03026 errors_pipe[WRITE_END] = -1; 03027 03028 ret = 0; 03029 do 03030 { 03031 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03032 } 03033 while (ret > 0); 03034 03035 /* reap the child process to avoid it lingering as zombie */ 03036 do 03037 { 03038 ret = waitpid (pid, &status, 0); 03039 } 03040 while (ret == -1 && errno == EINTR); 03041 03042 /* We succeeded if the process exited with status 0 and 03043 anything was read */ 03044 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03045 { 03046 /* The process ended with error */ 03047 DBusString error_message; 03048 _dbus_string_init (&error_message); 03049 ret = 0; 03050 do 03051 { 03052 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03053 } 03054 while (ret > 0); 03055 03056 _dbus_string_set_length (result, orig_len); 03057 if (_dbus_string_get_length (&error_message) > 0) 03058 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03059 "%s terminated abnormally with the following error: %s", 03060 progpath, _dbus_string_get_data (&error_message)); 03061 else 03062 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03063 "%s terminated abnormally without any error message", 03064 progpath); 03065 goto out; 03066 } 03067 03068 retval = TRUE; 03069 03070 out: 03071 sigprocmask (SIG_SETMASK, &old_set, NULL); 03072 03073 if (retval) 03074 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03075 else 03076 _DBUS_ASSERT_ERROR_IS_SET (error); 03077 03078 if (result_pipe[0] != -1) 03079 close (result_pipe[0]); 03080 if (result_pipe[1] != -1) 03081 close (result_pipe[1]); 03082 if (errors_pipe[0] != -1) 03083 close (errors_pipe[0]); 03084 if (errors_pipe[1] != -1) 03085 close (errors_pipe[1]); 03086 03087 return retval; 03088 } 03089 03101 dbus_bool_t 03102 _dbus_get_autolaunch_address (DBusString *address, 03103 DBusError *error) 03104 { 03105 static char *argv[6]; 03106 int i; 03107 DBusString uuid; 03108 dbus_bool_t retval; 03109 03110 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03111 retval = FALSE; 03112 03113 if (!_dbus_string_init (&uuid)) 03114 { 03115 _DBUS_SET_OOM (error); 03116 return FALSE; 03117 } 03118 03119 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03120 { 03121 _DBUS_SET_OOM (error); 03122 goto out; 03123 } 03124 03125 i = 0; 03126 argv[i] = "dbus-launch"; 03127 ++i; 03128 argv[i] = "--autolaunch"; 03129 ++i; 03130 argv[i] = _dbus_string_get_data (&uuid); 03131 ++i; 03132 argv[i] = "--binary-syntax"; 03133 ++i; 03134 argv[i] = "--close-stderr"; 03135 ++i; 03136 argv[i] = NULL; 03137 ++i; 03138 03139 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03140 03141 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03142 TRUE, 03143 argv, address, error); 03144 03145 out: 03146 _dbus_string_free (&uuid); 03147 return retval; 03148 } 03149 03168 dbus_bool_t 03169 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03170 dbus_bool_t create_if_not_found, 03171 DBusError *error) 03172 { 03173 DBusString filename; 03174 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03175 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03176 } 03177 03178 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03179 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03180 03200 dbus_bool_t 03201 _dbus_lookup_session_address (dbus_bool_t *supported, 03202 DBusString *address, 03203 DBusError *error) 03204 { 03205 /* On non-Mac Unix platforms, if the session address isn't already 03206 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03207 * fall back to the autolaunch: global default; see 03208 * init_session_address in dbus/dbus-bus.c. */ 03209 *supported = FALSE; 03210 return TRUE; 03211 } 03212 03230 dbus_bool_t 03231 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03232 { 03233 const char *xdg_data_home; 03234 const char *xdg_data_dirs; 03235 DBusString servicedir_path; 03236 03237 if (!_dbus_string_init (&servicedir_path)) 03238 return FALSE; 03239 03240 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03241 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03242 03243 if (xdg_data_dirs != NULL) 03244 { 03245 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03246 goto oom; 03247 03248 if (!_dbus_string_append (&servicedir_path, ":")) 03249 goto oom; 03250 } 03251 else 03252 { 03253 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03254 goto oom; 03255 } 03256 03257 /* 03258 * add configured datadir to defaults 03259 * this may be the same as an xdg dir 03260 * however the config parser should take 03261 * care of duplicates 03262 */ 03263 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) 03264 goto oom; 03265 03266 if (xdg_data_home != NULL) 03267 { 03268 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03269 goto oom; 03270 } 03271 else 03272 { 03273 const DBusString *homedir; 03274 DBusString local_share; 03275 03276 if (!_dbus_homedir_from_current_process (&homedir)) 03277 goto oom; 03278 03279 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03280 goto oom; 03281 03282 _dbus_string_init_const (&local_share, "/.local/share"); 03283 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03284 goto oom; 03285 } 03286 03287 if (!_dbus_split_paths_and_append (&servicedir_path, 03288 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03289 dirs)) 03290 goto oom; 03291 03292 _dbus_string_free (&servicedir_path); 03293 return TRUE; 03294 03295 oom: 03296 _dbus_string_free (&servicedir_path); 03297 return FALSE; 03298 } 03299 03300 03319 dbus_bool_t 03320 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03321 { 03322 const char *xdg_data_dirs; 03323 DBusString servicedir_path; 03324 03325 if (!_dbus_string_init (&servicedir_path)) 03326 return FALSE; 03327 03328 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03329 03330 if (xdg_data_dirs != NULL) 03331 { 03332 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03333 goto oom; 03334 03335 if (!_dbus_string_append (&servicedir_path, ":")) 03336 goto oom; 03337 } 03338 else 03339 { 03340 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03341 goto oom; 03342 } 03343 03344 /* 03345 * add configured datadir to defaults 03346 * this may be the same as an xdg dir 03347 * however the config parser should take 03348 * care of duplicates 03349 */ 03350 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":")) 03351 goto oom; 03352 03353 if (!_dbus_split_paths_and_append (&servicedir_path, 03354 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03355 dirs)) 03356 goto oom; 03357 03358 _dbus_string_free (&servicedir_path); 03359 return TRUE; 03360 03361 oom: 03362 _dbus_string_free (&servicedir_path); 03363 return FALSE; 03364 } 03365 03374 dbus_bool_t 03375 _dbus_append_system_config_file (DBusString *str) 03376 { 03377 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03378 } 03379 03386 dbus_bool_t 03387 _dbus_append_session_config_file (DBusString *str) 03388 { 03389 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03390 } 03391 03399 void 03400 _dbus_flush_caches (void) 03401 { 03402 _dbus_user_database_flush_system (); 03403 } 03404 03418 dbus_bool_t 03419 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03420 DBusCredentials *credentials) 03421 { 03422 DBusString homedir; 03423 DBusString dotdir; 03424 dbus_uid_t uid; 03425 03426 _dbus_assert (credentials != NULL); 03427 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03428 03429 if (!_dbus_string_init (&homedir)) 03430 return FALSE; 03431 03432 uid = _dbus_credentials_get_unix_uid (credentials); 03433 _dbus_assert (uid != DBUS_UID_UNSET); 03434 03435 if (!_dbus_homedir_from_uid (uid, &homedir)) 03436 goto failed; 03437 03438 #ifdef DBUS_BUILD_TESTS 03439 { 03440 const char *override; 03441 03442 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03443 if (override != NULL && *override != '\0') 03444 { 03445 _dbus_string_set_length (&homedir, 0); 03446 if (!_dbus_string_append (&homedir, override)) 03447 goto failed; 03448 03449 _dbus_verbose ("Using fake homedir for testing: %s\n", 03450 _dbus_string_get_const_data (&homedir)); 03451 } 03452 else 03453 { 03454 static dbus_bool_t already_warned = FALSE; 03455 if (!already_warned) 03456 { 03457 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03458 already_warned = TRUE; 03459 } 03460 } 03461 } 03462 #endif 03463 03464 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03465 if (!_dbus_concat_dir_and_file (&homedir, 03466 &dotdir)) 03467 goto failed; 03468 03469 if (!_dbus_string_copy (&homedir, 0, 03470 directory, _dbus_string_get_length (directory))) { 03471 goto failed; 03472 } 03473 03474 _dbus_string_free (&homedir); 03475 return TRUE; 03476 03477 failed: 03478 _dbus_string_free (&homedir); 03479 return FALSE; 03480 } 03481 03482 03489 dbus_bool_t 03490 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03491 { 03492 return errno == EAGAIN || errno == EWOULDBLOCK; 03493 } 03494 03495 /* tests in dbus-sysdeps-util.c */