• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24 
25 #include "dbus-internals.h"
26 #include "dbus-sysdeps.h"
27 #include "dbus-sysdeps-unix.h"
28 #include "dbus-threads.h"
29 #include "dbus-protocol.h"
30 #include "dbus-transport.h"
31 #include "dbus-string.h"
32 #include "dbus-userdb.h"
33 #include "dbus-list.h"
34 #include <sys/types.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <signal.h>
38 #include <unistd.h>
39 #include <stdio.h>
40 #include <fcntl.h>
41 #include <sys/socket.h>
42 #include <dirent.h>
43 #include <sys/un.h>
44 #include <pwd.h>
45 #include <time.h>
46 #include <locale.h>
47 #include <sys/time.h>
48 #include <sys/stat.h>
49 #include <sys/wait.h>
50 #include <netinet/in.h>
51 #include <netdb.h>
52 #include <grp.h>
53 #include <cutils/sockets.h>
54 
55 #ifdef HAVE_ERRNO_H
56 #include <errno.h>
57 #endif
58 #ifdef HAVE_WRITEV
59 #include <sys/uio.h>
60 #endif
61 #ifdef HAVE_POLL
62 #include <sys/poll.h>
63 #endif
64 #ifdef HAVE_BACKTRACE
65 #include <execinfo.h>
66 #endif
67 #ifdef HAVE_GETPEERUCRED
68 #include <ucred.h>
69 #endif
70 
71 #ifndef O_BINARY
72 #define O_BINARY 0
73 #endif
74 
75 #ifndef HAVE_SOCKLEN_T
76 #define socklen_t int
77 #endif
78 
79 static dbus_bool_t
_dbus_open_socket(int * fd,int domain,int type,int protocol,DBusError * error)80 _dbus_open_socket (int              *fd,
81                    int               domain,
82                    int               type,
83                    int               protocol,
84                    DBusError        *error)
85 {
86   *fd = socket (domain, type, protocol);
87   if (*fd >= 0)
88     {
89       return TRUE;
90     }
91   else
92     {
93       dbus_set_error(error,
94                      _dbus_error_from_errno (errno),
95                      "Failed to open socket: %s",
96                      _dbus_strerror (errno));
97       return FALSE;
98     }
99 }
100 
101 dbus_bool_t
_dbus_open_tcp_socket(int * fd,DBusError * error)102 _dbus_open_tcp_socket (int              *fd,
103                        DBusError        *error)
104 {
105   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
106 }
107 
108 /**
109  * Opens a UNIX domain socket (as in the socket() call).
110  * Does not bind the socket.
111  * @param fd return location for socket descriptor
112  * @param error return location for an error
113  * @returns #FALSE if error is set
114  */
115 dbus_bool_t
_dbus_open_unix_socket(int * fd,DBusError * error)116 _dbus_open_unix_socket (int              *fd,
117                         DBusError        *error)
118 {
119   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
120 }
121 
122 /**
123  * Closes a socket. Should not be used on non-socket
124  * file descriptors or handles.
125  *
126  * @param fd the socket
127  * @param error return location for an error
128  * @returns #FALSE if error is set
129  */
130 dbus_bool_t
_dbus_close_socket(int fd,DBusError * error)131 _dbus_close_socket (int               fd,
132                     DBusError        *error)
133 {
134   return _dbus_close (fd, error);
135 }
136 
137 /**
138  * Like _dbus_read(), but only works on sockets so is
139  * available on Windows.
140  *
141  * @param fd the socket
142  * @param buffer string to append data to
143  * @param count max amount of data to read
144  * @returns number of bytes appended to the string
145  */
146 int
_dbus_read_socket(int fd,DBusString * buffer,int count)147 _dbus_read_socket (int               fd,
148                    DBusString       *buffer,
149                    int               count)
150 {
151   return _dbus_read (fd, buffer, count);
152 }
153 
154 /**
155  * Like _dbus_write(), but only supports sockets
156  * and is thus available on Windows.
157  *
158  * @param fd the file descriptor to write
159  * @param buffer the buffer to write data from
160  * @param start the first byte in the buffer to write
161  * @param len the number of bytes to try to write
162  * @returns the number of bytes written or -1 on error
163  */
164 int
_dbus_write_socket(int fd,const DBusString * buffer,int start,int len)165 _dbus_write_socket (int               fd,
166                     const DBusString *buffer,
167                     int               start,
168                     int               len)
169 {
170   return _dbus_write (fd, buffer, start, len);
171 }
172 
173 /**
174  * Like _dbus_write_two() but only works on sockets and is thus
175  * available on Windows.
176  *
177  * @param fd the file descriptor
178  * @param buffer1 first buffer
179  * @param start1 first byte to write in first buffer
180  * @param len1 number of bytes to write from first buffer
181  * @param buffer2 second buffer, or #NULL
182  * @param start2 first byte to write in second buffer
183  * @param len2 number of bytes to write in second buffer
184  * @returns total bytes written from both buffers, or -1 on error
185  */
186 int
_dbus_write_socket_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2)187 _dbus_write_socket_two (int               fd,
188                         const DBusString *buffer1,
189                         int               start1,
190                         int               len1,
191                         const DBusString *buffer2,
192                         int               start2,
193                         int               len2)
194 {
195   return _dbus_write_two (fd, buffer1, start1, len1,
196                           buffer2, start2, len2);
197 }
198 
199 
200 /**
201  * Thin wrapper around the read() system call that appends
202  * the data it reads to the DBusString buffer. It appends
203  * up to the given count, and returns the same value
204  * and same errno as read(). The only exception is that
205  * _dbus_read() handles EINTR for you. Also, _dbus_read() can
206  * return ENOMEM, even though regular UNIX read doesn't.
207  *
208  * Unlike _dbus_read_socket(), _dbus_read() is not available
209  * on Windows.
210  *
211  * @param fd the file descriptor to read from
212  * @param buffer the buffer to append data to
213  * @param count the amount of data to read
214  * @returns the number of bytes read or -1
215  */
216 int
_dbus_read(int fd,DBusString * buffer,int count)217 _dbus_read (int               fd,
218             DBusString       *buffer,
219             int               count)
220 {
221   int bytes_read;
222   int start;
223   char *data;
224 
225   _dbus_assert (count >= 0);
226 
227   start = _dbus_string_get_length (buffer);
228 
229   if (!_dbus_string_lengthen (buffer, count))
230     {
231       errno = ENOMEM;
232       return -1;
233     }
234 
235   data = _dbus_string_get_data_len (buffer, start, count);
236 
237  again:
238 
239   bytes_read = read (fd, data, count);
240 
241   if (bytes_read < 0)
242     {
243       if (errno == EINTR)
244         goto again;
245       else
246         {
247           /* put length back (note that this doesn't actually realloc anything) */
248           _dbus_string_set_length (buffer, start);
249           return -1;
250         }
251     }
252   else
253     {
254       /* put length back (doesn't actually realloc) */
255       _dbus_string_set_length (buffer, start + bytes_read);
256 
257 #if 0
258       if (bytes_read > 0)
259         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
260 #endif
261 
262       return bytes_read;
263     }
264 }
265 
266 /**
267  * Thin wrapper around the write() system call that writes a part of a
268  * DBusString and handles EINTR for you.
269  *
270  * @param fd the file descriptor to write
271  * @param buffer the buffer to write data from
272  * @param start the first byte in the buffer to write
273  * @param len the number of bytes to try to write
274  * @returns the number of bytes written or -1 on error
275  */
276 int
_dbus_write(int fd,const DBusString * buffer,int start,int len)277 _dbus_write (int               fd,
278              const DBusString *buffer,
279              int               start,
280              int               len)
281 {
282   const char *data;
283   int bytes_written;
284 
285   data = _dbus_string_get_const_data_len (buffer, start, len);
286 
287  again:
288 
289   bytes_written = write (fd, data, len);
290 
291   if (bytes_written < 0 && errno == EINTR)
292     goto again;
293 
294 #if 0
295   if (bytes_written > 0)
296     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
297 #endif
298 
299   return bytes_written;
300 }
301 
302 /**
303  * Like _dbus_write() but will use writev() if possible
304  * to write both buffers in sequence. The return value
305  * is the number of bytes written in the first buffer,
306  * plus the number written in the second. If the first
307  * buffer is written successfully and an error occurs
308  * writing the second, the number of bytes in the first
309  * is returned (i.e. the error is ignored), on systems that
310  * don't have writev. Handles EINTR for you.
311  * The second buffer may be #NULL.
312  *
313  * @param fd the file descriptor
314  * @param buffer1 first buffer
315  * @param start1 first byte to write in first buffer
316  * @param len1 number of bytes to write from first buffer
317  * @param buffer2 second buffer, or #NULL
318  * @param start2 first byte to write in second buffer
319  * @param len2 number of bytes to write in second buffer
320  * @returns total bytes written from both buffers, or -1 on error
321  */
322 int
_dbus_write_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2)323 _dbus_write_two (int               fd,
324                  const DBusString *buffer1,
325                  int               start1,
326                  int               len1,
327                  const DBusString *buffer2,
328                  int               start2,
329                  int               len2)
330 {
331   _dbus_assert (buffer1 != NULL);
332   _dbus_assert (start1 >= 0);
333   _dbus_assert (start2 >= 0);
334   _dbus_assert (len1 >= 0);
335   _dbus_assert (len2 >= 0);
336 
337 #ifdef HAVE_WRITEV
338   {
339     struct iovec vectors[2];
340     const char *data1;
341     const char *data2;
342     int bytes_written;
343 
344     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
345 
346     if (buffer2 != NULL)
347       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
348     else
349       {
350         data2 = NULL;
351         start2 = 0;
352         len2 = 0;
353       }
354 
355     vectors[0].iov_base = (char*) data1;
356     vectors[0].iov_len = len1;
357     vectors[1].iov_base = (char*) data2;
358     vectors[1].iov_len = len2;
359 
360   again:
361 
362     bytes_written = writev (fd,
363                             vectors,
364                             data2 ? 2 : 1);
365 
366     if (bytes_written < 0 && errno == EINTR)
367       goto again;
368 
369     return bytes_written;
370   }
371 #else /* HAVE_WRITEV */
372   {
373     int ret1;
374 
375     ret1 = _dbus_write (fd, buffer1, start1, len1);
376     if (ret1 == len1 && buffer2 != NULL)
377       {
378         ret2 = _dbus_write (fd, buffer2, start2, len2);
379         if (ret2 < 0)
380           ret2 = 0; /* we can't report an error as the first write was OK */
381 
382         return ret1 + ret2;
383       }
384     else
385       return ret1;
386   }
387 #endif /* !HAVE_WRITEV */
388 }
389 
390 #define _DBUS_MAX_SUN_PATH_LENGTH 99
391 
392 /**
393  * @def _DBUS_MAX_SUN_PATH_LENGTH
394  *
395  * Maximum length of the path to a UNIX domain socket,
396  * sockaddr_un::sun_path member. POSIX requires that all systems
397  * support at least 100 bytes here, including the nul termination.
398  * We use 99 for the max value to allow for the nul.
399  *
400  * We could probably also do sizeof (addr.sun_path)
401  * but this way we are the same on all platforms
402  * which is probably a good idea.
403  */
404 
405 /**
406  * Creates a socket and connects it to the UNIX domain socket at the
407  * given path.  The connection fd is returned, and is set up as
408  * nonblocking.
409  *
410  * Uses abstract sockets instead of filesystem-linked sockets if
411  * requested (it's possible only on Linux; see "man 7 unix" on Linux).
412  * On non-Linux abstract socket usage always fails.
413  *
414  * @param path the path to UNIX domain socket
415  * @param abstract #TRUE to use abstract namespace
416  * @param error return location for error code
417  * @returns connection file descriptor or -1 on error
418  */
419 int
_dbus_connect_unix_socket(const char * path,dbus_bool_t abstract,DBusError * error)420 _dbus_connect_unix_socket (const char     *path,
421                            dbus_bool_t     abstract,
422                            DBusError      *error)
423 {
424   int fd;
425   size_t path_len;
426   struct sockaddr_un addr;
427 
428   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
429 
430   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
431                  path, abstract);
432 
433 
434   if (!_dbus_open_unix_socket (&fd, error))
435     {
436       _DBUS_ASSERT_ERROR_IS_SET(error);
437       return -1;
438     }
439   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
440 
441   _DBUS_ZERO (addr);
442   addr.sun_family = AF_UNIX;
443   path_len = strlen (path);
444 
445   if (abstract)
446     {
447 #ifdef HAVE_ABSTRACT_SOCKETS
448       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
449       path_len++; /* Account for the extra nul byte added to the start of sun_path */
450 
451       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
452         {
453           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
454                       "Abstract socket name too long\n");
455           _dbus_close (fd, NULL);
456           return -1;
457 	}
458 
459       strncpy (&addr.sun_path[1], path, path_len);
460       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
461 #else /* HAVE_ABSTRACT_SOCKETS */
462       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
463                       "Operating system does not support abstract socket namespace\n");
464       _dbus_close (fd, NULL);
465       return -1;
466 #endif /* ! HAVE_ABSTRACT_SOCKETS */
467     }
468   else
469     {
470       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
471         {
472           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
473                       "Socket name too long\n");
474           _dbus_close (fd, NULL);
475           return -1;
476 	}
477 
478       strncpy (addr.sun_path, path, path_len);
479     }
480 
481   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
482     {
483       dbus_set_error (error,
484                       _dbus_error_from_errno (errno),
485                       "Failed to connect to socket %s: %s",
486                       path, _dbus_strerror (errno));
487 
488       _dbus_close (fd, NULL);
489       fd = -1;
490 
491       return -1;
492     }
493 
494   if (!_dbus_set_fd_nonblocking (fd, error))
495     {
496       _DBUS_ASSERT_ERROR_IS_SET (error);
497 
498       _dbus_close (fd, NULL);
499       fd = -1;
500 
501       return -1;
502     }
503 
504   return fd;
505 }
506 
507 /**
508  * Enables or disables the reception of credentials on the given socket during
509  * the next message transmission.  This is only effective if the #LOCAL_CREDS
510  * system feature exists, in which case the other side of the connection does
511  * not have to do anything special to send the credentials.
512  *
513  * @param fd socket on which to change the #LOCAL_CREDS flag.
514  * @param on whether to enable or disable the #LOCAL_CREDS flag.
515  */
516 static dbus_bool_t
_dbus_set_local_creds(int fd,dbus_bool_t on)517 _dbus_set_local_creds (int fd, dbus_bool_t on)
518 {
519   dbus_bool_t retval = TRUE;
520 
521 #if defined(HAVE_CMSGCRED)
522   /* NOOP just to make sure only one codepath is used
523    *      and to prefer CMSGCRED
524    */
525 #elif defined(LOCAL_CREDS)
526   int val = on ? 1 : 0;
527   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
528     {
529       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
530       retval = FALSE;
531     }
532   else
533     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
534                    on ? "enabled" : "disabled", fd);
535 #endif
536 
537   return retval;
538 }
539 
540 /**
541  * Creates a socket and binds it to the given path,
542  * then listens on the socket. The socket is
543  * set to be nonblocking.
544  *
545  * Uses abstract sockets instead of filesystem-linked
546  * sockets if requested (it's possible only on Linux;
547  * see "man 7 unix" on Linux).
548  * On non-Linux abstract socket usage always fails.
549  *
550  * @param path the socket name
551  * @param abstract #TRUE to use abstract namespace
552  * @param error return location for errors
553  * @returns the listening file descriptor or -1 on error
554  */
555 int
_dbus_listen_unix_socket(const char * path,dbus_bool_t abstract,DBusError * error)556 _dbus_listen_unix_socket (const char     *path,
557                           dbus_bool_t     abstract,
558                           DBusError      *error)
559 {
560   int listen_fd;
561   struct sockaddr_un addr;
562   size_t path_len;
563 
564   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
565 
566   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
567                  path, abstract);
568 #ifdef ANDROID_MANAGED_SOCKET
569   if (strncmp (path, ANDROID_SOCKET_DIR"/", strlen(ANDROID_SOCKET_DIR"/")) == 0)
570     {
571       const char* suffix;
572       /* init has created a socket for us, pick it up from environ */
573       suffix = &path[strlen (ANDROID_SOCKET_DIR"/")];
574       listen_fd = android_get_control_socket (suffix);
575       if (listen_fd == -1)
576         {
577           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
578                 "Could not obtain fd for android socket %s\n", suffix);
579           return -1;
580         }
581 
582       _dbus_verbose ("Obtained fd for android socket %s\n", suffix);
583     }
584   else
585     {
586       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
587             "Not an android socket: %s\n", path);
588       return -1;
589     }
590 #else
591 
592   if (!_dbus_open_unix_socket (&listen_fd, error))
593     {
594       _DBUS_ASSERT_ERROR_IS_SET(error);
595       return -1;
596     }
597   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
598 
599   _DBUS_ZERO (addr);
600   addr.sun_family = AF_UNIX;
601   path_len = strlen (path);
602 
603   if (abstract)
604     {
605 #ifdef HAVE_ABSTRACT_SOCKETS
606       /* remember that abstract names aren't nul-terminated so we rely
607        * on sun_path being filled in with zeroes above.
608        */
609       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
610       path_len++; /* Account for the extra nul byte added to the start of sun_path */
611 
612       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
613         {
614           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
615                       "Abstract socket name too long\n");
616           _dbus_close (listen_fd, NULL);
617           return -1;
618 	}
619 
620       strncpy (&addr.sun_path[1], path, path_len);
621       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
622 #else /* HAVE_ABSTRACT_SOCKETS */
623       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
624                       "Operating system does not support abstract socket namespace\n");
625       _dbus_close (listen_fd, NULL);
626       return -1;
627 #endif /* ! HAVE_ABSTRACT_SOCKETS */
628     }
629   else
630     {
631       /* Discussed security implications of this with Nalin,
632        * and we couldn't think of where it would kick our ass, but
633        * it still seems a bit sucky. It also has non-security suckage;
634        * really we'd prefer to exit if the socket is already in use.
635        * But there doesn't seem to be a good way to do this.
636        *
637        * Just to be extra careful, I threw in the stat() - clearly
638        * the stat() can't *fix* any security issue, but it at least
639        * avoids inadvertent/accidental data loss.
640        */
641       {
642         struct stat sb;
643 
644         if (stat (path, &sb) == 0 &&
645             S_ISSOCK (sb.st_mode))
646           unlink (path);
647       }
648 
649       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
650         {
651           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
652                       "Abstract socket name too long\n");
653           _dbus_close (listen_fd, NULL);
654           return -1;
655 	}
656 
657       strncpy (addr.sun_path, path, path_len);
658     }
659 
660   if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
661     {
662       dbus_set_error (error, _dbus_error_from_errno (errno),
663                       "Failed to bind socket \"%s\": %s",
664                       path, _dbus_strerror (errno));
665       _dbus_close (listen_fd, NULL);
666       return -1;
667     }
668 
669 #endif  /* android init managed sockets */
670 
671   if (listen (listen_fd, 30 /* backlog */) < 0)
672     {
673       dbus_set_error (error, _dbus_error_from_errno (errno),
674                       "Failed to listen on socket \"%s\": %s",
675                       path, _dbus_strerror (errno));
676       _dbus_close (listen_fd, NULL);
677       return -1;
678     }
679 
680   if (!_dbus_set_local_creds (listen_fd, TRUE))
681     {
682       dbus_set_error (error, _dbus_error_from_errno (errno),
683                       "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
684                       path, _dbus_strerror (errno));
685       close (listen_fd);
686       return -1;
687     }
688 
689   if (!_dbus_set_fd_nonblocking (listen_fd, error))
690     {
691       _DBUS_ASSERT_ERROR_IS_SET (error);
692       _dbus_close (listen_fd, NULL);
693       return -1;
694     }
695 
696 #ifndef ANDROID_MANAGED_SOCKET
697   /* Try opening up the permissions, but if we can't, just go ahead
698    * and continue, maybe it will be good enough.
699    */
700   if (!abstract && chmod (path, 0777) < 0)
701     _dbus_warn ("Could not set mode 0777 on socket %s\n",
702                 path);
703 #endif
704 
705   return listen_fd;
706 }
707 
708 /**
709  * Creates a socket and connects to a socket at the given host
710  * and port. The connection fd is returned, and is set up as
711  * nonblocking.
712  *
713  * @param host the host name to connect to
714  * @param port the prot to connect to
715  * @param error return location for error code
716  * @returns connection file descriptor or -1 on error
717  */
718 int
_dbus_connect_tcp_socket(const char * host,dbus_uint32_t port,DBusError * error)719 _dbus_connect_tcp_socket (const char     *host,
720                           dbus_uint32_t   port,
721                           DBusError      *error)
722 {
723   int fd;
724   struct sockaddr_in addr;
725   struct hostent *he;
726   struct in_addr *haddr;
727 
728   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
729 
730 
731   if (!_dbus_open_tcp_socket (&fd, error))
732     {
733       _DBUS_ASSERT_ERROR_IS_SET(error);
734 
735       return -1;
736     }
737   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
738 
739   if (host == NULL)
740     host = "localhost";
741 
742   he = gethostbyname (host);
743   if (he == NULL)
744     {
745       dbus_set_error (error,
746                       _dbus_error_from_errno (errno),
747                       "Failed to lookup hostname: %s",
748                       host);
749       _dbus_close (fd, NULL);
750       return -1;
751     }
752 
753   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
754 
755   _DBUS_ZERO (addr);
756   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
757   addr.sin_family = AF_INET;
758   addr.sin_port = htons (port);
759 
760   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
761     {
762       dbus_set_error (error,
763                        _dbus_error_from_errno (errno),
764                       "Failed to connect to socket %s:%d %s",
765                       host, port, _dbus_strerror (errno));
766 
767       _dbus_close (fd, NULL);
768       fd = -1;
769 
770       return -1;
771     }
772 
773   if (!_dbus_set_fd_nonblocking (fd, error))
774     {
775       _dbus_close (fd, NULL);
776       fd = -1;
777 
778       return -1;
779     }
780 
781   return fd;
782 }
783 
784 /**
785  * Creates a socket and binds it to the given path,
786  * then listens on the socket. The socket is
787  * set to be nonblocking.
788  *
789  * @param host the host name to listen on
790  * @param port the prot to listen on
791  * @param error return location for errors
792  * @returns the listening file descriptor or -1 on error
793  */
794 int
_dbus_listen_tcp_socket(const char * host,dbus_uint32_t port,DBusError * error)795 _dbus_listen_tcp_socket (const char     *host,
796                          dbus_uint32_t   port,
797                          DBusError      *error)
798 {
799   int listen_fd;
800   struct sockaddr_in addr;
801   struct hostent *he;
802   struct in_addr *haddr;
803 
804   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
805 
806 
807   if (!_dbus_open_tcp_socket (&listen_fd, error))
808     {
809       _DBUS_ASSERT_ERROR_IS_SET(error);
810       return -1;
811     }
812   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
813 
814   he = gethostbyname (host);
815   if (he == NULL)
816     {
817       dbus_set_error (error,
818                       _dbus_error_from_errno (errno),
819                       "Failed to lookup hostname: %s",
820                       host);
821       _dbus_close (listen_fd, NULL);
822       return -1;
823     }
824 
825   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
826 
827   _DBUS_ZERO (addr);
828   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
829   addr.sin_family = AF_INET;
830   addr.sin_port = htons (port);
831 
832   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
833     {
834       dbus_set_error (error, _dbus_error_from_errno (errno),
835                       "Failed to bind socket \"%s:%d\": %s",
836                       host, port, _dbus_strerror (errno));
837       _dbus_close (listen_fd, NULL);
838       return -1;
839     }
840 
841   if (listen (listen_fd, 30 /* backlog */) < 0)
842     {
843       dbus_set_error (error, _dbus_error_from_errno (errno),
844                       "Failed to listen on socket \"%s:%d\": %s",
845                       host, port, _dbus_strerror (errno));
846       _dbus_close (listen_fd, NULL);
847       return -1;
848     }
849 
850   if (!_dbus_set_fd_nonblocking (listen_fd, error))
851     {
852       _dbus_close (listen_fd, NULL);
853       return -1;
854     }
855 
856   return listen_fd;
857 }
858 
859 static dbus_bool_t
write_credentials_byte(int server_fd,DBusError * error)860 write_credentials_byte (int             server_fd,
861                         DBusError      *error)
862 {
863   int bytes_written;
864   char buf[1] = { '\0' };
865 #if defined(HAVE_CMSGCRED)
866   struct {
867 	  struct cmsghdr hdr;
868 	  struct cmsgcred cred;
869   } cmsg;
870   struct iovec iov;
871   struct msghdr msg;
872   iov.iov_base = buf;
873   iov.iov_len = 1;
874 
875   memset (&msg, 0, sizeof (msg));
876   msg.msg_iov = &iov;
877   msg.msg_iovlen = 1;
878 
879   msg.msg_control = &cmsg;
880   msg.msg_controllen = sizeof (cmsg);
881   memset (&cmsg, 0, sizeof (cmsg));
882   cmsg.hdr.cmsg_len = sizeof (cmsg);
883   cmsg.hdr.cmsg_level = SOL_SOCKET;
884   cmsg.hdr.cmsg_type = SCM_CREDS;
885 #endif
886 
887   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
888 
889  again:
890 
891 #if defined(HAVE_CMSGCRED)
892   bytes_written = sendmsg (server_fd, &msg, 0);
893 #else
894   bytes_written = write (server_fd, buf, 1);
895 #endif
896 
897   if (bytes_written < 0 && errno == EINTR)
898     goto again;
899 
900   if (bytes_written < 0)
901     {
902       dbus_set_error (error, _dbus_error_from_errno (errno),
903                       "Failed to write credentials byte: %s",
904                      _dbus_strerror (errno));
905       return FALSE;
906     }
907   else if (bytes_written == 0)
908     {
909       dbus_set_error (error, DBUS_ERROR_IO_ERROR,
910                       "wrote zero bytes writing credentials byte");
911       return FALSE;
912     }
913   else
914     {
915       _dbus_assert (bytes_written == 1);
916       _dbus_verbose ("wrote credentials byte\n");
917       return TRUE;
918     }
919 }
920 
921 /**
922  * Reads a single byte which must be nul (an error occurs otherwise),
923  * and reads unix credentials if available. Fills in pid/uid/gid with
924  * -1 if no credentials are available. Return value indicates whether
925  * a byte was read, not whether we got valid credentials. On some
926  * systems, such as Linux, reading/writing the byte isn't actually
927  * required, but we do it anyway just to avoid multiple codepaths.
928  *
929  * Fails if no byte is available, so you must select() first.
930  *
931  * The point of the byte is that on some systems we have to
932  * use sendmsg()/recvmsg() to transmit credentials.
933  *
934  * @param client_fd the client file descriptor
935  * @param credentials struct to fill with credentials of client
936  * @param error location to store error code
937  * @returns #TRUE on success
938  */
939 dbus_bool_t
_dbus_read_credentials_unix_socket(int client_fd,DBusCredentials * credentials,DBusError * error)940 _dbus_read_credentials_unix_socket  (int              client_fd,
941                                      DBusCredentials *credentials,
942                                      DBusError       *error)
943 {
944   struct msghdr msg;
945   struct iovec iov;
946   char buf;
947 
948 #ifdef HAVE_CMSGCRED
949   struct {
950 	  struct cmsghdr hdr;
951 	  struct cmsgcred cred;
952   } cmsg;
953 
954 #elif defined(LOCAL_CREDS)
955   struct {
956 	  struct cmsghdr hdr;
957 	  struct sockcred cred;
958   } cmsg;
959 #endif
960 
961   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
962 
963   /* The POSIX spec certainly doesn't promise this, but
964    * we need these assertions to fail as soon as we're wrong about
965    * it so we can do the porting fixups
966    */
967   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
968   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
969   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
970 
971   _dbus_credentials_clear (credentials);
972 
973   /* Systems supporting LOCAL_CREDS are configured to have this feature
974    * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
975    * the connection.  Therefore, the received message must carry the
976    * credentials information without doing anything special.
977    */
978 
979   iov.iov_base = &buf;
980   iov.iov_len = 1;
981 
982   memset (&msg, 0, sizeof (msg));
983   msg.msg_iov = &iov;
984   msg.msg_iovlen = 1;
985 
986 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
987   memset (&cmsg, 0, sizeof (cmsg));
988   msg.msg_control = &cmsg;
989   msg.msg_controllen = sizeof (cmsg);
990 #endif
991 
992  again:
993   if (recvmsg (client_fd, &msg, 0) < 0)
994     {
995       if (errno == EINTR)
996 	goto again;
997 
998       dbus_set_error (error, _dbus_error_from_errno (errno),
999                       "Failed to read credentials byte: %s",
1000                       _dbus_strerror (errno));
1001       return FALSE;
1002     }
1003 
1004   if (buf != '\0')
1005     {
1006       dbus_set_error (error, DBUS_ERROR_FAILED,
1007                       "Credentials byte was not nul");
1008       return FALSE;
1009     }
1010 
1011 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
1012   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
1013     {
1014       dbus_set_error (error, DBUS_ERROR_FAILED,
1015                       "Message from recvmsg() was not SCM_CREDS");
1016       return FALSE;
1017     }
1018 #endif
1019 
1020   _dbus_verbose ("read credentials byte\n");
1021 
1022   {
1023 #ifdef SO_PEERCRED
1024     struct ucred cr;
1025     int cr_len = sizeof (cr);
1026 
1027     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
1028 	cr_len == sizeof (cr))
1029       {
1030 	credentials->pid = cr.pid;
1031 	credentials->uid = cr.uid;
1032 	credentials->gid = cr.gid;
1033       }
1034     else
1035       {
1036 	_dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
1037 		       cr_len, (int) sizeof (cr), _dbus_strerror (errno));
1038       }
1039 #elif defined(HAVE_CMSGCRED)
1040     credentials->pid = cmsg.cred.cmcred_pid;
1041     credentials->uid = cmsg.cred.cmcred_euid;
1042     credentials->gid = cmsg.cred.cmcred_groups[0];
1043 #elif defined(LOCAL_CREDS)
1044     credentials->pid = DBUS_PID_UNSET;
1045     credentials->uid = cmsg.cred.sc_uid;
1046     credentials->gid = cmsg.cred.sc_gid;
1047     /* Since we have already got the credentials from this socket, we can
1048      * disable its LOCAL_CREDS flag if it was ever set. */
1049     _dbus_set_local_creds (client_fd, FALSE);
1050 #elif defined(HAVE_GETPEEREID)
1051     uid_t euid;
1052     gid_t egid;
1053     if (getpeereid (client_fd, &euid, &egid) == 0)
1054       {
1055         credentials->uid = euid;
1056         credentials->gid = egid;
1057       }
1058     else
1059       {
1060         _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
1061       }
1062 #elif defined(HAVE_GETPEERUCRED)
1063     ucred_t * ucred = NULL;
1064     if (getpeerucred (client_fd, &ucred) == 0)
1065       {
1066         credentials->pid = ucred_getpid (ucred);
1067         credentials->uid = ucred_geteuid (ucred);
1068         credentials->gid = ucred_getegid (ucred);
1069       }
1070     else
1071       {
1072         _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
1073       }
1074     if (ucred != NULL)
1075       ucred_free (ucred);
1076 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
1077     _dbus_verbose ("Socket credentials not supported on this OS\n");
1078 #endif
1079   }
1080 
1081   _dbus_verbose ("Credentials:"
1082                  "  pid "DBUS_PID_FORMAT
1083                  "  uid "DBUS_UID_FORMAT
1084                  "  gid "DBUS_GID_FORMAT"\n",
1085 		 credentials->pid,
1086 		 credentials->uid,
1087 		 credentials->gid);
1088 
1089   return TRUE;
1090 }
1091 
1092 /**
1093  * Sends a single nul byte with our UNIX credentials as ancillary
1094  * data.  Returns #TRUE if the data was successfully written.  On
1095  * systems that don't support sending credentials, just writes a byte,
1096  * doesn't send any credentials.  On some systems, such as Linux,
1097  * reading/writing the byte isn't actually required, but we do it
1098  * anyway just to avoid multiple codepaths.
1099  *
1100  * Fails if no byte can be written, so you must select() first.
1101  *
1102  * The point of the byte is that on some systems we have to
1103  * use sendmsg()/recvmsg() to transmit credentials.
1104  *
1105  * @param server_fd file descriptor for connection to server
1106  * @param error return location for error code
1107  * @returns #TRUE if the byte was sent
1108  */
1109 dbus_bool_t
_dbus_send_credentials_unix_socket(int server_fd,DBusError * error)1110 _dbus_send_credentials_unix_socket  (int              server_fd,
1111                                      DBusError       *error)
1112 {
1113   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1114 
1115   if (write_credentials_byte (server_fd, error))
1116     return TRUE;
1117   else
1118     return FALSE;
1119 }
1120 
1121 /**
1122  * Accepts a connection on a listening socket.
1123  * Handles EINTR for you.
1124  *
1125  * @param listen_fd the listen file descriptor
1126  * @returns the connection fd of the client, or -1 on error
1127  */
1128 int
_dbus_accept(int listen_fd)1129 _dbus_accept  (int listen_fd)
1130 {
1131   int client_fd;
1132   struct sockaddr addr;
1133   socklen_t addrlen;
1134 
1135   addrlen = sizeof (addr);
1136 
1137  retry:
1138   client_fd = accept (listen_fd, &addr, &addrlen);
1139 
1140   if (client_fd < 0)
1141     {
1142       if (errno == EINTR)
1143         goto retry;
1144     }
1145 
1146   return client_fd;
1147 }
1148 
1149 /**
1150  * Checks to make sure the given directory is
1151  * private to the user
1152  *
1153  * @param dir the name of the directory
1154  * @param error error return
1155  * @returns #FALSE on failure
1156  **/
1157 dbus_bool_t
_dbus_check_dir_is_private_to_user(DBusString * dir,DBusError * error)1158 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
1159 {
1160   const char *directory;
1161   struct stat sb;
1162 
1163   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1164 
1165   directory = _dbus_string_get_const_data (dir);
1166 
1167   if (stat (directory, &sb) < 0)
1168     {
1169       dbus_set_error (error, _dbus_error_from_errno (errno),
1170                       "%s", _dbus_strerror (errno));
1171 
1172       return FALSE;
1173     }
1174 
1175   if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
1176       (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
1177     {
1178       dbus_set_error (error, DBUS_ERROR_FAILED,
1179                      "%s directory is not private to the user", directory);
1180       return FALSE;
1181     }
1182 
1183   return TRUE;
1184 }
1185 
1186 static dbus_bool_t
fill_user_info_from_passwd(struct passwd * p,DBusUserInfo * info,DBusError * error)1187 fill_user_info_from_passwd (struct passwd *p,
1188                             DBusUserInfo  *info,
1189                             DBusError     *error)
1190 {
1191   _dbus_assert (p->pw_name != NULL);
1192   _dbus_assert (p->pw_dir != NULL);
1193 
1194   info->uid = p->pw_uid;
1195   info->primary_gid = p->pw_gid;
1196   info->username = _dbus_strdup (p->pw_name);
1197   info->homedir = _dbus_strdup (p->pw_dir);
1198 
1199   if (info->username == NULL ||
1200       info->homedir == NULL)
1201     {
1202       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1203       return FALSE;
1204     }
1205 
1206   return TRUE;
1207 }
1208 
1209 static dbus_bool_t
fill_user_info(DBusUserInfo * info,dbus_uid_t uid,const DBusString * username,DBusError * error)1210 fill_user_info (DBusUserInfo       *info,
1211                 dbus_uid_t          uid,
1212                 const DBusString   *username,
1213                 DBusError          *error)
1214 {
1215   const char *username_c;
1216 
1217   /* exactly one of username/uid provided */
1218   _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
1219   _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
1220 
1221   info->uid = DBUS_UID_UNSET;
1222   info->primary_gid = DBUS_GID_UNSET;
1223   info->group_ids = NULL;
1224   info->n_group_ids = 0;
1225   info->username = NULL;
1226   info->homedir = NULL;
1227 
1228   if (username != NULL)
1229     username_c = _dbus_string_get_const_data (username);
1230   else
1231     username_c = NULL;
1232 
1233   /* For now assuming that the getpwnam() and getpwuid() flavors
1234    * are always symmetrical, if not we have to add more configure
1235    * checks
1236    */
1237 
1238 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
1239   {
1240     struct passwd *p;
1241     int result;
1242     char buf[1024];
1243     struct passwd p_str;
1244 
1245     p = NULL;
1246 #ifdef HAVE_POSIX_GETPWNAM_R
1247     if (uid != DBUS_UID_UNSET)
1248       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
1249                            &p);
1250     else
1251       result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
1252                            &p);
1253 #else
1254     if (uid != DBUS_UID_UNSET)
1255       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
1256     else
1257       p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
1258     result = 0;
1259 #endif /* !HAVE_POSIX_GETPWNAM_R */
1260     if (result == 0 && p == &p_str)
1261       {
1262         if (!fill_user_info_from_passwd (p, info, error))
1263           return FALSE;
1264       }
1265     else
1266       {
1267         dbus_set_error (error, _dbus_error_from_errno (errno),
1268                         "User \"%s\" unknown or no memory to allocate password entry\n",
1269                         username_c ? username_c : "???");
1270         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
1271         return FALSE;
1272       }
1273   }
1274 #else /* ! HAVE_GETPWNAM_R */
1275   {
1276     /* I guess we're screwed on thread safety here */
1277     struct passwd *p;
1278 
1279     if (uid != DBUS_UID_UNSET)
1280       p = getpwuid (uid);
1281     else
1282       p = getpwnam (username_c);
1283 
1284     if (p != NULL)
1285       {
1286         if (!fill_user_info_from_passwd (p, info, error))
1287           return FALSE;
1288       }
1289     else
1290       {
1291         dbus_set_error (error, _dbus_error_from_errno (errno),
1292                         "User \"%s\" unknown or no memory to allocate password entry\n",
1293                         username_c ? username_c : "???");
1294         _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
1295         return FALSE;
1296       }
1297   }
1298 #endif  /* ! HAVE_GETPWNAM_R */
1299 
1300   /* Fill this in so we can use it to get groups */
1301   username_c = info->username;
1302 
1303 #ifdef HAVE_GETGROUPLIST
1304   {
1305     gid_t *buf;
1306     int buf_count;
1307     int i;
1308 
1309     buf_count = 17;
1310     buf = dbus_new (gid_t, buf_count);
1311     if (buf == NULL)
1312       {
1313         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1314         goto failed;
1315       }
1316 
1317     if (getgrouplist (username_c,
1318                       info->primary_gid,
1319                       buf, &buf_count) < 0)
1320       {
1321         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
1322         if (new == NULL)
1323           {
1324             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1325             dbus_free (buf);
1326             goto failed;
1327           }
1328 
1329         buf = new;
1330 
1331         errno = 0;
1332         if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
1333           {
1334             dbus_set_error (error,
1335                             _dbus_error_from_errno (errno),
1336                             "Failed to get groups for username \"%s\" primary GID "
1337                             DBUS_GID_FORMAT ": %s\n",
1338                             username_c, info->primary_gid,
1339                             _dbus_strerror (errno));
1340             dbus_free (buf);
1341             goto failed;
1342           }
1343       }
1344 
1345     info->group_ids = dbus_new (dbus_gid_t, buf_count);
1346     if (info->group_ids == NULL)
1347       {
1348         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1349         dbus_free (buf);
1350         goto failed;
1351       }
1352 
1353     for (i = 0; i < buf_count; ++i)
1354       info->group_ids[i] = buf[i];
1355 
1356     info->n_group_ids = buf_count;
1357 
1358     dbus_free (buf);
1359   }
1360 #else  /* HAVE_GETGROUPLIST */
1361   {
1362     /* We just get the one group ID */
1363     info->group_ids = dbus_new (dbus_gid_t, 1);
1364     if (info->group_ids == NULL)
1365       {
1366         dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1367         goto failed;
1368       }
1369 
1370     info->n_group_ids = 1;
1371 
1372     (info->group_ids)[0] = info->primary_gid;
1373   }
1374 #endif /* HAVE_GETGROUPLIST */
1375 
1376   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1377 
1378   return TRUE;
1379 
1380  failed:
1381   _DBUS_ASSERT_ERROR_IS_SET (error);
1382   return FALSE;
1383 }
1384 
1385 /**
1386  * Gets user info for the given username.
1387  *
1388  * @param info user info object to initialize
1389  * @param username the username
1390  * @param error error return
1391  * @returns #TRUE on success
1392  */
1393 dbus_bool_t
_dbus_user_info_fill(DBusUserInfo * info,const DBusString * username,DBusError * error)1394 _dbus_user_info_fill (DBusUserInfo     *info,
1395                       const DBusString *username,
1396                       DBusError        *error)
1397 {
1398   return fill_user_info (info, DBUS_UID_UNSET,
1399                          username, error);
1400 }
1401 
1402 /**
1403  * Gets user info for the given user ID.
1404  *
1405  * @param info user info object to initialize
1406  * @param uid the user ID
1407  * @param error error return
1408  * @returns #TRUE on success
1409  */
1410 dbus_bool_t
_dbus_user_info_fill_uid(DBusUserInfo * info,dbus_uid_t uid,DBusError * error)1411 _dbus_user_info_fill_uid (DBusUserInfo *info,
1412                           dbus_uid_t    uid,
1413                           DBusError    *error)
1414 {
1415   return fill_user_info (info, uid,
1416                          NULL, error);
1417 }
1418 
1419 /**
1420  * Gets the credentials of the current process.
1421  *
1422  * @param credentials credentials to fill in.
1423  */
1424 void
_dbus_credentials_from_current_process(DBusCredentials * credentials)1425 _dbus_credentials_from_current_process (DBusCredentials *credentials)
1426 {
1427   /* The POSIX spec certainly doesn't promise this, but
1428    * we need these assertions to fail as soon as we're wrong about
1429    * it so we can do the porting fixups
1430    */
1431   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
1432   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
1433   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
1434 
1435   credentials->pid = getpid ();
1436   credentials->uid = getuid ();
1437   credentials->gid = getgid ();
1438 }
1439 
1440 /**
1441  * Gets our process ID
1442  * @returns process ID
1443  */
1444 unsigned long
_dbus_getpid(void)1445 _dbus_getpid (void)
1446 {
1447   return getpid ();
1448 }
1449 
1450 /** Gets our UID
1451  * @returns process UID
1452  */
1453 dbus_uid_t
_dbus_getuid(void)1454 _dbus_getuid (void)
1455 {
1456   return getuid ();
1457 }
1458 
1459 #ifdef DBUS_BUILD_TESTS
1460 /** Gets our GID
1461  * @returns process GID
1462  */
1463 dbus_gid_t
_dbus_getgid(void)1464 _dbus_getgid (void)
1465 {
1466   return getgid ();
1467 }
1468 #endif
1469 
1470 /**
1471  * Wrapper for poll().
1472  *
1473  * @param fds the file descriptors to poll
1474  * @param n_fds number of descriptors in the array
1475  * @param timeout_milliseconds timeout or -1 for infinite
1476  * @returns numbers of fds with revents, or <0 on error
1477  */
1478 int
_dbus_poll(DBusPollFD * fds,int n_fds,int timeout_milliseconds)1479 _dbus_poll (DBusPollFD *fds,
1480             int         n_fds,
1481             int         timeout_milliseconds)
1482 {
1483 #ifdef HAVE_POLL
1484   /* This big thing is a constant expression and should get optimized
1485    * out of existence. So it's more robust than a configure check at
1486    * no cost.
1487    */
1488   if (_DBUS_POLLIN == POLLIN &&
1489       _DBUS_POLLPRI == POLLPRI &&
1490       _DBUS_POLLOUT == POLLOUT &&
1491       _DBUS_POLLERR == POLLERR &&
1492       _DBUS_POLLHUP == POLLHUP &&
1493       _DBUS_POLLNVAL == POLLNVAL &&
1494       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1495       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1496       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1497       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1498       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1499       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1500       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1501     {
1502       return poll ((struct pollfd*) fds,
1503                    n_fds,
1504                    timeout_milliseconds);
1505     }
1506   else
1507     {
1508       /* We have to convert the DBusPollFD to an array of
1509        * struct pollfd, poll, and convert back.
1510        */
1511       _dbus_warn ("didn't implement poll() properly for this system yet\n");
1512       return -1;
1513     }
1514 #else /* ! HAVE_POLL */
1515 
1516   fd_set read_set, write_set, err_set;
1517   int max_fd = 0;
1518   int i;
1519   struct timeval tv;
1520   int ready;
1521 
1522   FD_ZERO (&read_set);
1523   FD_ZERO (&write_set);
1524   FD_ZERO (&err_set);
1525 
1526   for (i = 0; i < n_fds; i++)
1527     {
1528       DBusPollFD *fdp = &fds[i];
1529 
1530       if (fdp->events & _DBUS_POLLIN)
1531 	FD_SET (fdp->fd, &read_set);
1532 
1533       if (fdp->events & _DBUS_POLLOUT)
1534 	FD_SET (fdp->fd, &write_set);
1535 
1536       FD_SET (fdp->fd, &err_set);
1537 
1538       max_fd = MAX (max_fd, fdp->fd);
1539     }
1540 
1541   tv.tv_sec = timeout_milliseconds / 1000;
1542   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1543 
1544   ready = select (max_fd + 1, &read_set, &write_set, &err_set,
1545                   timeout_milliseconds < 0 ? NULL : &tv);
1546 
1547   if (ready > 0)
1548     {
1549       for (i = 0; i < n_fds; i++)
1550 	{
1551 	  DBusPollFD *fdp = &fds[i];
1552 
1553 	  fdp->revents = 0;
1554 
1555 	  if (FD_ISSET (fdp->fd, &read_set))
1556 	    fdp->revents |= _DBUS_POLLIN;
1557 
1558 	  if (FD_ISSET (fdp->fd, &write_set))
1559 	    fdp->revents |= _DBUS_POLLOUT;
1560 
1561 	  if (FD_ISSET (fdp->fd, &err_set))
1562 	    fdp->revents |= _DBUS_POLLERR;
1563 	}
1564     }
1565 
1566   return ready;
1567 #endif
1568 }
1569 
1570 /**
1571  * Get current time, as in gettimeofday().
1572  *
1573  * @param tv_sec return location for number of seconds
1574  * @param tv_usec return location for number of microseconds (thousandths)
1575  */
1576 void
_dbus_get_current_time(long * tv_sec,long * tv_usec)1577 _dbus_get_current_time (long *tv_sec,
1578                         long *tv_usec)
1579 {
1580   struct timeval t;
1581 
1582   gettimeofday (&t, NULL);
1583 
1584   if (tv_sec)
1585     *tv_sec = t.tv_sec;
1586   if (tv_usec)
1587     *tv_usec = t.tv_usec;
1588 }
1589 
1590 /**
1591  * Appends the contents of the given file to the string,
1592  * returning error code. At the moment, won't open a file
1593  * more than a megabyte in size.
1594  *
1595  * @param str the string to append to
1596  * @param filename filename to load
1597  * @param error place to set an error
1598  * @returns #FALSE if error was set
1599  */
1600 dbus_bool_t
_dbus_file_get_contents(DBusString * str,const DBusString * filename,DBusError * error)1601 _dbus_file_get_contents (DBusString       *str,
1602                          const DBusString *filename,
1603                          DBusError        *error)
1604 {
1605   int fd;
1606   struct stat sb;
1607   int orig_len;
1608   int total;
1609   const char *filename_c;
1610 
1611   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1612 
1613   filename_c = _dbus_string_get_const_data (filename);
1614 
1615   /* O_BINARY useful on Cygwin */
1616   fd = open (filename_c, O_RDONLY | O_BINARY);
1617   if (fd < 0)
1618     {
1619       dbus_set_error (error, _dbus_error_from_errno (errno),
1620                       "Failed to open \"%s\": %s",
1621                       filename_c,
1622                       _dbus_strerror (errno));
1623       return FALSE;
1624     }
1625 
1626   if (fstat (fd, &sb) < 0)
1627     {
1628       dbus_set_error (error, _dbus_error_from_errno (errno),
1629                       "Failed to stat \"%s\": %s",
1630                       filename_c,
1631                       _dbus_strerror (errno));
1632 
1633       _dbus_verbose ("fstat() failed: %s",
1634                      _dbus_strerror (errno));
1635 
1636       _dbus_close (fd, NULL);
1637 
1638       return FALSE;
1639     }
1640 
1641   if (sb.st_size > _DBUS_ONE_MEGABYTE)
1642     {
1643       dbus_set_error (error, DBUS_ERROR_FAILED,
1644                       "File size %lu of \"%s\" is too large.",
1645                       (unsigned long) sb.st_size, filename_c);
1646       _dbus_close (fd, NULL);
1647       return FALSE;
1648     }
1649 
1650   total = 0;
1651   orig_len = _dbus_string_get_length (str);
1652   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
1653     {
1654       int bytes_read;
1655 
1656       while (total < (int) sb.st_size)
1657         {
1658           bytes_read = _dbus_read (fd, str,
1659                                    sb.st_size - total);
1660           if (bytes_read <= 0)
1661             {
1662               dbus_set_error (error, _dbus_error_from_errno (errno),
1663                               "Error reading \"%s\": %s",
1664                               filename_c,
1665                               _dbus_strerror (errno));
1666 
1667               _dbus_verbose ("read() failed: %s",
1668                              _dbus_strerror (errno));
1669 
1670               _dbus_close (fd, NULL);
1671               _dbus_string_set_length (str, orig_len);
1672               return FALSE;
1673             }
1674           else
1675             total += bytes_read;
1676         }
1677 
1678       _dbus_close (fd, NULL);
1679       return TRUE;
1680     }
1681   else if (sb.st_size != 0)
1682     {
1683       _dbus_verbose ("Can only open regular files at the moment.\n");
1684       dbus_set_error (error, DBUS_ERROR_FAILED,
1685                       "\"%s\" is not a regular file",
1686                       filename_c);
1687       _dbus_close (fd, NULL);
1688       return FALSE;
1689     }
1690   else
1691     {
1692       _dbus_close (fd, NULL);
1693       return TRUE;
1694     }
1695 }
1696 
1697 /**
1698  * Writes a string out to a file. If the file exists,
1699  * it will be atomically overwritten by the new data.
1700  *
1701  * @param str the string to write out
1702  * @param filename the file to save string to
1703  * @param error error to be filled in on failure
1704  * @returns #FALSE on failure
1705  */
1706 dbus_bool_t
_dbus_string_save_to_file(const DBusString * str,const DBusString * filename,DBusError * error)1707 _dbus_string_save_to_file (const DBusString *str,
1708                            const DBusString *filename,
1709                            DBusError        *error)
1710 {
1711   int fd;
1712   int bytes_to_write;
1713   const char *filename_c;
1714   DBusString tmp_filename;
1715   const char *tmp_filename_c;
1716   int total;
1717   dbus_bool_t need_unlink;
1718   dbus_bool_t retval;
1719 
1720   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1721 
1722   fd = -1;
1723   retval = FALSE;
1724   need_unlink = FALSE;
1725 
1726   if (!_dbus_string_init (&tmp_filename))
1727     {
1728       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1729       return FALSE;
1730     }
1731 
1732   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
1733     {
1734       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1735       _dbus_string_free (&tmp_filename);
1736       return FALSE;
1737     }
1738 
1739   if (!_dbus_string_append (&tmp_filename, "."))
1740     {
1741       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1742       _dbus_string_free (&tmp_filename);
1743       return FALSE;
1744     }
1745 
1746 #define N_TMP_FILENAME_RANDOM_BYTES 8
1747   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
1748     {
1749       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1750       _dbus_string_free (&tmp_filename);
1751       return FALSE;
1752     }
1753 
1754   filename_c = _dbus_string_get_const_data (filename);
1755   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
1756 
1757   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1758              0600);
1759   if (fd < 0)
1760     {
1761       dbus_set_error (error, _dbus_error_from_errno (errno),
1762                       "Could not create %s: %s", tmp_filename_c,
1763                       _dbus_strerror (errno));
1764       goto out;
1765     }
1766 
1767   need_unlink = TRUE;
1768 
1769   total = 0;
1770   bytes_to_write = _dbus_string_get_length (str);
1771 
1772   while (total < bytes_to_write)
1773     {
1774       int bytes_written;
1775 
1776       bytes_written = _dbus_write (fd, str, total,
1777                                    bytes_to_write - total);
1778 
1779       if (bytes_written <= 0)
1780         {
1781           dbus_set_error (error, _dbus_error_from_errno (errno),
1782                           "Could not write to %s: %s", tmp_filename_c,
1783                           _dbus_strerror (errno));
1784 
1785           goto out;
1786         }
1787 
1788       total += bytes_written;
1789     }
1790 
1791   if (!_dbus_close (fd, NULL))
1792     {
1793       dbus_set_error (error, _dbus_error_from_errno (errno),
1794                       "Could not close file %s: %s",
1795                       tmp_filename_c, _dbus_strerror (errno));
1796 
1797       goto out;
1798     }
1799 
1800   fd = -1;
1801 
1802   if (rename (tmp_filename_c, filename_c) < 0)
1803     {
1804       dbus_set_error (error, _dbus_error_from_errno (errno),
1805                       "Could not rename %s to %s: %s",
1806                       tmp_filename_c, filename_c,
1807                       _dbus_strerror (errno));
1808 
1809       goto out;
1810     }
1811 
1812   need_unlink = FALSE;
1813 
1814   retval = TRUE;
1815 
1816  out:
1817   /* close first, then unlink, to prevent ".nfs34234235" garbage
1818    * files
1819    */
1820 
1821   if (fd >= 0)
1822     _dbus_close (fd, NULL);
1823 
1824   if (need_unlink && unlink (tmp_filename_c) < 0)
1825     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
1826                    tmp_filename_c, _dbus_strerror (errno));
1827 
1828   _dbus_string_free (&tmp_filename);
1829 
1830   if (!retval)
1831     _DBUS_ASSERT_ERROR_IS_SET (error);
1832 
1833   return retval;
1834 }
1835 
1836 /** Makes the file readable by every user in the system.
1837  *
1838  * @param filename the filename
1839  * @param error error location
1840  * @returns #TRUE if the file's permissions could be changed.
1841  */
1842 dbus_bool_t
_dbus_make_file_world_readable(const DBusString * filename,DBusError * error)1843 _dbus_make_file_world_readable(const DBusString *filename,
1844                                DBusError *error)
1845 {
1846   const char *filename_c;
1847 
1848   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1849 
1850   filename_c = _dbus_string_get_const_data (filename);
1851   if (chmod (filename_c, 0644) == -1)
1852     {
1853       dbus_set_error (error,
1854                       DBUS_ERROR_FAILED,
1855                       "Could not change permissions of file %s: %s\n",
1856                       filename_c,
1857                       _dbus_strerror (errno));
1858       return FALSE;
1859     }
1860   return TRUE;
1861 }
1862 
1863 /** Creates the given file, failing if the file already exists.
1864  *
1865  * @param filename the filename
1866  * @param error error location
1867  * @returns #TRUE if we created the file and it didn't exist
1868  */
1869 dbus_bool_t
_dbus_create_file_exclusively(const DBusString * filename,DBusError * error)1870 _dbus_create_file_exclusively (const DBusString *filename,
1871                                DBusError        *error)
1872 {
1873   int fd;
1874   const char *filename_c;
1875 
1876   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1877 
1878   filename_c = _dbus_string_get_const_data (filename);
1879 
1880   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1881              0600);
1882   if (fd < 0)
1883     {
1884       dbus_set_error (error,
1885                       DBUS_ERROR_FAILED,
1886                       "Could not create file %s: %s\n",
1887                       filename_c,
1888                       _dbus_strerror (errno));
1889       return FALSE;
1890     }
1891 
1892   if (!_dbus_close (fd, NULL))
1893     {
1894       dbus_set_error (error,
1895                       DBUS_ERROR_FAILED,
1896                       "Could not close file %s: %s\n",
1897                       filename_c,
1898                       _dbus_strerror (errno));
1899       return FALSE;
1900     }
1901 
1902   return TRUE;
1903 }
1904 
1905 /**
1906  * Deletes the given file.
1907  *
1908  * @param filename the filename
1909  * @param error error location
1910  *
1911  * @returns #TRUE if unlink() succeeded
1912  */
1913 dbus_bool_t
_dbus_delete_file(const DBusString * filename,DBusError * error)1914 _dbus_delete_file (const DBusString *filename,
1915                    DBusError        *error)
1916 {
1917   const char *filename_c;
1918 
1919   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1920 
1921   filename_c = _dbus_string_get_const_data (filename);
1922 
1923   if (unlink (filename_c) < 0)
1924     {
1925       dbus_set_error (error, DBUS_ERROR_FAILED,
1926                       "Failed to delete file %s: %s\n",
1927                       filename_c, _dbus_strerror (errno));
1928       return FALSE;
1929     }
1930   else
1931     return TRUE;
1932 }
1933 
1934 /**
1935  * Creates a directory; succeeds if the directory
1936  * is created or already existed.
1937  *
1938  * @param filename directory filename
1939  * @param error initialized error object
1940  * @returns #TRUE on success
1941  */
1942 dbus_bool_t
_dbus_create_directory(const DBusString * filename,DBusError * error)1943 _dbus_create_directory (const DBusString *filename,
1944                         DBusError        *error)
1945 {
1946   const char *filename_c;
1947 
1948   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1949 
1950   filename_c = _dbus_string_get_const_data (filename);
1951 
1952   if (mkdir (filename_c, 0700) < 0)
1953     {
1954       if (errno == EEXIST)
1955         return TRUE;
1956 
1957       dbus_set_error (error, DBUS_ERROR_FAILED,
1958                       "Failed to create directory %s: %s\n",
1959                       filename_c, _dbus_strerror (errno));
1960       return FALSE;
1961     }
1962   else
1963     return TRUE;
1964 }
1965 
1966 /**
1967  * Appends the given filename to the given directory.
1968  *
1969  * @todo it might be cute to collapse multiple '/' such as "foo//"
1970  * concat "//bar"
1971  *
1972  * @param dir the directory name
1973  * @param next_component the filename
1974  * @returns #TRUE on success
1975  */
1976 dbus_bool_t
_dbus_concat_dir_and_file(DBusString * dir,const DBusString * next_component)1977 _dbus_concat_dir_and_file (DBusString       *dir,
1978                            const DBusString *next_component)
1979 {
1980   dbus_bool_t dir_ends_in_slash;
1981   dbus_bool_t file_starts_with_slash;
1982 
1983   if (_dbus_string_get_length (dir) == 0 ||
1984       _dbus_string_get_length (next_component) == 0)
1985     return TRUE;
1986 
1987   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
1988                                                     _dbus_string_get_length (dir) - 1);
1989 
1990   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
1991 
1992   if (dir_ends_in_slash && file_starts_with_slash)
1993     {
1994       _dbus_string_shorten (dir, 1);
1995     }
1996   else if (!(dir_ends_in_slash || file_starts_with_slash))
1997     {
1998       if (!_dbus_string_append_byte (dir, '/'))
1999         return FALSE;
2000     }
2001 
2002   return _dbus_string_copy (next_component, 0, dir,
2003                             _dbus_string_get_length (dir));
2004 }
2005 
2006 /** nanoseconds in a second */
2007 #define NANOSECONDS_PER_SECOND       1000000000
2008 /** microseconds in a second */
2009 #define MICROSECONDS_PER_SECOND      1000000
2010 /** milliseconds in a second */
2011 #define MILLISECONDS_PER_SECOND      1000
2012 /** nanoseconds in a millisecond */
2013 #define NANOSECONDS_PER_MILLISECOND  1000000
2014 /** microseconds in a millisecond */
2015 #define MICROSECONDS_PER_MILLISECOND 1000
2016 
2017 /**
2018  * Sleeps the given number of milliseconds.
2019  * @param milliseconds number of milliseconds
2020  */
2021 void
_dbus_sleep_milliseconds(int milliseconds)2022 _dbus_sleep_milliseconds (int milliseconds)
2023 {
2024 #ifdef HAVE_NANOSLEEP
2025   struct timespec req;
2026   struct timespec rem;
2027 
2028   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
2029   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
2030   rem.tv_sec = 0;
2031   rem.tv_nsec = 0;
2032 
2033   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
2034     req = rem;
2035 #elif defined (HAVE_USLEEP)
2036   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
2037 #else /* ! HAVE_USLEEP */
2038   sleep (MAX (milliseconds / 1000, 1));
2039 #endif
2040 }
2041 
2042 static dbus_bool_t
_dbus_generate_pseudorandom_bytes(DBusString * str,int n_bytes)2043 _dbus_generate_pseudorandom_bytes (DBusString *str,
2044                                    int         n_bytes)
2045 {
2046   int old_len;
2047   char *p;
2048 
2049   old_len = _dbus_string_get_length (str);
2050 
2051   if (!_dbus_string_lengthen (str, n_bytes))
2052     return FALSE;
2053 
2054   p = _dbus_string_get_data_len (str, old_len, n_bytes);
2055 
2056   _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
2057 
2058   return TRUE;
2059 }
2060 
2061 /**
2062  * Generates the given number of random bytes,
2063  * using the best mechanism we can come up with.
2064  *
2065  * @param str the string
2066  * @param n_bytes the number of random bytes to append to string
2067  * @returns #TRUE on success, #FALSE if no memory
2068  */
2069 dbus_bool_t
_dbus_generate_random_bytes(DBusString * str,int n_bytes)2070 _dbus_generate_random_bytes (DBusString *str,
2071                              int         n_bytes)
2072 {
2073   int old_len;
2074   int fd;
2075 
2076   /* FALSE return means "no memory", if it could
2077    * mean something else then we'd need to return
2078    * a DBusError. So we always fall back to pseudorandom
2079    * if the I/O fails.
2080    */
2081 
2082   old_len = _dbus_string_get_length (str);
2083   fd = -1;
2084 
2085   /* note, urandom on linux will fall back to pseudorandom */
2086   fd = open ("/dev/urandom", O_RDONLY);
2087   if (fd < 0)
2088     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2089 
2090   if (_dbus_read (fd, str, n_bytes) != n_bytes)
2091     {
2092       _dbus_close (fd, NULL);
2093       _dbus_string_set_length (str, old_len);
2094       return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2095     }
2096 
2097   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2098                  n_bytes);
2099 
2100   _dbus_close (fd, NULL);
2101 
2102   return TRUE;
2103 }
2104 
2105 /**
2106  * Exit the process, returning the given value.
2107  *
2108  * @param code the exit code
2109  */
2110 void
_dbus_exit(int code)2111 _dbus_exit (int code)
2112 {
2113   _exit (code);
2114 }
2115 
2116 /**
2117  * A wrapper around strerror() because some platforms
2118  * may be lame and not have strerror().
2119  *
2120  * @param error_number errno.
2121  * @returns error description.
2122  */
2123 const char*
_dbus_strerror(int error_number)2124 _dbus_strerror (int error_number)
2125 {
2126   const char *msg;
2127 
2128   msg = strerror (error_number);
2129   if (msg == NULL)
2130     msg = "unknown";
2131 
2132   return msg;
2133 }
2134 
2135 /**
2136  * signal (SIGPIPE, SIG_IGN);
2137  */
2138 void
_dbus_disable_sigpipe(void)2139 _dbus_disable_sigpipe (void)
2140 {
2141   signal (SIGPIPE, SIG_IGN);
2142 }
2143 
2144 /**
2145  * Sets the file descriptor to be close
2146  * on exec. Should be called for all file
2147  * descriptors in D-Bus code.
2148  *
2149  * @param fd the file descriptor
2150  */
2151 void
_dbus_fd_set_close_on_exec(int fd)2152 _dbus_fd_set_close_on_exec (int fd)
2153 {
2154   int val;
2155 
2156   val = fcntl (fd, F_GETFD, 0);
2157 
2158   if (val < 0)
2159     return;
2160 
2161   val |= FD_CLOEXEC;
2162 
2163   fcntl (fd, F_SETFD, val);
2164 }
2165 
2166 /**
2167  * Closes a file descriptor.
2168  *
2169  * @param fd the file descriptor
2170  * @param error error object
2171  * @returns #FALSE if error set
2172  */
2173 dbus_bool_t
_dbus_close(int fd,DBusError * error)2174 _dbus_close (int        fd,
2175              DBusError *error)
2176 {
2177   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2178 
2179  again:
2180   if (close (fd) < 0)
2181     {
2182       if (errno == EINTR)
2183         goto again;
2184 
2185       dbus_set_error (error, _dbus_error_from_errno (errno),
2186                       "Could not close fd %d", fd);
2187       return FALSE;
2188     }
2189 
2190   return TRUE;
2191 }
2192 
2193 /**
2194  * Sets a file descriptor to be nonblocking.
2195  *
2196  * @param fd the file descriptor.
2197  * @param error address of error location.
2198  * @returns #TRUE on success.
2199  */
2200 dbus_bool_t
_dbus_set_fd_nonblocking(int fd,DBusError * error)2201 _dbus_set_fd_nonblocking (int             fd,
2202                           DBusError      *error)
2203 {
2204   int val;
2205 
2206   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2207 
2208   val = fcntl (fd, F_GETFL, 0);
2209   if (val < 0)
2210     {
2211       dbus_set_error (error, _dbus_error_from_errno (errno),
2212                       "Failed to get flags from file descriptor %d: %s",
2213                       fd, _dbus_strerror (errno));
2214       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
2215                      _dbus_strerror (errno));
2216       return FALSE;
2217     }
2218 
2219   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
2220     {
2221       dbus_set_error (error, _dbus_error_from_errno (errno),
2222                       "Failed to set nonblocking flag of file descriptor %d: %s",
2223                       fd, _dbus_strerror (errno));
2224       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
2225                      fd, _dbus_strerror (errno));
2226 
2227       return FALSE;
2228     }
2229 
2230   return TRUE;
2231 }
2232 
2233 /**
2234  * On GNU libc systems, print a crude backtrace to stderr.  On other
2235  * systems, print "no backtrace support" and block for possible gdb
2236  * attachment if an appropriate environment variable is set.
2237  */
2238 void
_dbus_print_backtrace(void)2239 _dbus_print_backtrace (void)
2240 {
2241 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
2242   void *bt[500];
2243   int bt_size;
2244   int i;
2245   char **syms;
2246 
2247   bt_size = backtrace (bt, 500);
2248 
2249   syms = backtrace_symbols (bt, bt_size);
2250 
2251   i = 0;
2252   while (i < bt_size)
2253     {
2254       /* don't use dbus_warn since it can _dbus_abort() */
2255       fprintf (stderr, "  %s\n", syms[i]);
2256       ++i;
2257     }
2258   fflush (stderr);
2259 
2260   free (syms);
2261 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
2262   fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
2263 #else
2264   fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
2265 #endif
2266 }
2267 
2268 /**
2269  * Creates a full-duplex pipe (as in socketpair()).
2270  * Sets both ends of the pipe nonblocking.
2271  *
2272  * @todo libdbus only uses this for the debug-pipe server, so in
2273  * principle it could be in dbus-sysdeps-util.c, except that
2274  * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
2275  * debug-pipe server is used.
2276  *
2277  * @param fd1 return location for one end
2278  * @param fd2 return location for the other end
2279  * @param blocking #TRUE if pipe should be blocking
2280  * @param error error return
2281  * @returns #FALSE on failure (if error is set)
2282  */
2283 dbus_bool_t
_dbus_full_duplex_pipe(int * fd1,int * fd2,dbus_bool_t blocking,DBusError * error)2284 _dbus_full_duplex_pipe (int        *fd1,
2285                         int        *fd2,
2286                         dbus_bool_t blocking,
2287                         DBusError  *error)
2288 {
2289 #ifdef HAVE_SOCKETPAIR
2290   int fds[2];
2291 
2292   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2293 
2294   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
2295     {
2296       dbus_set_error (error, _dbus_error_from_errno (errno),
2297                       "Could not create full-duplex pipe");
2298       return FALSE;
2299     }
2300 
2301   if (!blocking &&
2302       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
2303        !_dbus_set_fd_nonblocking (fds[1], NULL)))
2304     {
2305       dbus_set_error (error, _dbus_error_from_errno (errno),
2306                       "Could not set full-duplex pipe nonblocking");
2307 
2308       _dbus_close (fds[0], NULL);
2309       _dbus_close (fds[1], NULL);
2310 
2311       return FALSE;
2312     }
2313 
2314   *fd1 = fds[0];
2315   *fd2 = fds[1];
2316 
2317   _dbus_verbose ("full-duplex pipe %d <-> %d\n",
2318                  *fd1, *fd2);
2319 
2320   return TRUE;
2321 #else
2322   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
2323   dbus_set_error (error, DBUS_ERROR_FAILED,
2324                   "_dbus_full_duplex_pipe() not implemented on this OS");
2325   return FALSE;
2326 #endif
2327 }
2328 
2329 
2330 /**
2331  * Measure the length of the given format string and arguments,
2332  * not including the terminating nul.
2333  *
2334  * @param format a printf-style format string
2335  * @param args arguments for the format string
2336  * @returns length of the given format string and args
2337  */
2338 int
_dbus_printf_string_upper_bound(const char * format,va_list args)2339 _dbus_printf_string_upper_bound (const char *format,
2340                                  va_list     args)
2341 {
2342   char c;
2343   return vsnprintf (&c, 1, format, args);
2344 }
2345 
2346 /**
2347  * Gets the temporary files directory by inspecting the environment variables
2348  * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
2349  *
2350  * @returns location of temp directory
2351  */
2352 const char*
_dbus_get_tmpdir(void)2353 _dbus_get_tmpdir(void)
2354 {
2355   static const char* tmpdir = NULL;
2356 
2357   if (tmpdir == NULL)
2358     {
2359       /* TMPDIR is what glibc uses, then
2360        * glibc falls back to the P_tmpdir macro which
2361        * just expands to "/tmp"
2362        */
2363       if (tmpdir == NULL)
2364         tmpdir = getenv("TMPDIR");
2365 
2366       /* These two env variables are probably
2367        * broken, but maybe some OS uses them?
2368        */
2369       if (tmpdir == NULL)
2370         tmpdir = getenv("TMP");
2371       if (tmpdir == NULL)
2372         tmpdir = getenv("TEMP");
2373 
2374       /* And this is the sane fallback. */
2375       if (tmpdir == NULL)
2376         tmpdir = "/tmp";
2377     }
2378 
2379   _dbus_assert(tmpdir != NULL);
2380 
2381   return tmpdir;
2382 }
2383 
2384 /**
2385  * Determines the address of the session bus by querying a
2386  * platform-specific method.
2387  *
2388  * If successful, returns #TRUE and appends the address to @p
2389  * address. If a failure happens, returns #FALSE and
2390  * sets an error in @p error.
2391  *
2392  * @param address a DBusString where the address can be stored
2393  * @param error a DBusError to store the error in case of failure
2394  * @returns #TRUE on success, #FALSE if an error happened
2395  */
2396 dbus_bool_t
_dbus_get_autolaunch_address(DBusString * address,DBusError * error)2397 _dbus_get_autolaunch_address (DBusString *address,
2398                               DBusError  *error)
2399 {
2400   static char *argv[5];
2401   int address_pipe[2];
2402   pid_t pid;
2403   int ret;
2404   int status;
2405   int orig_len;
2406   int i;
2407   DBusString uuid;
2408   dbus_bool_t retval;
2409 
2410   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2411   retval = FALSE;
2412 
2413   _dbus_string_init (&uuid);
2414 
2415   if (!_dbus_get_local_machine_uuid_encoded (&uuid))
2416     {
2417       _DBUS_SET_OOM (error);
2418       goto out;
2419     }
2420 
2421   i = 0;
2422   argv[i] = "dbus-launch";
2423   ++i;
2424   argv[i] = "--autolaunch";
2425   ++i;
2426   argv[i] = _dbus_string_get_data (&uuid);
2427   ++i;
2428   argv[i] = "--binary-syntax";
2429   ++i;
2430   argv[i] = NULL;
2431   ++i;
2432 
2433   _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
2434 
2435   orig_len = _dbus_string_get_length (address);
2436 
2437 #define READ_END        0
2438 #define WRITE_END       1
2439   if (pipe (address_pipe) < 0)
2440     {
2441       dbus_set_error (error, _dbus_error_from_errno (errno),
2442                       "Failed to create a pipe: %s",
2443                       _dbus_strerror (errno));
2444       _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
2445                      _dbus_strerror (errno));
2446       goto out;
2447     }
2448 
2449   pid = fork ();
2450   if (pid < 0)
2451     {
2452       dbus_set_error (error, _dbus_error_from_errno (errno),
2453                       "Failed to fork(): %s",
2454                       _dbus_strerror (errno));
2455       _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
2456                      _dbus_strerror (errno));
2457       goto out;
2458     }
2459 
2460   if (pid == 0)
2461     {
2462       /* child process */
2463       int fd = open ("/dev/null", O_RDWR);
2464       if (fd == -1)
2465         /* huh?! can't open /dev/null? */
2466         _exit (1);
2467 
2468       /* set-up stdXXX */
2469       close (address_pipe[READ_END]);
2470       close (0);                /* close stdin */
2471       close (1);                /* close stdout */
2472       close (2);                /* close stderr */
2473 
2474       if (dup2 (fd, 0) == -1)
2475         _exit (1);
2476       if (dup2 (address_pipe[WRITE_END], 1) == -1)
2477         _exit (1);
2478       if (dup2 (fd, 2) == -1)
2479         _exit (1);
2480 
2481       close (fd);
2482       close (address_pipe[WRITE_END]);
2483 
2484       execv (DBUS_BINDIR "/dbus-launch", argv);
2485 
2486       /* failed, try searching PATH */
2487       execvp ("dbus-launch", argv);
2488 
2489       /* still nothing, we failed */
2490       _exit (1);
2491     }
2492 
2493   /* parent process */
2494   close (address_pipe[WRITE_END]);
2495   ret = 0;
2496   do
2497     {
2498       ret = _dbus_read (address_pipe[READ_END], address, 1024);
2499     }
2500   while (ret > 0);
2501 
2502   /* reap the child process to avoid it lingering as zombie */
2503   do
2504     {
2505       ret = waitpid (pid, &status, 0);
2506     }
2507   while (ret == -1 && errno == EINTR);
2508 
2509   /* We succeeded if the process exited with status 0 and
2510      anything was read */
2511   if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
2512       _dbus_string_get_length (address) == orig_len)
2513     {
2514       /* The process ended with error */
2515       _dbus_string_set_length (address, orig_len);
2516       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
2517                       "Failed to execute dbus-launch to autolaunch D-Bus session");
2518       goto out;
2519     }
2520 
2521   retval = TRUE;
2522 
2523  out:
2524   if (retval)
2525     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2526   else
2527     _DBUS_ASSERT_ERROR_IS_SET (error);
2528 
2529   _dbus_string_free (&uuid);
2530   return retval;
2531 }
2532 
2533 /**
2534  * Reads the uuid of the machine we're running on from
2535  * the dbus configuration. Optionally try to create it
2536  * (only root can do this usually).
2537  *
2538  * On UNIX, reads a file that gets created by dbus-uuidgen
2539  * in a post-install script. On Windows, if there's a standard
2540  * machine uuid we could just use that, but I can't find one
2541  * with the right properties (the hardware profile guid can change
2542  * without rebooting I believe). If there's no standard one
2543  * we might want to use the registry instead of a file for
2544  * this, and I'm not sure how we'd ensure the uuid gets created.
2545  *
2546  * @param machine_id guid to init with the machine's uuid
2547  * @param create_if_not_found try to create the uuid if it doesn't exist
2548  * @param error the error return
2549  * @returns #FALSE if the error is set
2550  */
2551 dbus_bool_t
_dbus_read_local_machine_uuid(DBusGUID * machine_id,dbus_bool_t create_if_not_found,DBusError * error)2552 _dbus_read_local_machine_uuid (DBusGUID   *machine_id,
2553                                dbus_bool_t create_if_not_found,
2554                                DBusError  *error)
2555 {
2556   DBusString filename;
2557   _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
2558   return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
2559 }
2560 
2561 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
2562 
2563 static dbus_bool_t
split_paths_and_append(DBusString * dirs,const char * suffix,DBusList ** dir_list)2564 split_paths_and_append (DBusString *dirs,
2565                         const char *suffix,
2566                         DBusList **dir_list)
2567 {
2568   /* split on colon (:) */
2569    int start;
2570    int i;
2571    int len;
2572    char *cpath;
2573    const DBusString file_suffix;
2574 
2575    start = 0;
2576    i = 0;
2577 
2578    _dbus_string_init_const (&file_suffix, suffix);
2579 
2580    len = _dbus_string_get_length (dirs);
2581 
2582    while (_dbus_string_find (dirs, start, ":", &i))
2583      {
2584        DBusString path;
2585 
2586        if (!_dbus_string_init (&path))
2587           goto oom;
2588 
2589        if (!_dbus_string_copy_len (dirs,
2590                                    start,
2591                                    i - start,
2592                                    &path,
2593                                    0))
2594           {
2595             _dbus_string_free (&path);
2596             goto oom;
2597           }
2598 
2599         _dbus_string_chop_white (&path);
2600 
2601         /* check for an empty path */
2602         if (_dbus_string_get_length (&path) == 0)
2603           goto next;
2604 
2605         if (!_dbus_concat_dir_and_file (&path,
2606                                         &file_suffix))
2607           {
2608             _dbus_string_free (&path);
2609             goto oom;
2610           }
2611 
2612         if (!_dbus_string_copy_data(&path, &cpath))
2613           {
2614             _dbus_string_free (&path);
2615             goto oom;
2616           }
2617 
2618         if (!_dbus_list_append (dir_list, cpath))
2619           {
2620             _dbus_string_free (&path);
2621             dbus_free (cpath);
2622             goto oom;
2623           }
2624 
2625        next:
2626         _dbus_string_free (&path);
2627         start = i + 1;
2628     }
2629 
2630   if (start != len)
2631     {
2632       DBusString path;
2633 
2634       if (!_dbus_string_init (&path))
2635         goto oom;
2636 
2637       if (!_dbus_string_copy_len (dirs,
2638                                   start,
2639                                   len - start,
2640                                   &path,
2641                                   0))
2642         {
2643           _dbus_string_free (&path);
2644           goto oom;
2645         }
2646 
2647       if (!_dbus_concat_dir_and_file (&path,
2648                                       &file_suffix))
2649         {
2650           _dbus_string_free (&path);
2651           goto oom;
2652         }
2653 
2654       if (!_dbus_string_copy_data(&path, &cpath))
2655         {
2656           _dbus_string_free (&path);
2657           goto oom;
2658         }
2659 
2660       if (!_dbus_list_append (dir_list, cpath))
2661         {
2662           _dbus_string_free (&path);
2663           dbus_free (cpath);
2664           goto oom;
2665         }
2666 
2667       _dbus_string_free (&path);
2668     }
2669 
2670   return TRUE;
2671 
2672  oom:
2673   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
2674   _dbus_list_clear (dir_list);
2675   return FALSE;
2676 }
2677 
2678 /**
2679  * Returns the standard directories for a session bus to look for service
2680  * activation files
2681  *
2682  * On UNIX this should be the standard xdg freedesktop.org data directories:
2683  *
2684  * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share}
2685  * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
2686  *
2687  * and
2688  *
2689  * DBUS_DATADIR
2690  *
2691  * @param dirs the directory list we are returning
2692  * @returns #FALSE on OOM
2693  */
2694 
2695 dbus_bool_t
_dbus_get_standard_session_servicedirs(DBusList ** dirs)2696 _dbus_get_standard_session_servicedirs (DBusList **dirs)
2697 {
2698   const char *xdg_data_home;
2699   const char *xdg_data_dirs;
2700   DBusString servicedir_path;
2701 
2702   if (!_dbus_string_init (&servicedir_path))
2703     return FALSE;
2704 
2705   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
2706   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
2707 
2708   if (xdg_data_dirs != NULL)
2709     {
2710       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
2711         goto oom;
2712 
2713       if (!_dbus_string_append (&servicedir_path, ":"))
2714         goto oom;
2715     }
2716   else
2717     {
2718       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
2719         goto oom;
2720     }
2721 
2722   /*
2723    * add configured datadir to defaults
2724    * this may be the same as an xdg dir
2725    * however the config parser should take
2726    * care of duplicates
2727    */
2728   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
2729         goto oom;
2730 
2731   if (xdg_data_home != NULL)
2732     {
2733       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
2734         goto oom;
2735     }
2736   else
2737     {
2738       const DBusString *homedir;
2739       const DBusString local_share;
2740 
2741       if (!_dbus_homedir_from_current_process (&homedir))
2742         goto oom;
2743 
2744       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
2745         goto oom;
2746 
2747       _dbus_string_init_const (&local_share, "/.local/share");
2748       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
2749         goto oom;
2750     }
2751 
2752   if (!split_paths_and_append (&servicedir_path,
2753                                DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
2754                                dirs))
2755     goto oom;
2756 
2757   _dbus_string_free (&servicedir_path);
2758   return TRUE;
2759 
2760  oom:
2761   _dbus_string_free (&servicedir_path);
2762   return FALSE;
2763 }
2764 
2765 /* tests in dbus-sysdeps-util.c */
2766