00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-sysdeps-unix.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-protocol.h"
00030 #include "dbus-transport.h"
00031 #include "dbus-string.h"
00032 #include "dbus-userdb.h"
00033 #include "dbus-list.h"
00034 #include <sys/types.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <signal.h>
00038 #include <unistd.h>
00039 #include <stdio.h>
00040 #include <fcntl.h>
00041 #include <sys/socket.h>
00042 #include <dirent.h>
00043 #include <sys/un.h>
00044 #include <pwd.h>
00045 #include <time.h>
00046 #include <locale.h>
00047 #include <sys/time.h>
00048 #include <sys/stat.h>
00049 #include <sys/wait.h>
00050 #include <netinet/in.h>
00051 #include <netdb.h>
00052 #include <grp.h>
00053
00054 #ifdef HAVE_ERRNO_H
00055 #include <errno.h>
00056 #endif
00057 #ifdef HAVE_WRITEV
00058 #include <sys/uio.h>
00059 #endif
00060 #ifdef HAVE_POLL
00061 #include <sys/poll.h>
00062 #endif
00063 #ifdef HAVE_BACKTRACE
00064 #include <execinfo.h>
00065 #endif
00066 #ifdef HAVE_GETPEERUCRED
00067 #include <ucred.h>
00068 #endif
00069
00070 #ifndef O_BINARY
00071 #define O_BINARY 0
00072 #endif
00073
00074 #ifndef HAVE_SOCKLEN_T
00075 #define socklen_t int
00076 #endif
00077
00078 static dbus_bool_t
00079 _dbus_open_socket (int *fd_p,
00080 int domain,
00081 int type,
00082 int protocol,
00083 DBusError *error)
00084 {
00085 *fd_p = socket (domain, type, protocol);
00086 if (*fd_p >= 0)
00087 {
00088 return TRUE;
00089 }
00090 else
00091 {
00092 dbus_set_error(error,
00093 _dbus_error_from_errno (errno),
00094 "Failed to open socket: %s",
00095 _dbus_strerror (errno));
00096 return FALSE;
00097 }
00098 }
00099
00100 dbus_bool_t
00101 _dbus_open_tcp_socket (int *fd,
00102 DBusError *error)
00103 {
00104 return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00105 }
00106
00114 dbus_bool_t
00115 _dbus_open_unix_socket (int *fd,
00116 DBusError *error)
00117 {
00118 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00119 }
00120
00129 dbus_bool_t
00130 _dbus_close_socket (int fd,
00131 DBusError *error)
00132 {
00133 return _dbus_close (fd, error);
00134 }
00135
00145 int
00146 _dbus_read_socket (int fd,
00147 DBusString *buffer,
00148 int count)
00149 {
00150 return _dbus_read (fd, buffer, count);
00151 }
00152
00163 int
00164 _dbus_write_socket (int fd,
00165 const DBusString *buffer,
00166 int start,
00167 int len)
00168 {
00169 return _dbus_write (fd, buffer, start, len);
00170 }
00171
00185 int
00186 _dbus_write_socket_two (int fd,
00187 const DBusString *buffer1,
00188 int start1,
00189 int len1,
00190 const DBusString *buffer2,
00191 int start2,
00192 int len2)
00193 {
00194 return _dbus_write_two (fd, buffer1, start1, len1,
00195 buffer2, start2, len2);
00196 }
00197
00198
00215 int
00216 _dbus_read (int fd,
00217 DBusString *buffer,
00218 int count)
00219 {
00220 int bytes_read;
00221 int start;
00222 char *data;
00223
00224 _dbus_assert (count >= 0);
00225
00226 start = _dbus_string_get_length (buffer);
00227
00228 if (!_dbus_string_lengthen (buffer, count))
00229 {
00230 errno = ENOMEM;
00231 return -1;
00232 }
00233
00234 data = _dbus_string_get_data_len (buffer, start, count);
00235
00236 again:
00237
00238 bytes_read = read (fd, data, count);
00239
00240 if (bytes_read < 0)
00241 {
00242 if (errno == EINTR)
00243 goto again;
00244 else
00245 {
00246
00247 _dbus_string_set_length (buffer, start);
00248 return -1;
00249 }
00250 }
00251 else
00252 {
00253
00254 _dbus_string_set_length (buffer, start + bytes_read);
00255
00256 #if 0
00257 if (bytes_read > 0)
00258 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00259 #endif
00260
00261 return bytes_read;
00262 }
00263 }
00264
00275 int
00276 _dbus_write (int fd,
00277 const DBusString *buffer,
00278 int start,
00279 int len)
00280 {
00281 const char *data;
00282 int bytes_written;
00283
00284 data = _dbus_string_get_const_data_len (buffer, start, len);
00285
00286 again:
00287
00288 bytes_written = write (fd, data, len);
00289
00290 if (bytes_written < 0 && errno == EINTR)
00291 goto again;
00292
00293 #if 0
00294 if (bytes_written > 0)
00295 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00296 #endif
00297
00298 return bytes_written;
00299 }
00300
00321 int
00322 _dbus_write_two (int fd,
00323 const DBusString *buffer1,
00324 int start1,
00325 int len1,
00326 const DBusString *buffer2,
00327 int start2,
00328 int len2)
00329 {
00330 _dbus_assert (buffer1 != NULL);
00331 _dbus_assert (start1 >= 0);
00332 _dbus_assert (start2 >= 0);
00333 _dbus_assert (len1 >= 0);
00334 _dbus_assert (len2 >= 0);
00335
00336 #ifdef HAVE_WRITEV
00337 {
00338 struct iovec vectors[2];
00339 const char *data1;
00340 const char *data2;
00341 int bytes_written;
00342
00343 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00344
00345 if (buffer2 != NULL)
00346 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00347 else
00348 {
00349 data2 = NULL;
00350 start2 = 0;
00351 len2 = 0;
00352 }
00353
00354 vectors[0].iov_base = (char*) data1;
00355 vectors[0].iov_len = len1;
00356 vectors[1].iov_base = (char*) data2;
00357 vectors[1].iov_len = len2;
00358
00359 again:
00360
00361 bytes_written = writev (fd,
00362 vectors,
00363 data2 ? 2 : 1);
00364
00365 if (bytes_written < 0 && errno == EINTR)
00366 goto again;
00367
00368 return bytes_written;
00369 }
00370 #else
00371 {
00372 int ret1;
00373
00374 ret1 = _dbus_write (fd, buffer1, start1, len1);
00375 if (ret1 == len1 && buffer2 != NULL)
00376 {
00377 ret2 = _dbus_write (fd, buffer2, start2, len2);
00378 if (ret2 < 0)
00379 ret2 = 0;
00380
00381 return ret1 + ret2;
00382 }
00383 else
00384 return ret1;
00385 }
00386 #endif
00387 }
00388
00389 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00390
00418 int
00419 _dbus_connect_unix_socket (const char *path,
00420 dbus_bool_t abstract,
00421 DBusError *error)
00422 {
00423 int fd;
00424 size_t path_len;
00425 struct sockaddr_un addr;
00426
00427 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00428
00429 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00430 path, abstract);
00431
00432
00433 if (!_dbus_open_unix_socket (&fd, error))
00434 {
00435 _DBUS_ASSERT_ERROR_IS_SET(error);
00436 return -1;
00437 }
00438 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00439
00440 _DBUS_ZERO (addr);
00441 addr.sun_family = AF_UNIX;
00442 path_len = strlen (path);
00443
00444 if (abstract)
00445 {
00446 #ifdef HAVE_ABSTRACT_SOCKETS
00447 addr.sun_path[0] = '\0';
00448 path_len++;
00449
00450 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00451 {
00452 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00453 "Abstract socket name too long\n");
00454 _dbus_close (fd, NULL);
00455 return -1;
00456 }
00457
00458 strncpy (&addr.sun_path[1], path, path_len);
00459
00460 #else
00461 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00462 "Operating system does not support abstract socket namespace\n");
00463 _dbus_close (fd, NULL);
00464 return -1;
00465 #endif
00466 }
00467 else
00468 {
00469 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00470 {
00471 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00472 "Socket name too long\n");
00473 _dbus_close (fd, NULL);
00474 return -1;
00475 }
00476
00477 strncpy (addr.sun_path, path, path_len);
00478 }
00479
00480 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00481 {
00482 dbus_set_error (error,
00483 _dbus_error_from_errno (errno),
00484 "Failed to connect to socket %s: %s",
00485 path, _dbus_strerror (errno));
00486
00487 _dbus_close (fd, NULL);
00488 fd = -1;
00489
00490 return -1;
00491 }
00492
00493 if (!_dbus_set_fd_nonblocking (fd, error))
00494 {
00495 _DBUS_ASSERT_ERROR_IS_SET (error);
00496
00497 _dbus_close (fd, NULL);
00498 fd = -1;
00499
00500 return -1;
00501 }
00502
00503 return fd;
00504 }
00505
00515 static dbus_bool_t
00516 _dbus_set_local_creds (int fd, dbus_bool_t on)
00517 {
00518 dbus_bool_t retval = TRUE;
00519
00520 #if defined(HAVE_CMSGCRED)
00521
00522
00523
00524 #elif defined(LOCAL_CREDS)
00525 int val = on ? 1 : 0;
00526 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00527 {
00528 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00529 retval = FALSE;
00530 }
00531 else
00532 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00533 on ? "enabled" : "disabled", fd);
00534 #endif
00535
00536 return retval;
00537 }
00538
00554 int
00555 _dbus_listen_unix_socket (const char *path,
00556 dbus_bool_t abstract,
00557 DBusError *error)
00558 {
00559 int listen_fd;
00560 struct sockaddr_un addr;
00561 size_t path_len;
00562
00563 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00564
00565 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00566 path, abstract);
00567
00568 if (!_dbus_open_unix_socket (&listen_fd, error))
00569 {
00570 _DBUS_ASSERT_ERROR_IS_SET(error);
00571 return -1;
00572 }
00573 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00574
00575 _DBUS_ZERO (addr);
00576 addr.sun_family = AF_UNIX;
00577 path_len = strlen (path);
00578
00579 if (abstract)
00580 {
00581 #ifdef HAVE_ABSTRACT_SOCKETS
00582
00583
00584
00585 addr.sun_path[0] = '\0';
00586 path_len++;
00587
00588 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00589 {
00590 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00591 "Abstract socket name too long\n");
00592 _dbus_close (listen_fd, NULL);
00593 return -1;
00594 }
00595
00596 strncpy (&addr.sun_path[1], path, path_len);
00597
00598 #else
00599 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00600 "Operating system does not support abstract socket namespace\n");
00601 _dbus_close (listen_fd, NULL);
00602 return -1;
00603 #endif
00604 }
00605 else
00606 {
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 {
00618 struct stat sb;
00619
00620 if (stat (path, &sb) == 0 &&
00621 S_ISSOCK (sb.st_mode))
00622 unlink (path);
00623 }
00624
00625 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00626 {
00627 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00628 "Abstract socket name too long\n");
00629 _dbus_close (listen_fd, NULL);
00630 return -1;
00631 }
00632
00633 strncpy (addr.sun_path, path, path_len);
00634 }
00635
00636 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00637 {
00638 dbus_set_error (error, _dbus_error_from_errno (errno),
00639 "Failed to bind socket \"%s\": %s",
00640 path, _dbus_strerror (errno));
00641 _dbus_close (listen_fd, NULL);
00642 return -1;
00643 }
00644
00645 if (listen (listen_fd, 30 ) < 0)
00646 {
00647 dbus_set_error (error, _dbus_error_from_errno (errno),
00648 "Failed to listen on socket \"%s\": %s",
00649 path, _dbus_strerror (errno));
00650 _dbus_close (listen_fd, NULL);
00651 return -1;
00652 }
00653
00654 if (!_dbus_set_local_creds (listen_fd, TRUE))
00655 {
00656 dbus_set_error (error, _dbus_error_from_errno (errno),
00657 "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00658 path, _dbus_strerror (errno));
00659 close (listen_fd);
00660 return -1;
00661 }
00662
00663 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00664 {
00665 _DBUS_ASSERT_ERROR_IS_SET (error);
00666 _dbus_close (listen_fd, NULL);
00667 return -1;
00668 }
00669
00670
00671
00672
00673 if (!abstract && chmod (path, 0777) < 0)
00674 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00675 path);
00676
00677 return listen_fd;
00678 }
00679
00690 int
00691 _dbus_connect_tcp_socket (const char *host,
00692 dbus_uint32_t port,
00693 DBusError *error)
00694 {
00695 int fd;
00696 struct sockaddr_in addr;
00697 struct hostent *he;
00698 struct in_addr *haddr;
00699
00700 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00701
00702
00703 if (!_dbus_open_tcp_socket (&fd, error))
00704 {
00705 _DBUS_ASSERT_ERROR_IS_SET(error);
00706
00707 return -1;
00708 }
00709 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00710
00711 if (host == NULL)
00712 host = "localhost";
00713
00714 he = gethostbyname (host);
00715 if (he == NULL)
00716 {
00717 dbus_set_error (error,
00718 _dbus_error_from_errno (errno),
00719 "Failed to lookup hostname: %s",
00720 host);
00721 _dbus_close (fd, NULL);
00722 return -1;
00723 }
00724
00725 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00726
00727 _DBUS_ZERO (addr);
00728 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00729 addr.sin_family = AF_INET;
00730 addr.sin_port = htons (port);
00731
00732 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00733 {
00734 dbus_set_error (error,
00735 _dbus_error_from_errno (errno),
00736 "Failed to connect to socket %s:%d %s",
00737 host, port, _dbus_strerror (errno));
00738
00739 _dbus_close (fd, NULL);
00740 fd = -1;
00741
00742 return -1;
00743 }
00744
00745 if (!_dbus_set_fd_nonblocking (fd, error))
00746 {
00747 _dbus_close (fd, NULL);
00748 fd = -1;
00749
00750 return -1;
00751 }
00752
00753 return fd;
00754 }
00755
00768 int
00769 _dbus_listen_tcp_socket (const char *host,
00770 dbus_uint32_t *port,
00771 DBusError *error)
00772 {
00773 int listen_fd;
00774 struct sockaddr_in addr;
00775 struct hostent *he;
00776 struct in_addr *haddr;
00777 socklen_t len = (socklen_t) sizeof (struct sockaddr);
00778
00779 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00780
00781
00782 if (!_dbus_open_tcp_socket (&listen_fd, error))
00783 {
00784 _DBUS_ASSERT_ERROR_IS_SET(error);
00785 return -1;
00786 }
00787 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00788
00789 he = gethostbyname (host);
00790 if (he == NULL)
00791 {
00792 dbus_set_error (error,
00793 _dbus_error_from_errno (errno),
00794 "Failed to lookup hostname: %s",
00795 host);
00796 _dbus_close (listen_fd, NULL);
00797 return -1;
00798 }
00799
00800 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00801
00802 _DBUS_ZERO (addr);
00803 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00804 addr.sin_family = AF_INET;
00805 addr.sin_port = htons (*port);
00806
00807 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00808 {
00809 dbus_set_error (error, _dbus_error_from_errno (errno),
00810 "Failed to bind socket \"%s:%d\": %s",
00811 host, *port, _dbus_strerror (errno));
00812 _dbus_close (listen_fd, NULL);
00813 return -1;
00814 }
00815
00816 if (listen (listen_fd, 30 ) < 0)
00817 {
00818 dbus_set_error (error, _dbus_error_from_errno (errno),
00819 "Failed to listen on socket \"%s:%d\": %s",
00820 host, *port, _dbus_strerror (errno));
00821 _dbus_close (listen_fd, NULL);
00822 return -1;
00823 }
00824
00825 getsockname(listen_fd, (struct sockaddr*) &addr, &len);
00826 *port = (dbus_uint32_t) ntohs(addr.sin_port);
00827
00828 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00829 {
00830 _dbus_close (listen_fd, NULL);
00831 return -1;
00832 }
00833
00834 return listen_fd;
00835 }
00836
00837 static dbus_bool_t
00838 write_credentials_byte (int server_fd,
00839 DBusError *error)
00840 {
00841 int bytes_written;
00842 char buf[1] = { '\0' };
00843 #if defined(HAVE_CMSGCRED)
00844 struct {
00845 struct cmsghdr hdr;
00846 struct cmsgcred cred;
00847 } cmsg;
00848 struct iovec iov;
00849 struct msghdr msg;
00850 iov.iov_base = buf;
00851 iov.iov_len = 1;
00852
00853 memset (&msg, 0, sizeof (msg));
00854 msg.msg_iov = &iov;
00855 msg.msg_iovlen = 1;
00856
00857 msg.msg_control = &cmsg;
00858 msg.msg_controllen = sizeof (cmsg);
00859 memset (&cmsg, 0, sizeof (cmsg));
00860 cmsg.hdr.cmsg_len = sizeof (cmsg);
00861 cmsg.hdr.cmsg_level = SOL_SOCKET;
00862 cmsg.hdr.cmsg_type = SCM_CREDS;
00863 #endif
00864
00865 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00866
00867 again:
00868
00869 #if defined(HAVE_CMSGCRED)
00870 bytes_written = sendmsg (server_fd, &msg, 0);
00871 #else
00872 bytes_written = write (server_fd, buf, 1);
00873 #endif
00874
00875 if (bytes_written < 0 && errno == EINTR)
00876 goto again;
00877
00878 if (bytes_written < 0)
00879 {
00880 dbus_set_error (error, _dbus_error_from_errno (errno),
00881 "Failed to write credentials byte: %s",
00882 _dbus_strerror (errno));
00883 return FALSE;
00884 }
00885 else if (bytes_written == 0)
00886 {
00887 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00888 "wrote zero bytes writing credentials byte");
00889 return FALSE;
00890 }
00891 else
00892 {
00893 _dbus_assert (bytes_written == 1);
00894 _dbus_verbose ("wrote credentials byte\n");
00895 return TRUE;
00896 }
00897 }
00898
00917 dbus_bool_t
00918 _dbus_read_credentials_unix_socket (int client_fd,
00919 DBusCredentials *credentials,
00920 DBusError *error)
00921 {
00922 struct msghdr msg;
00923 struct iovec iov;
00924 char buf;
00925
00926 #ifdef HAVE_CMSGCRED
00927 struct {
00928 struct cmsghdr hdr;
00929 struct cmsgcred cred;
00930 } cmsg;
00931
00932 #elif defined(LOCAL_CREDS)
00933 struct {
00934 struct cmsghdr hdr;
00935 struct sockcred cred;
00936 } cmsg;
00937 #endif
00938
00939 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00940
00941
00942
00943
00944
00945 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00946 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00947 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00948
00949 _dbus_credentials_clear (credentials);
00950
00951
00952
00953
00954
00955
00956
00957 iov.iov_base = &buf;
00958 iov.iov_len = 1;
00959
00960 memset (&msg, 0, sizeof (msg));
00961 msg.msg_iov = &iov;
00962 msg.msg_iovlen = 1;
00963
00964 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00965 memset (&cmsg, 0, sizeof (cmsg));
00966 msg.msg_control = &cmsg;
00967 msg.msg_controllen = sizeof (cmsg);
00968 #endif
00969
00970 again:
00971 if (recvmsg (client_fd, &msg, 0) < 0)
00972 {
00973 if (errno == EINTR)
00974 goto again;
00975
00976 dbus_set_error (error, _dbus_error_from_errno (errno),
00977 "Failed to read credentials byte: %s",
00978 _dbus_strerror (errno));
00979 return FALSE;
00980 }
00981
00982 if (buf != '\0')
00983 {
00984 dbus_set_error (error, DBUS_ERROR_FAILED,
00985 "Credentials byte was not nul");
00986 return FALSE;
00987 }
00988
00989 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
00990 if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00991 {
00992 dbus_set_error (error, DBUS_ERROR_FAILED,
00993 "Message from recvmsg() was not SCM_CREDS");
00994 return FALSE;
00995 }
00996 #endif
00997
00998 _dbus_verbose ("read credentials byte\n");
00999
01000 {
01001 #ifdef SO_PEERCRED
01002 struct ucred cr;
01003 int cr_len = sizeof (cr);
01004
01005 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01006 cr_len == sizeof (cr))
01007 {
01008 credentials->pid = cr.pid;
01009 credentials->uid = cr.uid;
01010 credentials->gid = cr.gid;
01011 }
01012 else
01013 {
01014 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01015 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01016 }
01017 #elif defined(HAVE_CMSGCRED)
01018 credentials->pid = cmsg.cred.cmcred_pid;
01019 credentials->uid = cmsg.cred.cmcred_euid;
01020 credentials->gid = cmsg.cred.cmcred_groups[0];
01021 #elif defined(LOCAL_CREDS)
01022 credentials->pid = DBUS_PID_UNSET;
01023 credentials->uid = cmsg.cred.sc_uid;
01024 credentials->gid = cmsg.cred.sc_gid;
01025
01026
01027 _dbus_set_local_creds (client_fd, FALSE);
01028 #elif defined(HAVE_GETPEEREID)
01029 uid_t euid;
01030 gid_t egid;
01031 if (getpeereid (client_fd, &euid, &egid) == 0)
01032 {
01033 credentials->uid = euid;
01034 credentials->gid = egid;
01035 }
01036 else
01037 {
01038 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01039 }
01040 #elif defined(HAVE_GETPEERUCRED)
01041 ucred_t * ucred = NULL;
01042 if (getpeerucred (client_fd, &ucred) == 0)
01043 {
01044 credentials->pid = ucred_getpid (ucred);
01045 credentials->uid = ucred_geteuid (ucred);
01046 credentials->gid = ucred_getegid (ucred);
01047 }
01048 else
01049 {
01050 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01051 }
01052 if (ucred != NULL)
01053 ucred_free (ucred);
01054 #else
01055 _dbus_verbose ("Socket credentials not supported on this OS\n");
01056 #endif
01057 }
01058
01059 _dbus_verbose ("Credentials:"
01060 " pid "DBUS_PID_FORMAT
01061 " uid "DBUS_UID_FORMAT
01062 " gid "DBUS_GID_FORMAT"\n",
01063 credentials->pid,
01064 credentials->uid,
01065 credentials->gid);
01066
01067 return TRUE;
01068 }
01069
01087 dbus_bool_t
01088 _dbus_send_credentials_unix_socket (int server_fd,
01089 DBusError *error)
01090 {
01091 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01092
01093 if (write_credentials_byte (server_fd, error))
01094 return TRUE;
01095 else
01096 return FALSE;
01097 }
01098
01106 int
01107 _dbus_accept (int listen_fd)
01108 {
01109 int client_fd;
01110 struct sockaddr addr;
01111 socklen_t addrlen;
01112
01113 addrlen = sizeof (addr);
01114
01115 retry:
01116 client_fd = accept (listen_fd, &addr, &addrlen);
01117
01118 if (client_fd < 0)
01119 {
01120 if (errno == EINTR)
01121 goto retry;
01122 }
01123
01124 return client_fd;
01125 }
01126
01135 dbus_bool_t
01136 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01137 {
01138 const char *directory;
01139 struct stat sb;
01140
01141 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01142
01143 directory = _dbus_string_get_const_data (dir);
01144
01145 if (stat (directory, &sb) < 0)
01146 {
01147 dbus_set_error (error, _dbus_error_from_errno (errno),
01148 "%s", _dbus_strerror (errno));
01149
01150 return FALSE;
01151 }
01152
01153 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01154 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01155 {
01156 dbus_set_error (error, DBUS_ERROR_FAILED,
01157 "%s directory is not private to the user", directory);
01158 return FALSE;
01159 }
01160
01161 return TRUE;
01162 }
01163
01164 static dbus_bool_t
01165 fill_user_info_from_passwd (struct passwd *p,
01166 DBusUserInfo *info,
01167 DBusError *error)
01168 {
01169 _dbus_assert (p->pw_name != NULL);
01170 _dbus_assert (p->pw_dir != NULL);
01171
01172 info->uid = p->pw_uid;
01173 info->primary_gid = p->pw_gid;
01174 info->username = _dbus_strdup (p->pw_name);
01175 info->homedir = _dbus_strdup (p->pw_dir);
01176
01177 if (info->username == NULL ||
01178 info->homedir == NULL)
01179 {
01180 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01181 return FALSE;
01182 }
01183
01184 return TRUE;
01185 }
01186
01187 static dbus_bool_t
01188 fill_user_info (DBusUserInfo *info,
01189 dbus_uid_t uid,
01190 const DBusString *username,
01191 DBusError *error)
01192 {
01193 const char *username_c;
01194
01195
01196 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01197 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01198
01199 info->uid = DBUS_UID_UNSET;
01200 info->primary_gid = DBUS_GID_UNSET;
01201 info->group_ids = NULL;
01202 info->n_group_ids = 0;
01203 info->username = NULL;
01204 info->homedir = NULL;
01205
01206 if (username != NULL)
01207 username_c = _dbus_string_get_const_data (username);
01208 else
01209 username_c = NULL;
01210
01211
01212
01213
01214
01215
01216 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01217 {
01218 struct passwd *p;
01219 int result;
01220 char buf[1024];
01221 struct passwd p_str;
01222
01223 p = NULL;
01224 #ifdef HAVE_POSIX_GETPWNAM_R
01225 if (uid != DBUS_UID_UNSET)
01226 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01227 &p);
01228 else
01229 result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01230 &p);
01231 #else
01232 if (uid != DBUS_UID_UNSET)
01233 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01234 else
01235 p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01236 result = 0;
01237 #endif
01238 if (result == 0 && p == &p_str)
01239 {
01240 if (!fill_user_info_from_passwd (p, info, error))
01241 return FALSE;
01242 }
01243 else
01244 {
01245 dbus_set_error (error, _dbus_error_from_errno (errno),
01246 "User \"%s\" unknown or no memory to allocate password entry\n",
01247 username_c ? username_c : "???");
01248 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01249 return FALSE;
01250 }
01251 }
01252 #else
01253 {
01254
01255 struct passwd *p;
01256
01257 if (uid != DBUS_UID_UNSET)
01258 p = getpwuid (uid);
01259 else
01260 p = getpwnam (username_c);
01261
01262 if (p != NULL)
01263 {
01264 if (!fill_user_info_from_passwd (p, info, error))
01265 return FALSE;
01266 }
01267 else
01268 {
01269 dbus_set_error (error, _dbus_error_from_errno (errno),
01270 "User \"%s\" unknown or no memory to allocate password entry\n",
01271 username_c ? username_c : "???");
01272 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01273 return FALSE;
01274 }
01275 }
01276 #endif
01277
01278
01279 username_c = info->username;
01280
01281 #ifdef HAVE_GETGROUPLIST
01282 {
01283 gid_t *buf;
01284 int buf_count;
01285 int i;
01286
01287 buf_count = 17;
01288 buf = dbus_new (gid_t, buf_count);
01289 if (buf == NULL)
01290 {
01291 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01292 goto failed;
01293 }
01294
01295 if (getgrouplist (username_c,
01296 info->primary_gid,
01297 buf, &buf_count) < 0)
01298 {
01299 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01300 if (new == NULL)
01301 {
01302 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01303 dbus_free (buf);
01304 goto failed;
01305 }
01306
01307 buf = new;
01308
01309 errno = 0;
01310 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01311 {
01312 dbus_set_error (error,
01313 _dbus_error_from_errno (errno),
01314 "Failed to get groups for username \"%s\" primary GID "
01315 DBUS_GID_FORMAT ": %s\n",
01316 username_c, info->primary_gid,
01317 _dbus_strerror (errno));
01318 dbus_free (buf);
01319 goto failed;
01320 }
01321 }
01322
01323 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01324 if (info->group_ids == NULL)
01325 {
01326 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01327 dbus_free (buf);
01328 goto failed;
01329 }
01330
01331 for (i = 0; i < buf_count; ++i)
01332 info->group_ids[i] = buf[i];
01333
01334 info->n_group_ids = buf_count;
01335
01336 dbus_free (buf);
01337 }
01338 #else
01339 {
01340
01341 info->group_ids = dbus_new (dbus_gid_t, 1);
01342 if (info->group_ids == NULL)
01343 {
01344 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01345 goto failed;
01346 }
01347
01348 info->n_group_ids = 1;
01349
01350 (info->group_ids)[0] = info->primary_gid;
01351 }
01352 #endif
01353
01354 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01355
01356 return TRUE;
01357
01358 failed:
01359 _DBUS_ASSERT_ERROR_IS_SET (error);
01360 return FALSE;
01361 }
01362
01371 dbus_bool_t
01372 _dbus_user_info_fill (DBusUserInfo *info,
01373 const DBusString *username,
01374 DBusError *error)
01375 {
01376 return fill_user_info (info, DBUS_UID_UNSET,
01377 username, error);
01378 }
01379
01388 dbus_bool_t
01389 _dbus_user_info_fill_uid (DBusUserInfo *info,
01390 dbus_uid_t uid,
01391 DBusError *error)
01392 {
01393 return fill_user_info (info, uid,
01394 NULL, error);
01395 }
01396
01402 void
01403 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01404 {
01405
01406
01407
01408
01409 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01410 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01411 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01412
01413 credentials->pid = getpid ();
01414 credentials->uid = getuid ();
01415 credentials->gid = getgid ();
01416 }
01417
01422 unsigned long
01423 _dbus_getpid (void)
01424 {
01425 return getpid ();
01426 }
01427
01431 dbus_uid_t
01432 _dbus_getuid (void)
01433 {
01434 return getuid ();
01435 }
01436
01437 #ifdef DBUS_BUILD_TESTS
01438
01441 dbus_gid_t
01442 _dbus_getgid (void)
01443 {
01444 return getgid ();
01445 }
01446 #endif
01447
01456 int
01457 _dbus_poll (DBusPollFD *fds,
01458 int n_fds,
01459 int timeout_milliseconds)
01460 {
01461 #ifdef HAVE_POLL
01462
01463
01464
01465
01466 if (_DBUS_POLLIN == POLLIN &&
01467 _DBUS_POLLPRI == POLLPRI &&
01468 _DBUS_POLLOUT == POLLOUT &&
01469 _DBUS_POLLERR == POLLERR &&
01470 _DBUS_POLLHUP == POLLHUP &&
01471 _DBUS_POLLNVAL == POLLNVAL &&
01472 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01473 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01474 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01475 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01476 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01477 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01478 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01479 {
01480 return poll ((struct pollfd*) fds,
01481 n_fds,
01482 timeout_milliseconds);
01483 }
01484 else
01485 {
01486
01487
01488
01489 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01490 return -1;
01491 }
01492 #else
01493
01494 fd_set read_set, write_set, err_set;
01495 int max_fd = 0;
01496 int i;
01497 struct timeval tv;
01498 int ready;
01499
01500 FD_ZERO (&read_set);
01501 FD_ZERO (&write_set);
01502 FD_ZERO (&err_set);
01503
01504 for (i = 0; i < n_fds; i++)
01505 {
01506 DBusPollFD *fdp = &fds[i];
01507
01508 if (fdp->events & _DBUS_POLLIN)
01509 FD_SET (fdp->fd, &read_set);
01510
01511 if (fdp->events & _DBUS_POLLOUT)
01512 FD_SET (fdp->fd, &write_set);
01513
01514 FD_SET (fdp->fd, &err_set);
01515
01516 max_fd = MAX (max_fd, fdp->fd);
01517 }
01518
01519 tv.tv_sec = timeout_milliseconds / 1000;
01520 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01521
01522 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01523 timeout_milliseconds < 0 ? NULL : &tv);
01524
01525 if (ready > 0)
01526 {
01527 for (i = 0; i < n_fds; i++)
01528 {
01529 DBusPollFD *fdp = &fds[i];
01530
01531 fdp->revents = 0;
01532
01533 if (FD_ISSET (fdp->fd, &read_set))
01534 fdp->revents |= _DBUS_POLLIN;
01535
01536 if (FD_ISSET (fdp->fd, &write_set))
01537 fdp->revents |= _DBUS_POLLOUT;
01538
01539 if (FD_ISSET (fdp->fd, &err_set))
01540 fdp->revents |= _DBUS_POLLERR;
01541 }
01542 }
01543
01544 return ready;
01545 #endif
01546 }
01547
01554 void
01555 _dbus_get_current_time (long *tv_sec,
01556 long *tv_usec)
01557 {
01558 struct timeval t;
01559
01560 gettimeofday (&t, NULL);
01561
01562 if (tv_sec)
01563 *tv_sec = t.tv_sec;
01564 if (tv_usec)
01565 *tv_usec = t.tv_usec;
01566 }
01567
01578 dbus_bool_t
01579 _dbus_file_get_contents (DBusString *str,
01580 const DBusString *filename,
01581 DBusError *error)
01582 {
01583 int fd;
01584 struct stat sb;
01585 int orig_len;
01586 int total;
01587 const char *filename_c;
01588
01589 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01590
01591 filename_c = _dbus_string_get_const_data (filename);
01592
01593
01594 fd = open (filename_c, O_RDONLY | O_BINARY);
01595 if (fd < 0)
01596 {
01597 dbus_set_error (error, _dbus_error_from_errno (errno),
01598 "Failed to open \"%s\": %s",
01599 filename_c,
01600 _dbus_strerror (errno));
01601 return FALSE;
01602 }
01603
01604 if (fstat (fd, &sb) < 0)
01605 {
01606 dbus_set_error (error, _dbus_error_from_errno (errno),
01607 "Failed to stat \"%s\": %s",
01608 filename_c,
01609 _dbus_strerror (errno));
01610
01611 _dbus_verbose ("fstat() failed: %s",
01612 _dbus_strerror (errno));
01613
01614 _dbus_close (fd, NULL);
01615
01616 return FALSE;
01617 }
01618
01619 if (sb.st_size > _DBUS_ONE_MEGABYTE)
01620 {
01621 dbus_set_error (error, DBUS_ERROR_FAILED,
01622 "File size %lu of \"%s\" is too large.",
01623 (unsigned long) sb.st_size, filename_c);
01624 _dbus_close (fd, NULL);
01625 return FALSE;
01626 }
01627
01628 total = 0;
01629 orig_len = _dbus_string_get_length (str);
01630 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
01631 {
01632 int bytes_read;
01633
01634 while (total < (int) sb.st_size)
01635 {
01636 bytes_read = _dbus_read (fd, str,
01637 sb.st_size - total);
01638 if (bytes_read <= 0)
01639 {
01640 dbus_set_error (error, _dbus_error_from_errno (errno),
01641 "Error reading \"%s\": %s",
01642 filename_c,
01643 _dbus_strerror (errno));
01644
01645 _dbus_verbose ("read() failed: %s",
01646 _dbus_strerror (errno));
01647
01648 _dbus_close (fd, NULL);
01649 _dbus_string_set_length (str, orig_len);
01650 return FALSE;
01651 }
01652 else
01653 total += bytes_read;
01654 }
01655
01656 _dbus_close (fd, NULL);
01657 return TRUE;
01658 }
01659 else if (sb.st_size != 0)
01660 {
01661 _dbus_verbose ("Can only open regular files at the moment.\n");
01662 dbus_set_error (error, DBUS_ERROR_FAILED,
01663 "\"%s\" is not a regular file",
01664 filename_c);
01665 _dbus_close (fd, NULL);
01666 return FALSE;
01667 }
01668 else
01669 {
01670 _dbus_close (fd, NULL);
01671 return TRUE;
01672 }
01673 }
01674
01684 dbus_bool_t
01685 _dbus_string_save_to_file (const DBusString *str,
01686 const DBusString *filename,
01687 DBusError *error)
01688 {
01689 int fd;
01690 int bytes_to_write;
01691 const char *filename_c;
01692 DBusString tmp_filename;
01693 const char *tmp_filename_c;
01694 int total;
01695 dbus_bool_t need_unlink;
01696 dbus_bool_t retval;
01697
01698 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01699
01700 fd = -1;
01701 retval = FALSE;
01702 need_unlink = FALSE;
01703
01704 if (!_dbus_string_init (&tmp_filename))
01705 {
01706 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01707 return FALSE;
01708 }
01709
01710 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
01711 {
01712 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01713 _dbus_string_free (&tmp_filename);
01714 return FALSE;
01715 }
01716
01717 if (!_dbus_string_append (&tmp_filename, "."))
01718 {
01719 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01720 _dbus_string_free (&tmp_filename);
01721 return FALSE;
01722 }
01723
01724 #define N_TMP_FILENAME_RANDOM_BYTES 8
01725 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
01726 {
01727 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01728 _dbus_string_free (&tmp_filename);
01729 return FALSE;
01730 }
01731
01732 filename_c = _dbus_string_get_const_data (filename);
01733 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
01734
01735 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01736 0600);
01737 if (fd < 0)
01738 {
01739 dbus_set_error (error, _dbus_error_from_errno (errno),
01740 "Could not create %s: %s", tmp_filename_c,
01741 _dbus_strerror (errno));
01742 goto out;
01743 }
01744
01745 need_unlink = TRUE;
01746
01747 total = 0;
01748 bytes_to_write = _dbus_string_get_length (str);
01749
01750 while (total < bytes_to_write)
01751 {
01752 int bytes_written;
01753
01754 bytes_written = _dbus_write (fd, str, total,
01755 bytes_to_write - total);
01756
01757 if (bytes_written <= 0)
01758 {
01759 dbus_set_error (error, _dbus_error_from_errno (errno),
01760 "Could not write to %s: %s", tmp_filename_c,
01761 _dbus_strerror (errno));
01762
01763 goto out;
01764 }
01765
01766 total += bytes_written;
01767 }
01768
01769 if (!_dbus_close (fd, NULL))
01770 {
01771 dbus_set_error (error, _dbus_error_from_errno (errno),
01772 "Could not close file %s: %s",
01773 tmp_filename_c, _dbus_strerror (errno));
01774
01775 goto out;
01776 }
01777
01778 fd = -1;
01779
01780 if (rename (tmp_filename_c, filename_c) < 0)
01781 {
01782 dbus_set_error (error, _dbus_error_from_errno (errno),
01783 "Could not rename %s to %s: %s",
01784 tmp_filename_c, filename_c,
01785 _dbus_strerror (errno));
01786
01787 goto out;
01788 }
01789
01790 need_unlink = FALSE;
01791
01792 retval = TRUE;
01793
01794 out:
01795
01796
01797
01798
01799 if (fd >= 0)
01800 _dbus_close (fd, NULL);
01801
01802 if (need_unlink && unlink (tmp_filename_c) < 0)
01803 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
01804 tmp_filename_c, _dbus_strerror (errno));
01805
01806 _dbus_string_free (&tmp_filename);
01807
01808 if (!retval)
01809 _DBUS_ASSERT_ERROR_IS_SET (error);
01810
01811 return retval;
01812 }
01813
01820 dbus_bool_t
01821 _dbus_make_file_world_readable(const DBusString *filename,
01822 DBusError *error)
01823 {
01824 const char *filename_c;
01825
01826 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01827
01828 filename_c = _dbus_string_get_const_data (filename);
01829 if (chmod (filename_c, 0644) == -1)
01830 {
01831 dbus_set_error (error,
01832 DBUS_ERROR_FAILED,
01833 "Could not change permissions of file %s: %s\n",
01834 filename_c,
01835 _dbus_strerror (errno));
01836 return FALSE;
01837 }
01838 return TRUE;
01839 }
01840
01847 dbus_bool_t
01848 _dbus_create_file_exclusively (const DBusString *filename,
01849 DBusError *error)
01850 {
01851 int fd;
01852 const char *filename_c;
01853
01854 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01855
01856 filename_c = _dbus_string_get_const_data (filename);
01857
01858 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
01859 0600);
01860 if (fd < 0)
01861 {
01862 dbus_set_error (error,
01863 DBUS_ERROR_FAILED,
01864 "Could not create file %s: %s\n",
01865 filename_c,
01866 _dbus_strerror (errno));
01867 return FALSE;
01868 }
01869
01870 if (!_dbus_close (fd, NULL))
01871 {
01872 dbus_set_error (error,
01873 DBUS_ERROR_FAILED,
01874 "Could not close file %s: %s\n",
01875 filename_c,
01876 _dbus_strerror (errno));
01877 return FALSE;
01878 }
01879
01880 return TRUE;
01881 }
01882
01891 dbus_bool_t
01892 _dbus_delete_file (const DBusString *filename,
01893 DBusError *error)
01894 {
01895 const char *filename_c;
01896
01897 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01898
01899 filename_c = _dbus_string_get_const_data (filename);
01900
01901 if (unlink (filename_c) < 0)
01902 {
01903 dbus_set_error (error, DBUS_ERROR_FAILED,
01904 "Failed to delete file %s: %s\n",
01905 filename_c, _dbus_strerror (errno));
01906 return FALSE;
01907 }
01908 else
01909 return TRUE;
01910 }
01911
01920 dbus_bool_t
01921 _dbus_create_directory (const DBusString *filename,
01922 DBusError *error)
01923 {
01924 const char *filename_c;
01925
01926 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01927
01928 filename_c = _dbus_string_get_const_data (filename);
01929
01930 if (mkdir (filename_c, 0700) < 0)
01931 {
01932 if (errno == EEXIST)
01933 return TRUE;
01934
01935 dbus_set_error (error, DBUS_ERROR_FAILED,
01936 "Failed to create directory %s: %s\n",
01937 filename_c, _dbus_strerror (errno));
01938 return FALSE;
01939 }
01940 else
01941 return TRUE;
01942 }
01943
01954 dbus_bool_t
01955 _dbus_concat_dir_and_file (DBusString *dir,
01956 const DBusString *next_component)
01957 {
01958 dbus_bool_t dir_ends_in_slash;
01959 dbus_bool_t file_starts_with_slash;
01960
01961 if (_dbus_string_get_length (dir) == 0 ||
01962 _dbus_string_get_length (next_component) == 0)
01963 return TRUE;
01964
01965 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
01966 _dbus_string_get_length (dir) - 1);
01967
01968 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
01969
01970 if (dir_ends_in_slash && file_starts_with_slash)
01971 {
01972 _dbus_string_shorten (dir, 1);
01973 }
01974 else if (!(dir_ends_in_slash || file_starts_with_slash))
01975 {
01976 if (!_dbus_string_append_byte (dir, '/'))
01977 return FALSE;
01978 }
01979
01980 return _dbus_string_copy (next_component, 0, dir,
01981 _dbus_string_get_length (dir));
01982 }
01983
01985 #define NANOSECONDS_PER_SECOND 1000000000
01986
01987 #define MICROSECONDS_PER_SECOND 1000000
01988
01989 #define MILLISECONDS_PER_SECOND 1000
01990
01991 #define NANOSECONDS_PER_MILLISECOND 1000000
01992
01993 #define MICROSECONDS_PER_MILLISECOND 1000
01994
01999 void
02000 _dbus_sleep_milliseconds (int milliseconds)
02001 {
02002 #ifdef HAVE_NANOSLEEP
02003 struct timespec req;
02004 struct timespec rem;
02005
02006 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02007 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02008 rem.tv_sec = 0;
02009 rem.tv_nsec = 0;
02010
02011 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02012 req = rem;
02013 #elif defined (HAVE_USLEEP)
02014 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02015 #else
02016 sleep (MAX (milliseconds / 1000, 1));
02017 #endif
02018 }
02019
02020 static dbus_bool_t
02021 _dbus_generate_pseudorandom_bytes (DBusString *str,
02022 int n_bytes)
02023 {
02024 int old_len;
02025 char *p;
02026
02027 old_len = _dbus_string_get_length (str);
02028
02029 if (!_dbus_string_lengthen (str, n_bytes))
02030 return FALSE;
02031
02032 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02033
02034 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02035
02036 return TRUE;
02037 }
02038
02047 dbus_bool_t
02048 _dbus_generate_random_bytes (DBusString *str,
02049 int n_bytes)
02050 {
02051 int old_len;
02052 int fd;
02053
02054
02055
02056
02057
02058
02059
02060 old_len = _dbus_string_get_length (str);
02061 fd = -1;
02062
02063
02064 fd = open ("/dev/urandom", O_RDONLY);
02065 if (fd < 0)
02066 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02067
02068 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02069 {
02070 _dbus_close (fd, NULL);
02071 _dbus_string_set_length (str, old_len);
02072 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02073 }
02074
02075 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02076 n_bytes);
02077
02078 _dbus_close (fd, NULL);
02079
02080 return TRUE;
02081 }
02082
02088 void
02089 _dbus_exit (int code)
02090 {
02091 _exit (code);
02092 }
02093
02101 const char*
02102 _dbus_strerror (int error_number)
02103 {
02104 const char *msg;
02105
02106 msg = strerror (error_number);
02107 if (msg == NULL)
02108 msg = "unknown";
02109
02110 return msg;
02111 }
02112
02116 void
02117 _dbus_disable_sigpipe (void)
02118 {
02119 signal (SIGPIPE, SIG_IGN);
02120 }
02121
02129 void
02130 _dbus_fd_set_close_on_exec (int fd)
02131 {
02132 int val;
02133
02134 val = fcntl (fd, F_GETFD, 0);
02135
02136 if (val < 0)
02137 return;
02138
02139 val |= FD_CLOEXEC;
02140
02141 fcntl (fd, F_SETFD, val);
02142 }
02143
02151 dbus_bool_t
02152 _dbus_close (int fd,
02153 DBusError *error)
02154 {
02155 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02156
02157 again:
02158 if (close (fd) < 0)
02159 {
02160 if (errno == EINTR)
02161 goto again;
02162
02163 dbus_set_error (error, _dbus_error_from_errno (errno),
02164 "Could not close fd %d", fd);
02165 return FALSE;
02166 }
02167
02168 return TRUE;
02169 }
02170
02178 dbus_bool_t
02179 _dbus_set_fd_nonblocking (int fd,
02180 DBusError *error)
02181 {
02182 int val;
02183
02184 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02185
02186 val = fcntl (fd, F_GETFL, 0);
02187 if (val < 0)
02188 {
02189 dbus_set_error (error, _dbus_error_from_errno (errno),
02190 "Failed to get flags from file descriptor %d: %s",
02191 fd, _dbus_strerror (errno));
02192 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02193 _dbus_strerror (errno));
02194 return FALSE;
02195 }
02196
02197 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02198 {
02199 dbus_set_error (error, _dbus_error_from_errno (errno),
02200 "Failed to set nonblocking flag of file descriptor %d: %s",
02201 fd, _dbus_strerror (errno));
02202 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02203 fd, _dbus_strerror (errno));
02204
02205 return FALSE;
02206 }
02207
02208 return TRUE;
02209 }
02210
02216 void
02217 _dbus_print_backtrace (void)
02218 {
02219 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02220 void *bt[500];
02221 int bt_size;
02222 int i;
02223 char **syms;
02224
02225 bt_size = backtrace (bt, 500);
02226
02227 syms = backtrace_symbols (bt, bt_size);
02228
02229 i = 0;
02230 while (i < bt_size)
02231 {
02232
02233 fprintf (stderr, " %s\n", syms[i]);
02234 ++i;
02235 }
02236 fflush (stderr);
02237
02238 free (syms);
02239 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02240 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
02241 #else
02242 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02243 #endif
02244 }
02245
02261 dbus_bool_t
02262 _dbus_full_duplex_pipe (int *fd1,
02263 int *fd2,
02264 dbus_bool_t blocking,
02265 DBusError *error)
02266 {
02267 #ifdef HAVE_SOCKETPAIR
02268 int fds[2];
02269
02270 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02271
02272 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02273 {
02274 dbus_set_error (error, _dbus_error_from_errno (errno),
02275 "Could not create full-duplex pipe");
02276 return FALSE;
02277 }
02278
02279 if (!blocking &&
02280 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02281 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02282 {
02283 dbus_set_error (error, _dbus_error_from_errno (errno),
02284 "Could not set full-duplex pipe nonblocking");
02285
02286 _dbus_close (fds[0], NULL);
02287 _dbus_close (fds[1], NULL);
02288
02289 return FALSE;
02290 }
02291
02292 *fd1 = fds[0];
02293 *fd2 = fds[1];
02294
02295 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02296 *fd1, *fd2);
02297
02298 return TRUE;
02299 #else
02300 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02301 dbus_set_error (error, DBUS_ERROR_FAILED,
02302 "_dbus_full_duplex_pipe() not implemented on this OS");
02303 return FALSE;
02304 #endif
02305 }
02306
02307
02316 int
02317 _dbus_printf_string_upper_bound (const char *format,
02318 va_list args)
02319 {
02320 char c;
02321 return vsnprintf (&c, 1, format, args);
02322 }
02323
02330 const char*
02331 _dbus_get_tmpdir(void)
02332 {
02333 static const char* tmpdir = NULL;
02334
02335 if (tmpdir == NULL)
02336 {
02337
02338
02339
02340
02341 if (tmpdir == NULL)
02342 tmpdir = getenv("TMPDIR");
02343
02344
02345
02346
02347 if (tmpdir == NULL)
02348 tmpdir = getenv("TMP");
02349 if (tmpdir == NULL)
02350 tmpdir = getenv("TEMP");
02351
02352
02353 if (tmpdir == NULL)
02354 tmpdir = "/tmp";
02355 }
02356
02357 _dbus_assert(tmpdir != NULL);
02358
02359 return tmpdir;
02360 }
02361
02374 dbus_bool_t
02375 _dbus_get_autolaunch_address (DBusString *address,
02376 DBusError *error)
02377 {
02378 static char *argv[6];
02379 int address_pipe[2] = { -1, -1 };
02380 int errors_pipe[2] = { -1, -1 };
02381 pid_t pid;
02382 int ret;
02383 int status;
02384 int orig_len;
02385 int i;
02386 DBusString uuid;
02387 dbus_bool_t retval;
02388
02389 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02390 retval = FALSE;
02391
02392 _dbus_string_init (&uuid);
02393
02394 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02395 {
02396 _DBUS_SET_OOM (error);
02397 goto out;
02398 }
02399
02400 i = 0;
02401 argv[i] = "dbus-launch";
02402 ++i;
02403 argv[i] = "--autolaunch";
02404 ++i;
02405 argv[i] = _dbus_string_get_data (&uuid);
02406 ++i;
02407 argv[i] = "--binary-syntax";
02408 ++i;
02409 argv[i] = "--close-stderr";
02410 ++i;
02411 argv[i] = NULL;
02412 ++i;
02413
02414 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02415
02416 orig_len = _dbus_string_get_length (address);
02417
02418 #define READ_END 0
02419 #define WRITE_END 1
02420 if (pipe (address_pipe) < 0)
02421 {
02422 dbus_set_error (error, _dbus_error_from_errno (errno),
02423 "Failed to create a pipe: %s",
02424 _dbus_strerror (errno));
02425 _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02426 _dbus_strerror (errno));
02427 goto out;
02428 }
02429 if (pipe (errors_pipe) < 0)
02430 {
02431 dbus_set_error (error, _dbus_error_from_errno (errno),
02432 "Failed to create a pipe: %s",
02433 _dbus_strerror (errno));
02434 _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02435 _dbus_strerror (errno));
02436 goto out;
02437 }
02438
02439 pid = fork ();
02440 if (pid < 0)
02441 {
02442 dbus_set_error (error, _dbus_error_from_errno (errno),
02443 "Failed to fork(): %s",
02444 _dbus_strerror (errno));
02445 _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02446 _dbus_strerror (errno));
02447 goto out;
02448 }
02449
02450 if (pid == 0)
02451 {
02452
02453 int fd = open ("/dev/null", O_RDWR);
02454 if (fd == -1)
02455
02456 _exit (1);
02457
02458
02459 close (address_pipe[READ_END]);
02460 close (errors_pipe[READ_END]);
02461 close (0);
02462 close (1);
02463 close (2);
02464
02465 if (dup2 (fd, 0) == -1)
02466 _exit (1);
02467 if (dup2 (address_pipe[WRITE_END], 1) == -1)
02468 _exit (1);
02469 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02470 _exit (1);
02471
02472 close (fd);
02473 close (address_pipe[WRITE_END]);
02474 close (errors_pipe[WRITE_END]);
02475
02476 execv (DBUS_BINDIR "/dbus-launch", argv);
02477
02478
02479 execvp ("dbus-launch", argv);
02480
02481
02482 _exit (1);
02483 }
02484
02485
02486 close (address_pipe[WRITE_END]);
02487 close (errors_pipe[WRITE_END]);
02488 address_pipe[WRITE_END] = -1;
02489 errors_pipe[WRITE_END] = -1;
02490
02491 ret = 0;
02492 do
02493 {
02494 ret = _dbus_read (address_pipe[READ_END], address, 1024);
02495 }
02496 while (ret > 0);
02497
02498
02499 do
02500 {
02501 ret = waitpid (pid, &status, 0);
02502 }
02503 while (ret == -1 && errno == EINTR);
02504
02505
02506
02507 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02508 _dbus_string_get_length (address) == orig_len)
02509 {
02510
02511 DBusString error_message;
02512 _dbus_string_init (&error_message);
02513 ret = 0;
02514 do
02515 {
02516 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
02517 }
02518 while (ret > 0);
02519
02520 _dbus_string_set_length (address, orig_len);
02521 if (_dbus_string_get_length (&error_message) > 0)
02522 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02523 "dbus-launch failed to autolaunch D-Bus session: %s",
02524 _dbus_string_get_data (&error_message));
02525 else
02526 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02527 "Failed to execute dbus-launch to autolaunch D-Bus session");
02528 goto out;
02529 }
02530
02531 retval = TRUE;
02532
02533 out:
02534 if (retval)
02535 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02536 else
02537 _DBUS_ASSERT_ERROR_IS_SET (error);
02538
02539 if (address_pipe[0] != -1)
02540 close (address_pipe[0]);
02541 if (address_pipe[1] != -1)
02542 close (address_pipe[1]);
02543 if (errors_pipe[0] != -1)
02544 close (errors_pipe[0]);
02545 if (errors_pipe[1] != -1)
02546 close (errors_pipe[1]);
02547
02548 _dbus_string_free (&uuid);
02549 return retval;
02550 }
02551
02570 dbus_bool_t
02571 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
02572 dbus_bool_t create_if_not_found,
02573 DBusError *error)
02574 {
02575 DBusString filename;
02576 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
02577 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
02578 }
02579
02580 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
02581
02582 static dbus_bool_t
02583 split_paths_and_append (DBusString *dirs,
02584 const char *suffix,
02585 DBusList **dir_list)
02586 {
02587
02588 int start;
02589 int i;
02590 int len;
02591 char *cpath;
02592 const DBusString file_suffix;
02593
02594 start = 0;
02595 i = 0;
02596
02597 _dbus_string_init_const (&file_suffix, suffix);
02598
02599 len = _dbus_string_get_length (dirs);
02600
02601 while (_dbus_string_find (dirs, start, ":", &i))
02602 {
02603 DBusString path;
02604
02605 if (!_dbus_string_init (&path))
02606 goto oom;
02607
02608 if (!_dbus_string_copy_len (dirs,
02609 start,
02610 i - start,
02611 &path,
02612 0))
02613 {
02614 _dbus_string_free (&path);
02615 goto oom;
02616 }
02617
02618 _dbus_string_chop_white (&path);
02619
02620
02621 if (_dbus_string_get_length (&path) == 0)
02622 goto next;
02623
02624 if (!_dbus_concat_dir_and_file (&path,
02625 &file_suffix))
02626 {
02627 _dbus_string_free (&path);
02628 goto oom;
02629 }
02630
02631 if (!_dbus_string_copy_data(&path, &cpath))
02632 {
02633 _dbus_string_free (&path);
02634 goto oom;
02635 }
02636
02637 if (!_dbus_list_append (dir_list, cpath))
02638 {
02639 _dbus_string_free (&path);
02640 dbus_free (cpath);
02641 goto oom;
02642 }
02643
02644 next:
02645 _dbus_string_free (&path);
02646 start = i + 1;
02647 }
02648
02649 if (start != len)
02650 {
02651 DBusString path;
02652
02653 if (!_dbus_string_init (&path))
02654 goto oom;
02655
02656 if (!_dbus_string_copy_len (dirs,
02657 start,
02658 len - start,
02659 &path,
02660 0))
02661 {
02662 _dbus_string_free (&path);
02663 goto oom;
02664 }
02665
02666 if (!_dbus_concat_dir_and_file (&path,
02667 &file_suffix))
02668 {
02669 _dbus_string_free (&path);
02670 goto oom;
02671 }
02672
02673 if (!_dbus_string_copy_data(&path, &cpath))
02674 {
02675 _dbus_string_free (&path);
02676 goto oom;
02677 }
02678
02679 if (!_dbus_list_append (dir_list, cpath))
02680 {
02681 _dbus_string_free (&path);
02682 dbus_free (cpath);
02683 goto oom;
02684 }
02685
02686 _dbus_string_free (&path);
02687 }
02688
02689 return TRUE;
02690
02691 oom:
02692 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
02693 _dbus_list_clear (dir_list);
02694 return FALSE;
02695 }
02696
02714 dbus_bool_t
02715 _dbus_get_standard_session_servicedirs (DBusList **dirs)
02716 {
02717 const char *xdg_data_home;
02718 const char *xdg_data_dirs;
02719 DBusString servicedir_path;
02720
02721 if (!_dbus_string_init (&servicedir_path))
02722 return FALSE;
02723
02724 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
02725 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
02726
02727 if (xdg_data_dirs != NULL)
02728 {
02729 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
02730 goto oom;
02731
02732 if (!_dbus_string_append (&servicedir_path, ":"))
02733 goto oom;
02734 }
02735 else
02736 {
02737 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
02738 goto oom;
02739 }
02740
02741
02742
02743
02744
02745
02746
02747 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
02748 goto oom;
02749
02750 if (xdg_data_home != NULL)
02751 {
02752 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
02753 goto oom;
02754 }
02755 else
02756 {
02757 const DBusString *homedir;
02758 const DBusString local_share;
02759
02760 if (!_dbus_homedir_from_current_process (&homedir))
02761 goto oom;
02762
02763 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
02764 goto oom;
02765
02766 _dbus_string_init_const (&local_share, "/.local/share");
02767 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
02768 goto oom;
02769 }
02770
02771 if (!split_paths_and_append (&servicedir_path,
02772 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
02773 dirs))
02774 goto oom;
02775
02776 _dbus_string_free (&servicedir_path);
02777 return TRUE;
02778
02779 oom:
02780 _dbus_string_free (&servicedir_path);
02781 return FALSE;
02782 }
02783
02784