1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #include <config.h>
26
27 #include "dbus-internals.h"
28 #include "dbus-sysdeps.h"
29 #include "dbus-sysdeps-unix.h"
30 #include "dbus-threads.h"
31 #include "dbus-protocol.h"
32 #include "dbus-transport.h"
33 #include "dbus-string.h"
34 #include "dbus-userdb.h"
35 #include "dbus-list.h"
36 #include "dbus-credentials.h"
37 #include "dbus-nonce.h"
38
39 #include <sys/types.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <signal.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <fcntl.h>
46 #include <sys/socket.h>
47 #include <dirent.h>
48 #include <sys/un.h>
49 #include <pwd.h>
50 #include <time.h>
51 #include <locale.h>
52 #include <sys/time.h>
53 #include <sys/stat.h>
54 #include <sys/wait.h>
55 #include <netinet/in.h>
56 #include <netdb.h>
57 #include <grp.h>
58 #include <cutils/sockets.h>
59
60 #ifdef HAVE_ERRNO_H
61 #include <errno.h>
62 #endif
63 #ifdef HAVE_WRITEV
64 #include <sys/uio.h>
65 #endif
66 #ifdef HAVE_POLL
67 #include <sys/poll.h>
68 #endif
69 #ifdef HAVE_BACKTRACE
70 #include <execinfo.h>
71 #endif
72 #ifdef HAVE_GETPEERUCRED
73 #include <ucred.h>
74 #endif
75
76 #ifdef HAVE_ADT
77 #include <bsm/adt.h>
78 #endif
79
80 #include "sd-daemon.h"
81
82 #ifndef O_BINARY
83 #define O_BINARY 0
84 #endif
85
86 #ifndef AI_ADDRCONFIG
87 #define AI_ADDRCONFIG 0
88 #endif
89
90 #ifndef HAVE_SOCKLEN_T
91 #define socklen_t int
92 #endif
93
94 #if defined (__sun) || defined (__sun__)
95 /*
96 * CMS_SPACE etc. definitions for Solaris < 10, based on
97 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
98 * via
99 * http://wiki.opencsw.org/porting-faq#toc10
100 *
101 * These are only redefined for Solaris, for now: if your OS needs these too,
102 * please file a bug. (Or preferably, improve your OS so they're not needed.)
103 */
104
105 # ifndef CMSG_ALIGN
106 # ifdef __sun__
107 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
108 # else
109 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
110 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
111 ~(sizeof (long) - 1))
112 # endif
113 # endif
114
115 # ifndef CMSG_SPACE
116 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
117 CMSG_ALIGN (len))
118 # endif
119
120 # ifndef CMSG_LEN
121 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
122 # endif
123
124 #endif /* Solaris */
125
126 static dbus_bool_t
_dbus_open_socket(int * fd_p,int domain,int type,int protocol,DBusError * error)127 _dbus_open_socket (int *fd_p,
128 int domain,
129 int type,
130 int protocol,
131 DBusError *error)
132 {
133 #ifdef SOCK_CLOEXEC
134 dbus_bool_t cloexec_done;
135
136 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
137 cloexec_done = *fd_p >= 0;
138
139 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
140 if (*fd_p < 0 && errno == EINVAL)
141 #endif
142 {
143 *fd_p = socket (domain, type, protocol);
144 }
145
146 if (*fd_p >= 0)
147 {
148 #ifdef SOCK_CLOEXEC
149 if (!cloexec_done)
150 #endif
151 {
152 _dbus_fd_set_close_on_exec(*fd_p);
153 }
154
155 _dbus_verbose ("socket fd %d opened\n", *fd_p);
156 return TRUE;
157 }
158 else
159 {
160 dbus_set_error(error,
161 _dbus_error_from_errno (errno),
162 "Failed to open socket: %s",
163 _dbus_strerror (errno));
164 return FALSE;
165 }
166 }
167
168 /**
169 * Opens a UNIX domain socket (as in the socket() call).
170 * Does not bind the socket.
171 *
172 * This will set FD_CLOEXEC for the socket returned
173 *
174 * @param fd return location for socket descriptor
175 * @param error return location for an error
176 * @returns #FALSE if error is set
177 */
178 static dbus_bool_t
_dbus_open_unix_socket(int * fd,DBusError * error)179 _dbus_open_unix_socket (int *fd,
180 DBusError *error)
181 {
182 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
183 }
184
185 /**
186 * Closes a socket. Should not be used on non-socket
187 * file descriptors or handles.
188 *
189 * @param fd the socket
190 * @param error return location for an error
191 * @returns #FALSE if error is set
192 */
193 dbus_bool_t
_dbus_close_socket(int fd,DBusError * error)194 _dbus_close_socket (int fd,
195 DBusError *error)
196 {
197 return _dbus_close (fd, error);
198 }
199
200 /**
201 * Like _dbus_read(), but only works on sockets so is
202 * available on Windows.
203 *
204 * @param fd the socket
205 * @param buffer string to append data to
206 * @param count max amount of data to read
207 * @returns number of bytes appended to the string
208 */
209 int
_dbus_read_socket(int fd,DBusString * buffer,int count)210 _dbus_read_socket (int fd,
211 DBusString *buffer,
212 int count)
213 {
214 return _dbus_read (fd, buffer, count);
215 }
216
217 /**
218 * Like _dbus_write(), but only supports sockets
219 * and is thus available on Windows.
220 *
221 * @param fd the file descriptor to write
222 * @param buffer the buffer to write data from
223 * @param start the first byte in the buffer to write
224 * @param len the number of bytes to try to write
225 * @returns the number of bytes written or -1 on error
226 */
227 int
_dbus_write_socket(int fd,const DBusString * buffer,int start,int len)228 _dbus_write_socket (int fd,
229 const DBusString *buffer,
230 int start,
231 int len)
232 {
233 #if HAVE_DECL_MSG_NOSIGNAL
234 const char *data;
235 int bytes_written;
236
237 data = _dbus_string_get_const_data_len (buffer, start, len);
238
239 again:
240
241 bytes_written = send (fd, data, len, MSG_NOSIGNAL);
242
243 if (bytes_written < 0 && errno == EINTR)
244 goto again;
245
246 return bytes_written;
247
248 #else
249 return _dbus_write (fd, buffer, start, len);
250 #endif
251 }
252
253 /**
254 * Like _dbus_read_socket() but also tries to read unix fds from the
255 * socket. When there are more fds to read than space in the array
256 * passed this function will fail with ENOSPC.
257 *
258 * @param fd the socket
259 * @param buffer string to append data to
260 * @param count max amount of data to read
261 * @param fds array to place read file descriptors in
262 * @param n_fds on input space in fds array, on output how many fds actually got read
263 * @returns number of bytes appended to string
264 */
265 int
_dbus_read_socket_with_unix_fds(int fd,DBusString * buffer,int count,int * fds,int * n_fds)266 _dbus_read_socket_with_unix_fds (int fd,
267 DBusString *buffer,
268 int count,
269 int *fds,
270 int *n_fds) {
271 #ifndef HAVE_UNIX_FD_PASSING
272 int r;
273
274 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
275 return r;
276
277 *n_fds = 0;
278 return r;
279
280 #else
281 int bytes_read;
282 int start;
283 struct msghdr m;
284 struct iovec iov;
285
286 _dbus_assert (count >= 0);
287 _dbus_assert (*n_fds >= 0);
288
289 start = _dbus_string_get_length (buffer);
290
291 if (!_dbus_string_lengthen (buffer, count))
292 {
293 errno = ENOMEM;
294 return -1;
295 }
296
297 _DBUS_ZERO(iov);
298 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
299 iov.iov_len = count;
300
301 _DBUS_ZERO(m);
302 m.msg_iov = &iov;
303 m.msg_iovlen = 1;
304
305 /* Hmm, we have no clue how long the control data will actually be
306 that is queued for us. The least we can do is assume that the
307 caller knows. Hence let's make space for the number of fds that
308 we shall read at max plus the cmsg header. */
309 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
310
311 /* It's probably safe to assume that systems with SCM_RIGHTS also
312 know alloca() */
313 m.msg_control = alloca(m.msg_controllen);
314 memset(m.msg_control, 0, m.msg_controllen);
315
316 again:
317
318 bytes_read = recvmsg(fd, &m, 0
319 #ifdef MSG_CMSG_CLOEXEC
320 |MSG_CMSG_CLOEXEC
321 #endif
322 );
323
324 if (bytes_read < 0)
325 {
326 if (errno == EINTR)
327 goto again;
328 else
329 {
330 /* put length back (note that this doesn't actually realloc anything) */
331 _dbus_string_set_length (buffer, start);
332 return -1;
333 }
334 }
335 else
336 {
337 struct cmsghdr *cm;
338 dbus_bool_t found = FALSE;
339
340 if (m.msg_flags & MSG_CTRUNC)
341 {
342 /* Hmm, apparently the control data was truncated. The bad
343 thing is that we might have completely lost a couple of fds
344 without chance to recover them. Hence let's treat this as a
345 serious error. */
346
347 errno = ENOSPC;
348 _dbus_string_set_length (buffer, start);
349 return -1;
350 }
351
352 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
353 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
354 {
355 unsigned i;
356
357 _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
358 *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
359
360 memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
361 found = TRUE;
362
363 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
364 worked, hence we need to go through this list and set
365 CLOEXEC everywhere in any case */
366 for (i = 0; i < *n_fds; i++)
367 _dbus_fd_set_close_on_exec(fds[i]);
368
369 break;
370 }
371
372 if (!found)
373 *n_fds = 0;
374
375 /* put length back (doesn't actually realloc) */
376 _dbus_string_set_length (buffer, start + bytes_read);
377
378 #if 0
379 if (bytes_read > 0)
380 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
381 #endif
382
383 return bytes_read;
384 }
385 #endif
386 }
387
388 int
_dbus_write_socket_with_unix_fds(int fd,const DBusString * buffer,int start,int len,const int * fds,int n_fds)389 _dbus_write_socket_with_unix_fds(int fd,
390 const DBusString *buffer,
391 int start,
392 int len,
393 const int *fds,
394 int n_fds) {
395
396 #ifndef HAVE_UNIX_FD_PASSING
397
398 if (n_fds > 0) {
399 errno = ENOTSUP;
400 return -1;
401 }
402
403 return _dbus_write_socket(fd, buffer, start, len);
404 #else
405 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
406 #endif
407 }
408
409 int
_dbus_write_socket_with_unix_fds_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2,const int * fds,int n_fds)410 _dbus_write_socket_with_unix_fds_two(int fd,
411 const DBusString *buffer1,
412 int start1,
413 int len1,
414 const DBusString *buffer2,
415 int start2,
416 int len2,
417 const int *fds,
418 int n_fds) {
419
420 #ifndef HAVE_UNIX_FD_PASSING
421
422 if (n_fds > 0) {
423 errno = ENOTSUP;
424 return -1;
425 }
426
427 return _dbus_write_socket_two(fd,
428 buffer1, start1, len1,
429 buffer2, start2, len2);
430 #else
431
432 struct msghdr m;
433 struct cmsghdr *cm;
434 struct iovec iov[2];
435 int bytes_written;
436
437 _dbus_assert (len1 >= 0);
438 _dbus_assert (len2 >= 0);
439 _dbus_assert (n_fds >= 0);
440
441 _DBUS_ZERO(iov);
442 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
443 iov[0].iov_len = len1;
444
445 if (buffer2)
446 {
447 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
448 iov[1].iov_len = len2;
449 }
450
451 _DBUS_ZERO(m);
452 m.msg_iov = iov;
453 m.msg_iovlen = buffer2 ? 2 : 1;
454
455 if (n_fds > 0)
456 {
457 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
458 m.msg_control = alloca(m.msg_controllen);
459 memset(m.msg_control, 0, m.msg_controllen);
460
461 cm = CMSG_FIRSTHDR(&m);
462 cm->cmsg_level = SOL_SOCKET;
463 cm->cmsg_type = SCM_RIGHTS;
464 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
465 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
466 }
467
468 again:
469
470 bytes_written = sendmsg (fd, &m, 0
471 #if HAVE_DECL_MSG_NOSIGNAL
472 |MSG_NOSIGNAL
473 #endif
474 );
475
476 if (bytes_written < 0 && errno == EINTR)
477 goto again;
478
479 #if 0
480 if (bytes_written > 0)
481 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
482 #endif
483
484 return bytes_written;
485 #endif
486 }
487
488 /**
489 * Like _dbus_write_two() but only works on sockets and is thus
490 * available on Windows.
491 *
492 * @param fd the file descriptor
493 * @param buffer1 first buffer
494 * @param start1 first byte to write in first buffer
495 * @param len1 number of bytes to write from first buffer
496 * @param buffer2 second buffer, or #NULL
497 * @param start2 first byte to write in second buffer
498 * @param len2 number of bytes to write in second buffer
499 * @returns total bytes written from both buffers, or -1 on error
500 */
501 int
_dbus_write_socket_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2)502 _dbus_write_socket_two (int fd,
503 const DBusString *buffer1,
504 int start1,
505 int len1,
506 const DBusString *buffer2,
507 int start2,
508 int len2)
509 {
510 #if HAVE_DECL_MSG_NOSIGNAL
511 struct iovec vectors[2];
512 const char *data1;
513 const char *data2;
514 int bytes_written;
515 struct msghdr m;
516
517 _dbus_assert (buffer1 != NULL);
518 _dbus_assert (start1 >= 0);
519 _dbus_assert (start2 >= 0);
520 _dbus_assert (len1 >= 0);
521 _dbus_assert (len2 >= 0);
522
523 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
524
525 if (buffer2 != NULL)
526 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
527 else
528 {
529 data2 = NULL;
530 start2 = 0;
531 len2 = 0;
532 }
533
534 vectors[0].iov_base = (char*) data1;
535 vectors[0].iov_len = len1;
536 vectors[1].iov_base = (char*) data2;
537 vectors[1].iov_len = len2;
538
539 _DBUS_ZERO(m);
540 m.msg_iov = vectors;
541 m.msg_iovlen = data2 ? 2 : 1;
542
543 again:
544
545 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
546
547 if (bytes_written < 0 && errno == EINTR)
548 goto again;
549
550 return bytes_written;
551
552 #else
553 return _dbus_write_two (fd, buffer1, start1, len1,
554 buffer2, start2, len2);
555 #endif
556 }
557
558 dbus_bool_t
_dbus_socket_is_invalid(int fd)559 _dbus_socket_is_invalid (int fd)
560 {
561 return fd < 0 ? TRUE : FALSE;
562 }
563
564 /**
565 * Thin wrapper around the read() system call that appends
566 * the data it reads to the DBusString buffer. It appends
567 * up to the given count, and returns the same value
568 * and same errno as read(). The only exception is that
569 * _dbus_read() handles EINTR for you. Also, _dbus_read() can
570 * return ENOMEM, even though regular UNIX read doesn't.
571 *
572 * Unlike _dbus_read_socket(), _dbus_read() is not available
573 * on Windows.
574 *
575 * @param fd the file descriptor to read from
576 * @param buffer the buffer to append data to
577 * @param count the amount of data to read
578 * @returns the number of bytes read or -1
579 */
580 int
_dbus_read(int fd,DBusString * buffer,int count)581 _dbus_read (int fd,
582 DBusString *buffer,
583 int count)
584 {
585 int bytes_read;
586 int start;
587 char *data;
588
589 _dbus_assert (count >= 0);
590
591 start = _dbus_string_get_length (buffer);
592
593 if (!_dbus_string_lengthen (buffer, count))
594 {
595 errno = ENOMEM;
596 return -1;
597 }
598
599 data = _dbus_string_get_data_len (buffer, start, count);
600
601 again:
602
603 bytes_read = read (fd, data, count);
604
605 if (bytes_read < 0)
606 {
607 if (errno == EINTR)
608 goto again;
609 else
610 {
611 /* put length back (note that this doesn't actually realloc anything) */
612 _dbus_string_set_length (buffer, start);
613 return -1;
614 }
615 }
616 else
617 {
618 /* put length back (doesn't actually realloc) */
619 _dbus_string_set_length (buffer, start + bytes_read);
620
621 #if 0
622 if (bytes_read > 0)
623 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
624 #endif
625
626 return bytes_read;
627 }
628 }
629
630 /**
631 * Thin wrapper around the write() system call that writes a part of a
632 * DBusString and handles EINTR for you.
633 *
634 * @param fd the file descriptor to write
635 * @param buffer the buffer to write data from
636 * @param start the first byte in the buffer to write
637 * @param len the number of bytes to try to write
638 * @returns the number of bytes written or -1 on error
639 */
640 int
_dbus_write(int fd,const DBusString * buffer,int start,int len)641 _dbus_write (int fd,
642 const DBusString *buffer,
643 int start,
644 int len)
645 {
646 const char *data;
647 int bytes_written;
648
649 data = _dbus_string_get_const_data_len (buffer, start, len);
650
651 again:
652
653 bytes_written = write (fd, data, len);
654
655 if (bytes_written < 0 && errno == EINTR)
656 goto again;
657
658 #if 0
659 if (bytes_written > 0)
660 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
661 #endif
662
663 return bytes_written;
664 }
665
666 /**
667 * Like _dbus_write() but will use writev() if possible
668 * to write both buffers in sequence. The return value
669 * is the number of bytes written in the first buffer,
670 * plus the number written in the second. If the first
671 * buffer is written successfully and an error occurs
672 * writing the second, the number of bytes in the first
673 * is returned (i.e. the error is ignored), on systems that
674 * don't have writev. Handles EINTR for you.
675 * The second buffer may be #NULL.
676 *
677 * @param fd the file descriptor
678 * @param buffer1 first buffer
679 * @param start1 first byte to write in first buffer
680 * @param len1 number of bytes to write from first buffer
681 * @param buffer2 second buffer, or #NULL
682 * @param start2 first byte to write in second buffer
683 * @param len2 number of bytes to write in second buffer
684 * @returns total bytes written from both buffers, or -1 on error
685 */
686 int
_dbus_write_two(int fd,const DBusString * buffer1,int start1,int len1,const DBusString * buffer2,int start2,int len2)687 _dbus_write_two (int fd,
688 const DBusString *buffer1,
689 int start1,
690 int len1,
691 const DBusString *buffer2,
692 int start2,
693 int len2)
694 {
695 _dbus_assert (buffer1 != NULL);
696 _dbus_assert (start1 >= 0);
697 _dbus_assert (start2 >= 0);
698 _dbus_assert (len1 >= 0);
699 _dbus_assert (len2 >= 0);
700
701 #ifdef HAVE_WRITEV
702 {
703 struct iovec vectors[2];
704 const char *data1;
705 const char *data2;
706 int bytes_written;
707
708 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
709
710 if (buffer2 != NULL)
711 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
712 else
713 {
714 data2 = NULL;
715 start2 = 0;
716 len2 = 0;
717 }
718
719 vectors[0].iov_base = (char*) data1;
720 vectors[0].iov_len = len1;
721 vectors[1].iov_base = (char*) data2;
722 vectors[1].iov_len = len2;
723
724 again:
725
726 bytes_written = writev (fd,
727 vectors,
728 data2 ? 2 : 1);
729
730 if (bytes_written < 0 && errno == EINTR)
731 goto again;
732
733 return bytes_written;
734 }
735 #else /* HAVE_WRITEV */
736 {
737 int ret1;
738
739 ret1 = _dbus_write (fd, buffer1, start1, len1);
740 if (ret1 == len1 && buffer2 != NULL)
741 {
742 ret2 = _dbus_write (fd, buffer2, start2, len2);
743 if (ret2 < 0)
744 ret2 = 0; /* we can't report an error as the first write was OK */
745
746 return ret1 + ret2;
747 }
748 else
749 return ret1;
750 }
751 #endif /* !HAVE_WRITEV */
752 }
753
754 #define _DBUS_MAX_SUN_PATH_LENGTH 99
755
756 /**
757 * @def _DBUS_MAX_SUN_PATH_LENGTH
758 *
759 * Maximum length of the path to a UNIX domain socket,
760 * sockaddr_un::sun_path member. POSIX requires that all systems
761 * support at least 100 bytes here, including the nul termination.
762 * We use 99 for the max value to allow for the nul.
763 *
764 * We could probably also do sizeof (addr.sun_path)
765 * but this way we are the same on all platforms
766 * which is probably a good idea.
767 */
768
769 /**
770 * Creates a socket and connects it to the UNIX domain socket at the
771 * given path. The connection fd is returned, and is set up as
772 * nonblocking.
773 *
774 * Uses abstract sockets instead of filesystem-linked sockets if
775 * requested (it's possible only on Linux; see "man 7 unix" on Linux).
776 * On non-Linux abstract socket usage always fails.
777 *
778 * This will set FD_CLOEXEC for the socket returned.
779 *
780 * @param path the path to UNIX domain socket
781 * @param abstract #TRUE to use abstract namespace
782 * @param error return location for error code
783 * @returns connection file descriptor or -1 on error
784 */
785 int
_dbus_connect_unix_socket(const char * path,dbus_bool_t abstract,DBusError * error)786 _dbus_connect_unix_socket (const char *path,
787 dbus_bool_t abstract,
788 DBusError *error)
789 {
790 int fd;
791 size_t path_len;
792 struct sockaddr_un addr;
793
794 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
795
796 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
797 path, abstract);
798
799
800 if (!_dbus_open_unix_socket (&fd, error))
801 {
802 _DBUS_ASSERT_ERROR_IS_SET(error);
803 return -1;
804 }
805 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
806
807 _DBUS_ZERO (addr);
808 addr.sun_family = AF_UNIX;
809 path_len = strlen (path);
810
811 if (abstract)
812 {
813 #ifdef HAVE_ABSTRACT_SOCKETS
814 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
815 path_len++; /* Account for the extra nul byte added to the start of sun_path */
816
817 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
818 {
819 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
820 "Abstract socket name too long\n");
821 _dbus_close (fd, NULL);
822 return -1;
823 }
824
825 strncpy (&addr.sun_path[1], path, path_len);
826 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
827 #else /* HAVE_ABSTRACT_SOCKETS */
828 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
829 "Operating system does not support abstract socket namespace\n");
830 _dbus_close (fd, NULL);
831 return -1;
832 #endif /* ! HAVE_ABSTRACT_SOCKETS */
833 }
834 else
835 {
836 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
837 {
838 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
839 "Socket name too long\n");
840 _dbus_close (fd, NULL);
841 return -1;
842 }
843
844 strncpy (addr.sun_path, path, path_len);
845 }
846
847 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
848 {
849 dbus_set_error (error,
850 _dbus_error_from_errno (errno),
851 "Failed to connect to socket %s: %s",
852 path, _dbus_strerror (errno));
853
854 _dbus_close (fd, NULL);
855 return -1;
856 }
857
858 if (!_dbus_set_fd_nonblocking (fd, error))
859 {
860 _DBUS_ASSERT_ERROR_IS_SET (error);
861
862 _dbus_close (fd, NULL);
863 return -1;
864 }
865
866 return fd;
867 }
868
869 /**
870 * Creates a UNIX domain socket and connects it to the specified
871 * process to execute.
872 *
873 * This will set FD_CLOEXEC for the socket returned.
874 *
875 * @param path the path to the executable
876 * @param argv the argument list for the process to execute.
877 * argv[0] typically is identical to the path of the executable
878 * @param error return location for error code
879 * @returns connection file descriptor or -1 on error
880 */
881 int
_dbus_connect_exec(const char * path,char * const argv[],DBusError * error)882 _dbus_connect_exec (const char *path,
883 char *const argv[],
884 DBusError *error)
885 {
886 int fds[2];
887 pid_t pid;
888
889 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
890
891 _dbus_verbose ("connecting to process %s\n", path);
892
893 if (socketpair (AF_UNIX, SOCK_STREAM
894 #ifdef SOCK_CLOEXEC
895 |SOCK_CLOEXEC
896 #endif
897 , 0, fds) < 0)
898 {
899 dbus_set_error (error,
900 _dbus_error_from_errno (errno),
901 "Failed to create socket pair: %s",
902 _dbus_strerror (errno));
903 return -1;
904 }
905
906 _dbus_fd_set_close_on_exec (fds[0]);
907 _dbus_fd_set_close_on_exec (fds[1]);
908
909 pid = fork ();
910 if (pid < 0)
911 {
912 dbus_set_error (error,
913 _dbus_error_from_errno (errno),
914 "Failed to fork() to call %s: %s",
915 path, _dbus_strerror (errno));
916 close (fds[0]);
917 close (fds[1]);
918 return -1;
919 }
920
921 if (pid == 0)
922 {
923 /* child */
924 close (fds[0]);
925
926 dup2 (fds[1], STDIN_FILENO);
927 dup2 (fds[1], STDOUT_FILENO);
928
929 if (fds[1] != STDIN_FILENO &&
930 fds[1] != STDOUT_FILENO)
931 close (fds[1]);
932
933 /* Inherit STDERR and the controlling terminal from the
934 parent */
935
936 _dbus_close_all ();
937
938 execvp (path, argv);
939
940 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
941
942 _exit(1);
943 }
944
945 /* parent */
946 close (fds[1]);
947
948 if (!_dbus_set_fd_nonblocking (fds[0], error))
949 {
950 _DBUS_ASSERT_ERROR_IS_SET (error);
951
952 close (fds[0]);
953 return -1;
954 }
955
956 return fds[0];
957 }
958
959 /**
960 * Enables or disables the reception of credentials on the given socket during
961 * the next message transmission. This is only effective if the #LOCAL_CREDS
962 * system feature exists, in which case the other side of the connection does
963 * not have to do anything special to send the credentials.
964 *
965 * @param fd socket on which to change the #LOCAL_CREDS flag.
966 * @param on whether to enable or disable the #LOCAL_CREDS flag.
967 */
968 static dbus_bool_t
_dbus_set_local_creds(int fd,dbus_bool_t on)969 _dbus_set_local_creds (int fd, dbus_bool_t on)
970 {
971 dbus_bool_t retval = TRUE;
972
973 #if defined(HAVE_CMSGCRED)
974 /* NOOP just to make sure only one codepath is used
975 * and to prefer CMSGCRED
976 */
977 #elif defined(LOCAL_CREDS)
978 int val = on ? 1 : 0;
979 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
980 {
981 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
982 retval = FALSE;
983 }
984 else
985 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
986 on ? "enabled" : "disabled", fd);
987 #endif
988
989 return retval;
990 }
991
992 /**
993 * Creates a socket and binds it to the given path,
994 * then listens on the socket. The socket is
995 * set to be nonblocking.
996 *
997 * Uses abstract sockets instead of filesystem-linked
998 * sockets if requested (it's possible only on Linux;
999 * see "man 7 unix" on Linux).
1000 * On non-Linux abstract socket usage always fails.
1001 *
1002 * This will set FD_CLOEXEC for the socket returned
1003 *
1004 * @param path the socket name
1005 * @param abstract #TRUE to use abstract namespace
1006 * @param error return location for errors
1007 * @returns the listening file descriptor or -1 on error
1008 */
1009 int
_dbus_listen_unix_socket(const char * path,dbus_bool_t abstract,DBusError * error)1010 _dbus_listen_unix_socket (const char *path,
1011 dbus_bool_t abstract,
1012 DBusError *error)
1013 {
1014 int listen_fd;
1015 struct sockaddr_un addr;
1016 size_t path_len;
1017 unsigned int reuseaddr;
1018
1019 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1020
1021 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1022 path, abstract);
1023 #ifdef ANDROID_MANAGED_SOCKET
1024 if (strncmp (path, ANDROID_SOCKET_DIR"/", strlen(ANDROID_SOCKET_DIR"/")) == 0)
1025 {
1026 const char* suffix;
1027 /* init has created a socket for us, pick it up from environ */
1028 suffix = &path[strlen (ANDROID_SOCKET_DIR"/")];
1029 listen_fd = android_get_control_socket (suffix);
1030 if (listen_fd == -1)
1031 {
1032 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1033 "Could not obtain fd for android socket %s\n", suffix);
1034 return -1;
1035 }
1036
1037 _dbus_verbose ("Obtained fd for android socket %s\n", suffix);
1038 }
1039 else
1040 {
1041 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1042 "Not an android socket: %s\n", path);
1043 return -1;
1044 }
1045 #else
1046
1047 if (!_dbus_open_unix_socket (&listen_fd, error))
1048 {
1049 _DBUS_ASSERT_ERROR_IS_SET(error);
1050 return -1;
1051 }
1052 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1053
1054 _DBUS_ZERO (addr);
1055 addr.sun_family = AF_UNIX;
1056 path_len = strlen (path);
1057
1058 if (abstract)
1059 {
1060 #ifdef HAVE_ABSTRACT_SOCKETS
1061 /* remember that abstract names aren't nul-terminated so we rely
1062 * on sun_path being filled in with zeroes above.
1063 */
1064 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1065 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1066
1067 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1068 {
1069 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1070 "Abstract socket name too long\n");
1071 _dbus_close (listen_fd, NULL);
1072 return -1;
1073 }
1074
1075 strncpy (&addr.sun_path[1], path, path_len);
1076 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1077 #else /* HAVE_ABSTRACT_SOCKETS */
1078 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
1079 "Operating system does not support abstract socket namespace\n");
1080 _dbus_close (listen_fd, NULL);
1081 return -1;
1082 #endif /* ! HAVE_ABSTRACT_SOCKETS */
1083 }
1084 else
1085 {
1086 /* Discussed security implications of this with Nalin,
1087 * and we couldn't think of where it would kick our ass, but
1088 * it still seems a bit sucky. It also has non-security suckage;
1089 * really we'd prefer to exit if the socket is already in use.
1090 * But there doesn't seem to be a good way to do this.
1091 *
1092 * Just to be extra careful, I threw in the stat() - clearly
1093 * the stat() can't *fix* any security issue, but it at least
1094 * avoids inadvertent/accidental data loss.
1095 */
1096 {
1097 struct stat sb;
1098
1099 if (stat (path, &sb) == 0 &&
1100 S_ISSOCK (sb.st_mode))
1101 unlink (path);
1102 }
1103
1104 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1105 {
1106 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1107 "Abstract socket name too long\n");
1108 _dbus_close (listen_fd, NULL);
1109 return -1;
1110 }
1111
1112 strncpy (addr.sun_path, path, path_len);
1113 }
1114
1115 reuseaddr = 1;
1116 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1117 {
1118 _dbus_warn ("Failed to set socket option\"%s\": %s",
1119 path, _dbus_strerror (errno));
1120 }
1121
1122 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1123 {
1124 dbus_set_error (error, _dbus_error_from_errno (errno),
1125 "Failed to bind socket \"%s\": %s",
1126 path, _dbus_strerror (errno));
1127 _dbus_close (listen_fd, NULL);
1128 return -1;
1129 }
1130
1131 #endif /* android init managed sockets */
1132
1133 if (listen (listen_fd, 30 /* backlog */) < 0)
1134 {
1135 dbus_set_error (error, _dbus_error_from_errno (errno),
1136 "Failed to listen on socket \"%s\": %s",
1137 path, _dbus_strerror (errno));
1138 _dbus_close (listen_fd, NULL);
1139 return -1;
1140 }
1141
1142 if (!_dbus_set_local_creds (listen_fd, TRUE))
1143 {
1144 dbus_set_error (error, _dbus_error_from_errno (errno),
1145 "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
1146 path, _dbus_strerror (errno));
1147 close (listen_fd);
1148 return -1;
1149 }
1150
1151 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1152 {
1153 _DBUS_ASSERT_ERROR_IS_SET (error);
1154 _dbus_close (listen_fd, NULL);
1155 return -1;
1156 }
1157
1158 #ifndef ANDROID_MANAGED_SOCKET
1159 /* Try opening up the permissions, but if we can't, just go ahead
1160 * and continue, maybe it will be good enough.
1161 */
1162 if (!abstract && chmod (path, 0777) < 0)
1163 _dbus_warn ("Could not set mode 0777 on socket %s\n",
1164 path);
1165 #endif
1166
1167 return listen_fd;
1168 }
1169
1170 /**
1171 * Acquires one or more sockets passed in from systemd. The sockets
1172 * are set to be nonblocking.
1173 *
1174 * This will set FD_CLOEXEC for the sockets returned.
1175 *
1176 * @oaram fds the file descriptors
1177 * @param error return location for errors
1178 * @returns the number of file descriptors
1179 */
1180 int
_dbus_listen_systemd_sockets(int ** fds,DBusError * error)1181 _dbus_listen_systemd_sockets (int **fds,
1182 DBusError *error)
1183 {
1184 int r, n;
1185 unsigned fd;
1186 int *new_fds;
1187
1188 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1189
1190 n = sd_listen_fds (TRUE);
1191 if (n < 0)
1192 {
1193 dbus_set_error (error, _dbus_error_from_errno (-n),
1194 "Failed to acquire systemd socket: %s",
1195 _dbus_strerror (-n));
1196 return -1;
1197 }
1198
1199 if (n <= 0)
1200 {
1201 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1202 "No socket received.");
1203 return -1;
1204 }
1205
1206 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1207 {
1208 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1209 if (r < 0)
1210 {
1211 dbus_set_error (error, _dbus_error_from_errno (-r),
1212 "Failed to verify systemd socket type: %s",
1213 _dbus_strerror (-r));
1214 return -1;
1215 }
1216
1217 if (!r)
1218 {
1219 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
1220 "Passed socket has wrong type.");
1221 return -1;
1222 }
1223 }
1224
1225 /* OK, the file descriptors are all good, so let's take posession of
1226 them then. */
1227
1228 new_fds = dbus_new (int, n);
1229 if (!new_fds)
1230 {
1231 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1232 "Failed to allocate file handle array.");
1233 goto fail;
1234 }
1235
1236 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1237 {
1238 if (!_dbus_set_local_creds (fd, TRUE))
1239 {
1240 dbus_set_error (error, _dbus_error_from_errno (errno),
1241 "Failed to enable LOCAL_CREDS on systemd socket: %s",
1242 _dbus_strerror (errno));
1243 goto fail;
1244 }
1245
1246 if (!_dbus_set_fd_nonblocking (fd, error))
1247 {
1248 _DBUS_ASSERT_ERROR_IS_SET (error);
1249 goto fail;
1250 }
1251
1252 new_fds[fd - SD_LISTEN_FDS_START] = fd;
1253 }
1254
1255 *fds = new_fds;
1256 return n;
1257
1258 fail:
1259
1260 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1261 {
1262 _dbus_close (fd, NULL);
1263 }
1264
1265 dbus_free (new_fds);
1266 return -1;
1267 }
1268
1269 /**
1270 * Creates a socket and connects to a socket at the given host
1271 * and port. The connection fd is returned, and is set up as
1272 * nonblocking.
1273 *
1274 * This will set FD_CLOEXEC for the socket returned
1275 *
1276 * @param host the host name to connect to
1277 * @param port the port to connect to
1278 * @param family the address family to listen on, NULL for all
1279 * @param error return location for error code
1280 * @returns connection file descriptor or -1 on error
1281 */
1282 int
_dbus_connect_tcp_socket(const char * host,const char * port,const char * family,DBusError * error)1283 _dbus_connect_tcp_socket (const char *host,
1284 const char *port,
1285 const char *family,
1286 DBusError *error)
1287 {
1288 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1289 }
1290
1291 int
_dbus_connect_tcp_socket_with_nonce(const char * host,const char * port,const char * family,const char * noncefile,DBusError * error)1292 _dbus_connect_tcp_socket_with_nonce (const char *host,
1293 const char *port,
1294 const char *family,
1295 const char *noncefile,
1296 DBusError *error)
1297 {
1298 int saved_errno = 0;
1299 int fd = -1, res;
1300 struct addrinfo hints;
1301 struct addrinfo *ai, *tmp;
1302
1303 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1304
1305 _DBUS_ZERO (hints);
1306
1307 if (!family)
1308 hints.ai_family = AF_UNSPEC;
1309 else if (!strcmp(family, "ipv4"))
1310 hints.ai_family = AF_INET;
1311 else if (!strcmp(family, "ipv6"))
1312 hints.ai_family = AF_INET6;
1313 else
1314 {
1315 dbus_set_error (error,
1316 DBUS_ERROR_BAD_ADDRESS,
1317 "Unknown address family %s", family);
1318 return -1;
1319 }
1320 hints.ai_protocol = IPPROTO_TCP;
1321 hints.ai_socktype = SOCK_STREAM;
1322 hints.ai_flags = AI_ADDRCONFIG;
1323
1324 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1325 {
1326 dbus_set_error (error,
1327 _dbus_error_from_errno (errno),
1328 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1329 host, port, gai_strerror(res), res);
1330 return -1;
1331 }
1332
1333 tmp = ai;
1334 while (tmp)
1335 {
1336 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1337 {
1338 freeaddrinfo(ai);
1339 _DBUS_ASSERT_ERROR_IS_SET(error);
1340 return -1;
1341 }
1342 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1343
1344 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1345 {
1346 saved_errno = errno;
1347 _dbus_close(fd, NULL);
1348 fd = -1;
1349 tmp = tmp->ai_next;
1350 continue;
1351 }
1352
1353 break;
1354 }
1355 freeaddrinfo(ai);
1356
1357 if (fd == -1)
1358 {
1359 dbus_set_error (error,
1360 _dbus_error_from_errno (saved_errno),
1361 "Failed to connect to socket \"%s:%s\" %s",
1362 host, port, _dbus_strerror(saved_errno));
1363 return -1;
1364 }
1365
1366 if (noncefile != NULL)
1367 {
1368 DBusString noncefileStr;
1369 dbus_bool_t ret;
1370 _dbus_string_init_const (&noncefileStr, noncefile);
1371 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1372 _dbus_string_free (&noncefileStr);
1373
1374 if (!ret)
1375 {
1376 _dbus_close (fd, NULL);
1377 return -1;
1378 }
1379 }
1380
1381 if (!_dbus_set_fd_nonblocking (fd, error))
1382 {
1383 _dbus_close (fd, NULL);
1384 return -1;
1385 }
1386
1387 return fd;
1388 }
1389
1390 /**
1391 * Creates a socket and binds it to the given path, then listens on
1392 * the socket. The socket is set to be nonblocking. In case of port=0
1393 * a random free port is used and returned in the port parameter.
1394 * If inaddr_any is specified, the hostname is ignored.
1395 *
1396 * This will set FD_CLOEXEC for the socket returned
1397 *
1398 * @param host the host name to listen on
1399 * @param port the port to listen on, if zero a free port will be used
1400 * @param family the address family to listen on, NULL for all
1401 * @param retport string to return the actual port listened on
1402 * @param fds_p location to store returned file descriptors
1403 * @param error return location for errors
1404 * @returns the number of listening file descriptors or -1 on error
1405 */
1406 int
_dbus_listen_tcp_socket(const char * host,const char * port,const char * family,DBusString * retport,int ** fds_p,DBusError * error)1407 _dbus_listen_tcp_socket (const char *host,
1408 const char *port,
1409 const char *family,
1410 DBusString *retport,
1411 int **fds_p,
1412 DBusError *error)
1413 {
1414 int saved_errno;
1415 int nlisten_fd = 0, *listen_fd = NULL, res, i;
1416 struct addrinfo hints;
1417 struct addrinfo *ai, *tmp;
1418 unsigned int reuseaddr;
1419
1420 *fds_p = NULL;
1421 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1422
1423 _DBUS_ZERO (hints);
1424
1425 if (!family)
1426 hints.ai_family = AF_UNSPEC;
1427 else if (!strcmp(family, "ipv4"))
1428 hints.ai_family = AF_INET;
1429 else if (!strcmp(family, "ipv6"))
1430 hints.ai_family = AF_INET6;
1431 else
1432 {
1433 dbus_set_error (error,
1434 DBUS_ERROR_BAD_ADDRESS,
1435 "Unknown address family %s", family);
1436 return -1;
1437 }
1438
1439 hints.ai_protocol = IPPROTO_TCP;
1440 hints.ai_socktype = SOCK_STREAM;
1441 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1442
1443 redo_lookup_with_port:
1444 ai = NULL;
1445 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1446 {
1447 dbus_set_error (error,
1448 _dbus_error_from_errno (errno),
1449 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1450 host ? host : "*", port, gai_strerror(res), res);
1451 goto failed;
1452 }
1453
1454 tmp = ai;
1455 while (tmp)
1456 {
1457 int fd = -1, *newlisten_fd;
1458 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1459 {
1460 _DBUS_ASSERT_ERROR_IS_SET(error);
1461 goto failed;
1462 }
1463 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1464
1465 reuseaddr = 1;
1466 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1467 {
1468 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1469 host ? host : "*", port, _dbus_strerror (errno));
1470 }
1471
1472 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1473 {
1474 saved_errno = errno;
1475 _dbus_close(fd, NULL);
1476 if (saved_errno == EADDRINUSE)
1477 {
1478 /* Depending on kernel policy, it may or may not
1479 be neccessary to bind to both IPv4 & 6 addresses
1480 so ignore EADDRINUSE here */
1481 tmp = tmp->ai_next;
1482 continue;
1483 }
1484 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1485 "Failed to bind socket \"%s:%s\": %s",
1486 host ? host : "*", port, _dbus_strerror (saved_errno));
1487 goto failed;
1488 }
1489
1490 if (listen (fd, 30 /* backlog */) < 0)
1491 {
1492 saved_errno = errno;
1493 _dbus_close (fd, NULL);
1494 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1495 "Failed to listen on socket \"%s:%s\": %s",
1496 host ? host : "*", port, _dbus_strerror (saved_errno));
1497 goto failed;
1498 }
1499
1500 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
1501 if (!newlisten_fd)
1502 {
1503 saved_errno = errno;
1504 _dbus_close (fd, NULL);
1505 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1506 "Failed to allocate file handle array: %s",
1507 _dbus_strerror (saved_errno));
1508 goto failed;
1509 }
1510 listen_fd = newlisten_fd;
1511 listen_fd[nlisten_fd] = fd;
1512 nlisten_fd++;
1513
1514 if (!_dbus_string_get_length(retport))
1515 {
1516 /* If the user didn't specify a port, or used 0, then
1517 the kernel chooses a port. After the first address
1518 is bound to, we need to force all remaining addresses
1519 to use the same port */
1520 if (!port || !strcmp(port, "0"))
1521 {
1522 int result;
1523 struct sockaddr_storage addr;
1524 socklen_t addrlen;
1525 char portbuf[50];
1526
1527 addrlen = sizeof(addr);
1528 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1529
1530 if (result == -1 ||
1531 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1532 portbuf, sizeof(portbuf),
1533 NI_NUMERICHOST)) != 0)
1534 {
1535 dbus_set_error (error, _dbus_error_from_errno (errno),
1536 "Failed to resolve port \"%s:%s\": %s (%s)",
1537 host ? host : "*", port, gai_strerror(res), res);
1538 goto failed;
1539 }
1540 if (!_dbus_string_append(retport, portbuf))
1541 {
1542 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1543 goto failed;
1544 }
1545
1546 /* Release current address list & redo lookup */
1547 port = _dbus_string_get_const_data(retport);
1548 freeaddrinfo(ai);
1549 goto redo_lookup_with_port;
1550 }
1551 else
1552 {
1553 if (!_dbus_string_append(retport, port))
1554 {
1555 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1556 goto failed;
1557 }
1558 }
1559 }
1560
1561 tmp = tmp->ai_next;
1562 }
1563 freeaddrinfo(ai);
1564 ai = NULL;
1565
1566 if (!nlisten_fd)
1567 {
1568 errno = EADDRINUSE;
1569 dbus_set_error (error, _dbus_error_from_errno (errno),
1570 "Failed to bind socket \"%s:%s\": %s",
1571 host ? host : "*", port, _dbus_strerror (errno));
1572 goto failed;
1573 }
1574
1575 for (i = 0 ; i < nlisten_fd ; i++)
1576 {
1577 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
1578 {
1579 goto failed;
1580 }
1581 }
1582
1583 *fds_p = listen_fd;
1584
1585 return nlisten_fd;
1586
1587 failed:
1588 if (ai)
1589 freeaddrinfo(ai);
1590 for (i = 0 ; i < nlisten_fd ; i++)
1591 _dbus_close(listen_fd[i], NULL);
1592 dbus_free(listen_fd);
1593 return -1;
1594 }
1595
1596 static dbus_bool_t
write_credentials_byte(int server_fd,DBusError * error)1597 write_credentials_byte (int server_fd,
1598 DBusError *error)
1599 {
1600 int bytes_written;
1601 char buf[1] = { '\0' };
1602 #if defined(HAVE_CMSGCRED)
1603 union {
1604 struct cmsghdr hdr;
1605 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1606 } cmsg;
1607 struct iovec iov;
1608 struct msghdr msg;
1609 iov.iov_base = buf;
1610 iov.iov_len = 1;
1611
1612 _DBUS_ZERO(msg);
1613 msg.msg_iov = &iov;
1614 msg.msg_iovlen = 1;
1615
1616 msg.msg_control = (caddr_t) &cmsg;
1617 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1618 _DBUS_ZERO(cmsg);
1619 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1620 cmsg.hdr.cmsg_level = SOL_SOCKET;
1621 cmsg.hdr.cmsg_type = SCM_CREDS;
1622 #endif
1623
1624 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1625
1626 again:
1627
1628 #if defined(HAVE_CMSGCRED)
1629 bytes_written = sendmsg (server_fd, &msg, 0
1630 #if HAVE_DECL_MSG_NOSIGNAL
1631 |MSG_NOSIGNAL
1632 #endif
1633 );
1634 #else
1635 bytes_written = send (server_fd, buf, 1, 0
1636 #if HAVE_DECL_MSG_NOSIGNAL
1637 |MSG_NOSIGNAL
1638 #endif
1639 );
1640 #endif
1641
1642 if (bytes_written < 0 && errno == EINTR)
1643 goto again;
1644
1645 if (bytes_written < 0)
1646 {
1647 dbus_set_error (error, _dbus_error_from_errno (errno),
1648 "Failed to write credentials byte: %s",
1649 _dbus_strerror (errno));
1650 return FALSE;
1651 }
1652 else if (bytes_written == 0)
1653 {
1654 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
1655 "wrote zero bytes writing credentials byte");
1656 return FALSE;
1657 }
1658 else
1659 {
1660 _dbus_assert (bytes_written == 1);
1661 _dbus_verbose ("wrote credentials byte\n");
1662 return TRUE;
1663 }
1664 }
1665
1666 /**
1667 * Reads a single byte which must be nul (an error occurs otherwise),
1668 * and reads unix credentials if available. Clears the credentials
1669 * object, then adds pid/uid if available, so any previous credentials
1670 * stored in the object are lost.
1671 *
1672 * Return value indicates whether a byte was read, not whether
1673 * we got valid credentials. On some systems, such as Linux,
1674 * reading/writing the byte isn't actually required, but we do it
1675 * anyway just to avoid multiple codepaths.
1676 *
1677 * Fails if no byte is available, so you must select() first.
1678 *
1679 * The point of the byte is that on some systems we have to
1680 * use sendmsg()/recvmsg() to transmit credentials.
1681 *
1682 * @param client_fd the client file descriptor
1683 * @param credentials object to add client credentials to
1684 * @param error location to store error code
1685 * @returns #TRUE on success
1686 */
1687 dbus_bool_t
_dbus_read_credentials_socket(int client_fd,DBusCredentials * credentials,DBusError * error)1688 _dbus_read_credentials_socket (int client_fd,
1689 DBusCredentials *credentials,
1690 DBusError *error)
1691 {
1692 struct msghdr msg;
1693 struct iovec iov;
1694 char buf;
1695 dbus_uid_t uid_read;
1696 dbus_pid_t pid_read;
1697 int bytes_read;
1698
1699 #ifdef HAVE_CMSGCRED
1700 union {
1701 struct cmsghdr hdr;
1702 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1703 } cmsg;
1704
1705 #elif defined(LOCAL_CREDS)
1706 struct {
1707 struct cmsghdr hdr;
1708 struct sockcred cred;
1709 } cmsg;
1710 #endif
1711
1712 uid_read = DBUS_UID_UNSET;
1713 pid_read = DBUS_PID_UNSET;
1714
1715 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1716
1717 /* The POSIX spec certainly doesn't promise this, but
1718 * we need these assertions to fail as soon as we're wrong about
1719 * it so we can do the porting fixups
1720 */
1721 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
1722 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
1723 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
1724
1725 _dbus_credentials_clear (credentials);
1726
1727 /* Systems supporting LOCAL_CREDS are configured to have this feature
1728 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
1729 * the connection. Therefore, the received message must carry the
1730 * credentials information without doing anything special.
1731 */
1732
1733 iov.iov_base = &buf;
1734 iov.iov_len = 1;
1735
1736 _DBUS_ZERO(msg);
1737 msg.msg_iov = &iov;
1738 msg.msg_iovlen = 1;
1739
1740 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
1741 _DBUS_ZERO(cmsg);
1742 msg.msg_control = (caddr_t) &cmsg;
1743 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1744 #endif
1745
1746 again:
1747 bytes_read = recvmsg (client_fd, &msg, 0);
1748
1749 if (bytes_read < 0)
1750 {
1751 if (errno == EINTR)
1752 goto again;
1753
1754 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1755 * normally only call read_credentials if the socket was ready
1756 * for reading
1757 */
1758
1759 dbus_set_error (error, _dbus_error_from_errno (errno),
1760 "Failed to read credentials byte: %s",
1761 _dbus_strerror (errno));
1762 return FALSE;
1763 }
1764 else if (bytes_read == 0)
1765 {
1766 /* this should not happen unless we are using recvmsg wrong,
1767 * so is essentially here for paranoia
1768 */
1769 dbus_set_error (error, DBUS_ERROR_FAILED,
1770 "Failed to read credentials byte (zero-length read)");
1771 return FALSE;
1772 }
1773 else if (buf != '\0')
1774 {
1775 dbus_set_error (error, DBUS_ERROR_FAILED,
1776 "Credentials byte was not nul");
1777 return FALSE;
1778 }
1779
1780 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
1781 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
1782 || cmsg.hdr.cmsg_type != SCM_CREDS)
1783 {
1784 dbus_set_error (error, DBUS_ERROR_FAILED,
1785 "Message from recvmsg() was not SCM_CREDS");
1786 return FALSE;
1787 }
1788 #endif
1789
1790 _dbus_verbose ("read credentials byte\n");
1791
1792 {
1793 #ifdef SO_PEERCRED
1794 #ifdef __OpenBSD__
1795 struct sockpeercred cr;
1796 #else
1797 struct ucred cr;
1798 #endif
1799 int cr_len = sizeof (cr);
1800
1801 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
1802 cr_len == sizeof (cr))
1803 {
1804 pid_read = cr.pid;
1805 uid_read = cr.uid;
1806 }
1807 else
1808 {
1809 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
1810 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
1811 }
1812 #elif defined(HAVE_CMSGCRED)
1813 struct cmsgcred *cred;
1814
1815 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
1816 pid_read = cred->cmcred_pid;
1817 uid_read = cred->cmcred_euid;
1818 #elif defined(LOCAL_CREDS)
1819 pid_read = DBUS_PID_UNSET;
1820 uid_read = cmsg.cred.sc_uid;
1821 /* Since we have already got the credentials from this socket, we can
1822 * disable its LOCAL_CREDS flag if it was ever set. */
1823 _dbus_set_local_creds (client_fd, FALSE);
1824 #elif defined(HAVE_GETPEEREID)
1825 uid_t euid;
1826 gid_t egid;
1827 if (getpeereid (client_fd, &euid, &egid) == 0)
1828 {
1829 uid_read = euid;
1830 }
1831 else
1832 {
1833 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
1834 }
1835 #elif defined(HAVE_GETPEERUCRED)
1836 ucred_t * ucred = NULL;
1837 if (getpeerucred (client_fd, &ucred) == 0)
1838 {
1839 pid_read = ucred_getpid (ucred);
1840 uid_read = ucred_geteuid (ucred);
1841 #ifdef HAVE_ADT
1842 /* generate audit session data based on socket ucred */
1843 adt_session_data_t *adth = NULL;
1844 adt_export_data_t *data = NULL;
1845 size_t size = 0;
1846 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
1847 {
1848 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
1849 }
1850 else
1851 {
1852 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
1853 {
1854 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
1855 }
1856 else
1857 {
1858 size = adt_export_session_data (adth, &data);
1859 if (size <= 0)
1860 {
1861 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
1862 }
1863 else
1864 {
1865 _dbus_credentials_add_adt_audit_data (credentials, data, size);
1866 free (data);
1867 }
1868 }
1869 (void) adt_end_session (adth);
1870 }
1871 #endif /* HAVE_ADT */
1872 }
1873 else
1874 {
1875 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
1876 }
1877 if (ucred != NULL)
1878 ucred_free (ucred);
1879 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
1880 _dbus_verbose ("Socket credentials not supported on this OS\n");
1881 #endif
1882 }
1883
1884 _dbus_verbose ("Credentials:"
1885 " pid "DBUS_PID_FORMAT
1886 " uid "DBUS_UID_FORMAT
1887 "\n",
1888 pid_read,
1889 uid_read);
1890
1891 if (pid_read != DBUS_PID_UNSET)
1892 {
1893 if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
1894 {
1895 _DBUS_SET_OOM (error);
1896 return FALSE;
1897 }
1898 }
1899
1900 if (uid_read != DBUS_UID_UNSET)
1901 {
1902 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
1903 {
1904 _DBUS_SET_OOM (error);
1905 return FALSE;
1906 }
1907 }
1908
1909 return TRUE;
1910 }
1911
1912 /**
1913 * Sends a single nul byte with our UNIX credentials as ancillary
1914 * data. Returns #TRUE if the data was successfully written. On
1915 * systems that don't support sending credentials, just writes a byte,
1916 * doesn't send any credentials. On some systems, such as Linux,
1917 * reading/writing the byte isn't actually required, but we do it
1918 * anyway just to avoid multiple codepaths.
1919 *
1920 * Fails if no byte can be written, so you must select() first.
1921 *
1922 * The point of the byte is that on some systems we have to
1923 * use sendmsg()/recvmsg() to transmit credentials.
1924 *
1925 * @param server_fd file descriptor for connection to server
1926 * @param error return location for error code
1927 * @returns #TRUE if the byte was sent
1928 */
1929 dbus_bool_t
_dbus_send_credentials_socket(int server_fd,DBusError * error)1930 _dbus_send_credentials_socket (int server_fd,
1931 DBusError *error)
1932 {
1933 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1934
1935 if (write_credentials_byte (server_fd, error))
1936 return TRUE;
1937 else
1938 return FALSE;
1939 }
1940
1941 /**
1942 * Accepts a connection on a listening socket.
1943 * Handles EINTR for you.
1944 *
1945 * This will enable FD_CLOEXEC for the returned socket.
1946 *
1947 * @param listen_fd the listen file descriptor
1948 * @returns the connection fd of the client, or -1 on error
1949 */
1950 int
_dbus_accept(int listen_fd)1951 _dbus_accept (int listen_fd)
1952 {
1953 int client_fd;
1954 struct sockaddr addr;
1955 socklen_t addrlen;
1956 #ifdef HAVE_ACCEPT4
1957 dbus_bool_t cloexec_done;
1958 #endif
1959
1960 addrlen = sizeof (addr);
1961
1962 retry:
1963
1964 #ifdef HAVE_ACCEPT4
1965 /* We assume that if accept4 is available SOCK_CLOEXEC is too */
1966 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
1967 cloexec_done = client_fd >= 0;
1968
1969 if (client_fd < 0 && errno == ENOSYS)
1970 #endif
1971 {
1972 client_fd = accept (listen_fd, &addr, &addrlen);
1973 }
1974
1975 if (client_fd < 0)
1976 {
1977 if (errno == EINTR)
1978 goto retry;
1979 }
1980
1981 _dbus_verbose ("client fd %d accepted\n", client_fd);
1982
1983 #ifdef HAVE_ACCEPT4
1984 if (!cloexec_done)
1985 #endif
1986 {
1987 _dbus_fd_set_close_on_exec(client_fd);
1988 }
1989
1990 return client_fd;
1991 }
1992
1993 /**
1994 * Checks to make sure the given directory is
1995 * private to the user
1996 *
1997 * @param dir the name of the directory
1998 * @param error error return
1999 * @returns #FALSE on failure
2000 **/
2001 dbus_bool_t
_dbus_check_dir_is_private_to_user(DBusString * dir,DBusError * error)2002 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
2003 {
2004 const char *directory;
2005 struct stat sb;
2006
2007 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2008
2009 directory = _dbus_string_get_const_data (dir);
2010
2011 if (stat (directory, &sb) < 0)
2012 {
2013 dbus_set_error (error, _dbus_error_from_errno (errno),
2014 "%s", _dbus_strerror (errno));
2015
2016 return FALSE;
2017 }
2018
2019 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2020 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2021 {
2022 dbus_set_error (error, DBUS_ERROR_FAILED,
2023 "%s directory is not private to the user", directory);
2024 return FALSE;
2025 }
2026
2027 return TRUE;
2028 }
2029
2030 static dbus_bool_t
fill_user_info_from_passwd(struct passwd * p,DBusUserInfo * info,DBusError * error)2031 fill_user_info_from_passwd (struct passwd *p,
2032 DBusUserInfo *info,
2033 DBusError *error)
2034 {
2035 _dbus_assert (p->pw_name != NULL);
2036 _dbus_assert (p->pw_dir != NULL);
2037
2038 info->uid = p->pw_uid;
2039 info->primary_gid = p->pw_gid;
2040 info->username = _dbus_strdup (p->pw_name);
2041 info->homedir = _dbus_strdup (p->pw_dir);
2042
2043 if (info->username == NULL ||
2044 info->homedir == NULL)
2045 {
2046 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2047 return FALSE;
2048 }
2049
2050 return TRUE;
2051 }
2052
2053 static dbus_bool_t
fill_user_info(DBusUserInfo * info,dbus_uid_t uid,const DBusString * username,DBusError * error)2054 fill_user_info (DBusUserInfo *info,
2055 dbus_uid_t uid,
2056 const DBusString *username,
2057 DBusError *error)
2058 {
2059 const char *username_c;
2060
2061 /* exactly one of username/uid provided */
2062 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2063 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2064
2065 info->uid = DBUS_UID_UNSET;
2066 info->primary_gid = DBUS_GID_UNSET;
2067 info->group_ids = NULL;
2068 info->n_group_ids = 0;
2069 info->username = NULL;
2070 info->homedir = NULL;
2071
2072 if (username != NULL)
2073 username_c = _dbus_string_get_const_data (username);
2074 else
2075 username_c = NULL;
2076
2077 /* For now assuming that the getpwnam() and getpwuid() flavors
2078 * are always symmetrical, if not we have to add more configure
2079 * checks
2080 */
2081
2082 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2083 {
2084 struct passwd *p;
2085 int result;
2086 size_t buflen;
2087 char *buf;
2088 struct passwd p_str;
2089
2090 /* retrieve maximum needed size for buf */
2091 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2092
2093 /* sysconf actually returns a long, but everything else expects size_t,
2094 * so just recast here.
2095 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2096 */
2097 if ((long) buflen <= 0)
2098 buflen = 1024;
2099
2100 result = -1;
2101 while (1)
2102 {
2103 buf = dbus_malloc (buflen);
2104 if (buf == NULL)
2105 {
2106 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2107 return FALSE;
2108 }
2109
2110 p = NULL;
2111 #ifdef HAVE_POSIX_GETPWNAM_R
2112 if (uid != DBUS_UID_UNSET)
2113 result = getpwuid_r (uid, &p_str, buf, buflen,
2114 &p);
2115 else
2116 result = getpwnam_r (username_c, &p_str, buf, buflen,
2117 &p);
2118 #else
2119 if (uid != DBUS_UID_UNSET)
2120 p = getpwuid_r (uid, &p_str, buf, buflen);
2121 else
2122 p = getpwnam_r (username_c, &p_str, buf, buflen);
2123 result = 0;
2124 #endif /* !HAVE_POSIX_GETPWNAM_R */
2125 //Try a bigger buffer if ERANGE was returned
2126 if (result == ERANGE && buflen < 512 * 1024)
2127 {
2128 dbus_free (buf);
2129 buflen *= 2;
2130 }
2131 else
2132 {
2133 break;
2134 }
2135 }
2136 if (result == 0 && p == &p_str)
2137 {
2138 if (!fill_user_info_from_passwd (p, info, error))
2139 {
2140 dbus_free (buf);
2141 return FALSE;
2142 }
2143 dbus_free (buf);
2144 }
2145 else
2146 {
2147 dbus_set_error (error, _dbus_error_from_errno (errno),
2148 "User \"%s\" unknown or no memory to allocate password entry\n",
2149 username_c ? username_c : "???");
2150 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2151 dbus_free (buf);
2152 return FALSE;
2153 }
2154 }
2155 #else /* ! HAVE_GETPWNAM_R */
2156 {
2157 /* I guess we're screwed on thread safety here */
2158 struct passwd *p;
2159
2160 if (uid != DBUS_UID_UNSET)
2161 p = getpwuid (uid);
2162 else
2163 p = getpwnam (username_c);
2164
2165 if (p != NULL)
2166 {
2167 if (!fill_user_info_from_passwd (p, info, error))
2168 {
2169 return FALSE;
2170 }
2171 }
2172 else
2173 {
2174 dbus_set_error (error, _dbus_error_from_errno (errno),
2175 "User \"%s\" unknown or no memory to allocate password entry\n",
2176 username_c ? username_c : "???");
2177 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2178 return FALSE;
2179 }
2180 }
2181 #endif /* ! HAVE_GETPWNAM_R */
2182
2183 /* Fill this in so we can use it to get groups */
2184 username_c = info->username;
2185
2186 #ifdef HAVE_GETGROUPLIST
2187 {
2188 gid_t *buf;
2189 int buf_count;
2190 int i;
2191 int initial_buf_count;
2192
2193 initial_buf_count = 17;
2194 buf_count = initial_buf_count;
2195 buf = dbus_new (gid_t, buf_count);
2196 if (buf == NULL)
2197 {
2198 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2199 goto failed;
2200 }
2201
2202 if (getgrouplist (username_c,
2203 info->primary_gid,
2204 buf, &buf_count) < 0)
2205 {
2206 gid_t *new;
2207 /* Presumed cause of negative return code: buf has insufficient
2208 entries to hold the entire group list. The Linux behavior in this
2209 case is to pass back the actual number of groups in buf_count, but
2210 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2211 So as a hack, try to help out a bit by guessing a larger
2212 number of groups, within reason.. might still fail, of course,
2213 but we can at least print a more informative message. I looked up
2214 the "right way" to do this by downloading Apple's own source code
2215 for the "id" command, and it turns out that they use an
2216 undocumented library function getgrouplist_2 (!) which is not
2217 declared in any header in /usr/include (!!). That did not seem
2218 like the way to go here.
2219 */
2220 if (buf_count == initial_buf_count)
2221 {
2222 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2223 }
2224 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2225 if (new == NULL)
2226 {
2227 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2228 dbus_free (buf);
2229 goto failed;
2230 }
2231
2232 buf = new;
2233
2234 errno = 0;
2235 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2236 {
2237 if (errno == 0)
2238 {
2239 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2240 username_c, buf_count, buf_count);
2241 }
2242 else
2243 {
2244 dbus_set_error (error,
2245 _dbus_error_from_errno (errno),
2246 "Failed to get groups for username \"%s\" primary GID "
2247 DBUS_GID_FORMAT ": %s\n",
2248 username_c, info->primary_gid,
2249 _dbus_strerror (errno));
2250 dbus_free (buf);
2251 goto failed;
2252 }
2253 }
2254 }
2255
2256 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2257 if (info->group_ids == NULL)
2258 {
2259 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2260 dbus_free (buf);
2261 goto failed;
2262 }
2263
2264 for (i = 0; i < buf_count; ++i)
2265 info->group_ids[i] = buf[i];
2266
2267 info->n_group_ids = buf_count;
2268
2269 dbus_free (buf);
2270 }
2271 #else /* HAVE_GETGROUPLIST */
2272 {
2273 /* We just get the one group ID */
2274 info->group_ids = dbus_new (dbus_gid_t, 1);
2275 if (info->group_ids == NULL)
2276 {
2277 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2278 goto failed;
2279 }
2280
2281 info->n_group_ids = 1;
2282
2283 (info->group_ids)[0] = info->primary_gid;
2284 }
2285 #endif /* HAVE_GETGROUPLIST */
2286
2287 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2288
2289 return TRUE;
2290
2291 failed:
2292 _DBUS_ASSERT_ERROR_IS_SET (error);
2293 return FALSE;
2294 }
2295
2296 /**
2297 * Gets user info for the given username.
2298 *
2299 * @param info user info object to initialize
2300 * @param username the username
2301 * @param error error return
2302 * @returns #TRUE on success
2303 */
2304 dbus_bool_t
_dbus_user_info_fill(DBusUserInfo * info,const DBusString * username,DBusError * error)2305 _dbus_user_info_fill (DBusUserInfo *info,
2306 const DBusString *username,
2307 DBusError *error)
2308 {
2309 return fill_user_info (info, DBUS_UID_UNSET,
2310 username, error);
2311 }
2312
2313 /**
2314 * Gets user info for the given user ID.
2315 *
2316 * @param info user info object to initialize
2317 * @param uid the user ID
2318 * @param error error return
2319 * @returns #TRUE on success
2320 */
2321 dbus_bool_t
_dbus_user_info_fill_uid(DBusUserInfo * info,dbus_uid_t uid,DBusError * error)2322 _dbus_user_info_fill_uid (DBusUserInfo *info,
2323 dbus_uid_t uid,
2324 DBusError *error)
2325 {
2326 return fill_user_info (info, uid,
2327 NULL, error);
2328 }
2329
2330 /**
2331 * Adds the credentials of the current process to the
2332 * passed-in credentials object.
2333 *
2334 * @param credentials credentials to add to
2335 * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
2336 */
2337 dbus_bool_t
_dbus_credentials_add_from_current_process(DBusCredentials * credentials)2338 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
2339 {
2340 /* The POSIX spec certainly doesn't promise this, but
2341 * we need these assertions to fail as soon as we're wrong about
2342 * it so we can do the porting fixups
2343 */
2344 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
2345 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
2346 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
2347
2348 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
2349 return FALSE;
2350 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2351 return FALSE;
2352
2353 return TRUE;
2354 }
2355
2356 /**
2357 * Append to the string the identity we would like to have when we
2358 * authenticate, on UNIX this is the current process UID and on
2359 * Windows something else, probably a Windows SID string. No escaping
2360 * is required, that is done in dbus-auth.c. The username here
2361 * need not be anything human-readable, it can be the machine-readable
2362 * form i.e. a user id.
2363 *
2364 * @param str the string to append to
2365 * @returns #FALSE on no memory
2366 */
2367 dbus_bool_t
_dbus_append_user_from_current_process(DBusString * str)2368 _dbus_append_user_from_current_process (DBusString *str)
2369 {
2370 return _dbus_string_append_uint (str,
2371 _dbus_geteuid ());
2372 }
2373
2374 /**
2375 * Gets our process ID
2376 * @returns process ID
2377 */
2378 dbus_pid_t
_dbus_getpid(void)2379 _dbus_getpid (void)
2380 {
2381 return getpid ();
2382 }
2383
2384 /** Gets our UID
2385 * @returns process UID
2386 */
2387 dbus_uid_t
_dbus_getuid(void)2388 _dbus_getuid (void)
2389 {
2390 return getuid ();
2391 }
2392
2393 /** Gets our effective UID
2394 * @returns process effective UID
2395 */
2396 dbus_uid_t
_dbus_geteuid(void)2397 _dbus_geteuid (void)
2398 {
2399 return geteuid ();
2400 }
2401
2402 /**
2403 * The only reason this is separate from _dbus_getpid() is to allow it
2404 * on Windows for logging but not for other purposes.
2405 *
2406 * @returns process ID to put in log messages
2407 */
2408 unsigned long
_dbus_pid_for_log(void)2409 _dbus_pid_for_log (void)
2410 {
2411 return getpid ();
2412 }
2413
2414 /**
2415 * Gets a UID from a UID string.
2416 *
2417 * @param uid_str the UID in string form
2418 * @param uid UID to fill in
2419 * @returns #TRUE if successfully filled in UID
2420 */
2421 dbus_bool_t
_dbus_parse_uid(const DBusString * uid_str,dbus_uid_t * uid)2422 _dbus_parse_uid (const DBusString *uid_str,
2423 dbus_uid_t *uid)
2424 {
2425 int end;
2426 long val;
2427
2428 if (_dbus_string_get_length (uid_str) == 0)
2429 {
2430 _dbus_verbose ("UID string was zero length\n");
2431 return FALSE;
2432 }
2433
2434 val = -1;
2435 end = 0;
2436 if (!_dbus_string_parse_int (uid_str, 0, &val,
2437 &end))
2438 {
2439 _dbus_verbose ("could not parse string as a UID\n");
2440 return FALSE;
2441 }
2442
2443 if (end != _dbus_string_get_length (uid_str))
2444 {
2445 _dbus_verbose ("string contained trailing stuff after UID\n");
2446 return FALSE;
2447 }
2448
2449 *uid = val;
2450
2451 return TRUE;
2452 }
2453
2454 #if !DBUS_USE_SYNC
2455 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
2456 #endif
2457
2458 /**
2459 * Atomically increments an integer
2460 *
2461 * @param atomic pointer to the integer to increment
2462 * @returns the value before incrementing
2463 */
2464 dbus_int32_t
_dbus_atomic_inc(DBusAtomic * atomic)2465 _dbus_atomic_inc (DBusAtomic *atomic)
2466 {
2467 #if DBUS_USE_SYNC
2468 return __sync_add_and_fetch(&atomic->value, 1)-1;
2469 #else
2470 dbus_int32_t res;
2471 _DBUS_LOCK (atomic);
2472 res = atomic->value;
2473 atomic->value += 1;
2474 _DBUS_UNLOCK (atomic);
2475 return res;
2476 #endif
2477 }
2478
2479 /**
2480 * Atomically decrement an integer
2481 *
2482 * @param atomic pointer to the integer to decrement
2483 * @returns the value before decrementing
2484 */
2485 dbus_int32_t
_dbus_atomic_dec(DBusAtomic * atomic)2486 _dbus_atomic_dec (DBusAtomic *atomic)
2487 {
2488 #if DBUS_USE_SYNC
2489 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2490 #else
2491 dbus_int32_t res;
2492
2493 _DBUS_LOCK (atomic);
2494 res = atomic->value;
2495 atomic->value -= 1;
2496 _DBUS_UNLOCK (atomic);
2497 return res;
2498 #endif
2499 }
2500
2501 /**
2502 * Atomically get the value of an integer. It may change at any time
2503 * thereafter, so this is mostly only useful for assertions.
2504 *
2505 * @param atomic pointer to the integer to get
2506 * @returns the value at this moment
2507 */
2508 dbus_int32_t
_dbus_atomic_get(DBusAtomic * atomic)2509 _dbus_atomic_get (DBusAtomic *atomic)
2510 {
2511 #if DBUS_USE_SYNC
2512 __sync_synchronize ();
2513 return atomic->value;
2514 #else
2515 dbus_int32_t res;
2516
2517 _DBUS_LOCK (atomic);
2518 res = atomic->value;
2519 _DBUS_UNLOCK (atomic);
2520 return res;
2521 #endif
2522 }
2523
2524 /**
2525 * Wrapper for poll().
2526 *
2527 * @param fds the file descriptors to poll
2528 * @param n_fds number of descriptors in the array
2529 * @param timeout_milliseconds timeout or -1 for infinite
2530 * @returns numbers of fds with revents, or <0 on error
2531 */
2532 int
_dbus_poll(DBusPollFD * fds,int n_fds,int timeout_milliseconds)2533 _dbus_poll (DBusPollFD *fds,
2534 int n_fds,
2535 int timeout_milliseconds)
2536 {
2537 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2538 /* This big thing is a constant expression and should get optimized
2539 * out of existence. So it's more robust than a configure check at
2540 * no cost.
2541 */
2542 if (_DBUS_POLLIN == POLLIN &&
2543 _DBUS_POLLPRI == POLLPRI &&
2544 _DBUS_POLLOUT == POLLOUT &&
2545 _DBUS_POLLERR == POLLERR &&
2546 _DBUS_POLLHUP == POLLHUP &&
2547 _DBUS_POLLNVAL == POLLNVAL &&
2548 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
2549 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
2550 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
2551 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
2552 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
2553 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
2554 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
2555 {
2556 return poll ((struct pollfd*) fds,
2557 n_fds,
2558 timeout_milliseconds);
2559 }
2560 else
2561 {
2562 /* We have to convert the DBusPollFD to an array of
2563 * struct pollfd, poll, and convert back.
2564 */
2565 _dbus_warn ("didn't implement poll() properly for this system yet\n");
2566 return -1;
2567 }
2568 #else /* ! HAVE_POLL */
2569
2570 fd_set read_set, write_set, err_set;
2571 int max_fd = 0;
2572 int i;
2573 struct timeval tv;
2574 int ready;
2575
2576 FD_ZERO (&read_set);
2577 FD_ZERO (&write_set);
2578 FD_ZERO (&err_set);
2579
2580 for (i = 0; i < n_fds; i++)
2581 {
2582 DBusPollFD *fdp = &fds[i];
2583
2584 if (fdp->events & _DBUS_POLLIN)
2585 FD_SET (fdp->fd, &read_set);
2586
2587 if (fdp->events & _DBUS_POLLOUT)
2588 FD_SET (fdp->fd, &write_set);
2589
2590 FD_SET (fdp->fd, &err_set);
2591
2592 max_fd = MAX (max_fd, fdp->fd);
2593 }
2594
2595 tv.tv_sec = timeout_milliseconds / 1000;
2596 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2597
2598 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2599 timeout_milliseconds < 0 ? NULL : &tv);
2600
2601 if (ready > 0)
2602 {
2603 for (i = 0; i < n_fds; i++)
2604 {
2605 DBusPollFD *fdp = &fds[i];
2606
2607 fdp->revents = 0;
2608
2609 if (FD_ISSET (fdp->fd, &read_set))
2610 fdp->revents |= _DBUS_POLLIN;
2611
2612 if (FD_ISSET (fdp->fd, &write_set))
2613 fdp->revents |= _DBUS_POLLOUT;
2614
2615 if (FD_ISSET (fdp->fd, &err_set))
2616 fdp->revents |= _DBUS_POLLERR;
2617 }
2618 }
2619
2620 return ready;
2621 #endif
2622 }
2623
2624 /**
2625 * Get current time, as in gettimeofday(). Use the monotonic clock if
2626 * available, to avoid problems when the system time changes.
2627 *
2628 * @param tv_sec return location for number of seconds
2629 * @param tv_usec return location for number of microseconds
2630 */
2631 void
_dbus_get_monotonic_time(long * tv_sec,long * tv_usec)2632 _dbus_get_monotonic_time (long *tv_sec,
2633 long *tv_usec)
2634 {
2635 #ifdef HAVE_MONOTONIC_CLOCK
2636 struct timespec ts;
2637 clock_gettime (CLOCK_MONOTONIC, &ts);
2638
2639 if (tv_sec)
2640 *tv_sec = ts.tv_sec;
2641 if (tv_usec)
2642 *tv_usec = ts.tv_nsec / 1000;
2643 #else
2644 struct timeval t;
2645
2646 gettimeofday (&t, NULL);
2647
2648 if (tv_sec)
2649 *tv_sec = t.tv_sec;
2650 if (tv_usec)
2651 *tv_usec = t.tv_usec;
2652 #endif
2653 }
2654
2655 /**
2656 * Get current time, as in gettimeofday(). Never uses the monotonic
2657 * clock.
2658 *
2659 * @param tv_sec return location for number of seconds
2660 * @param tv_usec return location for number of microseconds
2661 */
2662 void
_dbus_get_real_time(long * tv_sec,long * tv_usec)2663 _dbus_get_real_time (long *tv_sec,
2664 long *tv_usec)
2665 {
2666 struct timeval t;
2667
2668 gettimeofday (&t, NULL);
2669
2670 if (tv_sec)
2671 *tv_sec = t.tv_sec;
2672 if (tv_usec)
2673 *tv_usec = t.tv_usec;
2674 }
2675
2676 /**
2677 * Creates a directory; succeeds if the directory
2678 * is created or already existed.
2679 *
2680 * @param filename directory filename
2681 * @param error initialized error object
2682 * @returns #TRUE on success
2683 */
2684 dbus_bool_t
_dbus_create_directory(const DBusString * filename,DBusError * error)2685 _dbus_create_directory (const DBusString *filename,
2686 DBusError *error)
2687 {
2688 const char *filename_c;
2689
2690 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2691
2692 filename_c = _dbus_string_get_const_data (filename);
2693
2694 if (mkdir (filename_c, 0700) < 0)
2695 {
2696 if (errno == EEXIST)
2697 return TRUE;
2698
2699 dbus_set_error (error, DBUS_ERROR_FAILED,
2700 "Failed to create directory %s: %s\n",
2701 filename_c, _dbus_strerror (errno));
2702 return FALSE;
2703 }
2704 else
2705 return TRUE;
2706 }
2707
2708 /**
2709 * Appends the given filename to the given directory.
2710 *
2711 * @todo it might be cute to collapse multiple '/' such as "foo//"
2712 * concat "//bar"
2713 *
2714 * @param dir the directory name
2715 * @param next_component the filename
2716 * @returns #TRUE on success
2717 */
2718 dbus_bool_t
_dbus_concat_dir_and_file(DBusString * dir,const DBusString * next_component)2719 _dbus_concat_dir_and_file (DBusString *dir,
2720 const DBusString *next_component)
2721 {
2722 dbus_bool_t dir_ends_in_slash;
2723 dbus_bool_t file_starts_with_slash;
2724
2725 if (_dbus_string_get_length (dir) == 0 ||
2726 _dbus_string_get_length (next_component) == 0)
2727 return TRUE;
2728
2729 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
2730 _dbus_string_get_length (dir) - 1);
2731
2732 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
2733
2734 if (dir_ends_in_slash && file_starts_with_slash)
2735 {
2736 _dbus_string_shorten (dir, 1);
2737 }
2738 else if (!(dir_ends_in_slash || file_starts_with_slash))
2739 {
2740 if (!_dbus_string_append_byte (dir, '/'))
2741 return FALSE;
2742 }
2743
2744 return _dbus_string_copy (next_component, 0, dir,
2745 _dbus_string_get_length (dir));
2746 }
2747
2748 /** nanoseconds in a second */
2749 #define NANOSECONDS_PER_SECOND 1000000000
2750 /** microseconds in a second */
2751 #define MICROSECONDS_PER_SECOND 1000000
2752 /** milliseconds in a second */
2753 #define MILLISECONDS_PER_SECOND 1000
2754 /** nanoseconds in a millisecond */
2755 #define NANOSECONDS_PER_MILLISECOND 1000000
2756 /** microseconds in a millisecond */
2757 #define MICROSECONDS_PER_MILLISECOND 1000
2758
2759 /**
2760 * Sleeps the given number of milliseconds.
2761 * @param milliseconds number of milliseconds
2762 */
2763 void
_dbus_sleep_milliseconds(int milliseconds)2764 _dbus_sleep_milliseconds (int milliseconds)
2765 {
2766 #ifdef HAVE_NANOSLEEP
2767 struct timespec req;
2768 struct timespec rem;
2769
2770 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
2771 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
2772 rem.tv_sec = 0;
2773 rem.tv_nsec = 0;
2774
2775 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
2776 req = rem;
2777 #elif defined (HAVE_USLEEP)
2778 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
2779 #else /* ! HAVE_USLEEP */
2780 sleep (MAX (milliseconds / 1000, 1));
2781 #endif
2782 }
2783
2784 static dbus_bool_t
_dbus_generate_pseudorandom_bytes(DBusString * str,int n_bytes)2785 _dbus_generate_pseudorandom_bytes (DBusString *str,
2786 int n_bytes)
2787 {
2788 int old_len;
2789 char *p;
2790
2791 old_len = _dbus_string_get_length (str);
2792
2793 if (!_dbus_string_lengthen (str, n_bytes))
2794 return FALSE;
2795
2796 p = _dbus_string_get_data_len (str, old_len, n_bytes);
2797
2798 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
2799
2800 return TRUE;
2801 }
2802
2803 /**
2804 * Generates the given number of random bytes,
2805 * using the best mechanism we can come up with.
2806 *
2807 * @param str the string
2808 * @param n_bytes the number of random bytes to append to string
2809 * @returns #TRUE on success, #FALSE if no memory
2810 */
2811 dbus_bool_t
_dbus_generate_random_bytes(DBusString * str,int n_bytes)2812 _dbus_generate_random_bytes (DBusString *str,
2813 int n_bytes)
2814 {
2815 int old_len;
2816 int fd;
2817
2818 /* FALSE return means "no memory", if it could
2819 * mean something else then we'd need to return
2820 * a DBusError. So we always fall back to pseudorandom
2821 * if the I/O fails.
2822 */
2823
2824 old_len = _dbus_string_get_length (str);
2825 fd = -1;
2826
2827 /* note, urandom on linux will fall back to pseudorandom */
2828 fd = open ("/dev/urandom", O_RDONLY);
2829 if (fd < 0)
2830 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2831
2832 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
2833
2834 if (_dbus_read (fd, str, n_bytes) != n_bytes)
2835 {
2836 _dbus_close (fd, NULL);
2837 _dbus_string_set_length (str, old_len);
2838 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
2839 }
2840
2841 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2842 n_bytes);
2843
2844 _dbus_close (fd, NULL);
2845
2846 return TRUE;
2847 }
2848
2849 /**
2850 * Exit the process, returning the given value.
2851 *
2852 * @param code the exit code
2853 */
2854 void
_dbus_exit(int code)2855 _dbus_exit (int code)
2856 {
2857 _exit (code);
2858 }
2859
2860 /**
2861 * A wrapper around strerror() because some platforms
2862 * may be lame and not have strerror(). Also, never
2863 * returns NULL.
2864 *
2865 * @param error_number errno.
2866 * @returns error description.
2867 */
2868 const char*
_dbus_strerror(int error_number)2869 _dbus_strerror (int error_number)
2870 {
2871 const char *msg;
2872
2873 msg = strerror (error_number);
2874 if (msg == NULL)
2875 msg = "unknown";
2876
2877 return msg;
2878 }
2879
2880 /**
2881 * signal (SIGPIPE, SIG_IGN);
2882 */
2883 void
_dbus_disable_sigpipe(void)2884 _dbus_disable_sigpipe (void)
2885 {
2886 signal (SIGPIPE, SIG_IGN);
2887 }
2888
2889 /**
2890 * Sets the file descriptor to be close
2891 * on exec. Should be called for all file
2892 * descriptors in D-Bus code.
2893 *
2894 * @param fd the file descriptor
2895 */
2896 void
_dbus_fd_set_close_on_exec(intptr_t fd)2897 _dbus_fd_set_close_on_exec (intptr_t fd)
2898 {
2899 int val;
2900
2901 val = fcntl (fd, F_GETFD, 0);
2902
2903 if (val < 0)
2904 return;
2905
2906 val |= FD_CLOEXEC;
2907
2908 fcntl (fd, F_SETFD, val);
2909 }
2910
2911 /**
2912 * Closes a file descriptor.
2913 *
2914 * @param fd the file descriptor
2915 * @param error error object
2916 * @returns #FALSE if error set
2917 */
2918 dbus_bool_t
_dbus_close(int fd,DBusError * error)2919 _dbus_close (int fd,
2920 DBusError *error)
2921 {
2922 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2923
2924 again:
2925 if (close (fd) < 0)
2926 {
2927 if (errno == EINTR)
2928 goto again;
2929
2930 dbus_set_error (error, _dbus_error_from_errno (errno),
2931 "Could not close fd %d", fd);
2932 return FALSE;
2933 }
2934
2935 return TRUE;
2936 }
2937
2938 /**
2939 * Duplicates a file descriptor. Makes sure the fd returned is >= 3
2940 * (i.e. avoids stdin/stdout/stderr). Sets O_CLOEXEC.
2941 *
2942 * @param fd the file descriptor to duplicate
2943 * @returns duplicated file descriptor
2944 * */
2945 int
_dbus_dup(int fd,DBusError * error)2946 _dbus_dup(int fd,
2947 DBusError *error)
2948 {
2949 int new_fd;
2950
2951 #ifdef F_DUPFD_CLOEXEC
2952 dbus_bool_t cloexec_done;
2953
2954 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2955 cloexec_done = new_fd >= 0;
2956
2957 if (new_fd < 0 && errno == EINVAL)
2958 #endif
2959 {
2960 new_fd = fcntl(fd, F_DUPFD, 3);
2961 }
2962
2963 if (new_fd < 0) {
2964
2965 dbus_set_error (error, _dbus_error_from_errno (errno),
2966 "Could not duplicate fd %d", fd);
2967 return -1;
2968 }
2969
2970 #ifdef F_DUPFD_CLOEXEC
2971 if (!cloexec_done)
2972 #endif
2973 {
2974 _dbus_fd_set_close_on_exec(new_fd);
2975 }
2976
2977 return new_fd;
2978 }
2979
2980 /**
2981 * Sets a file descriptor to be nonblocking.
2982 *
2983 * @param fd the file descriptor.
2984 * @param error address of error location.
2985 * @returns #TRUE on success.
2986 */
2987 dbus_bool_t
_dbus_set_fd_nonblocking(int fd,DBusError * error)2988 _dbus_set_fd_nonblocking (int fd,
2989 DBusError *error)
2990 {
2991 int val;
2992
2993 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2994
2995 val = fcntl (fd, F_GETFL, 0);
2996 if (val < 0)
2997 {
2998 dbus_set_error (error, _dbus_error_from_errno (errno),
2999 "Failed to get flags from file descriptor %d: %s",
3000 fd, _dbus_strerror (errno));
3001 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3002 _dbus_strerror (errno));
3003 return FALSE;
3004 }
3005
3006 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3007 {
3008 dbus_set_error (error, _dbus_error_from_errno (errno),
3009 "Failed to set nonblocking flag of file descriptor %d: %s",
3010 fd, _dbus_strerror (errno));
3011 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3012 fd, _dbus_strerror (errno));
3013
3014 return FALSE;
3015 }
3016
3017 return TRUE;
3018 }
3019
3020 /**
3021 * On GNU libc systems, print a crude backtrace to stderr. On other
3022 * systems, print "no backtrace support" and block for possible gdb
3023 * attachment if an appropriate environment variable is set.
3024 */
3025 void
_dbus_print_backtrace(void)3026 _dbus_print_backtrace (void)
3027 {
3028 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3029 void *bt[500];
3030 int bt_size;
3031 int i;
3032 char **syms;
3033
3034 bt_size = backtrace (bt, 500);
3035
3036 syms = backtrace_symbols (bt, bt_size);
3037
3038 i = 0;
3039 while (i < bt_size)
3040 {
3041 /* don't use dbus_warn since it can _dbus_abort() */
3042 fprintf (stderr, " %s\n", syms[i]);
3043 ++i;
3044 }
3045 fflush (stderr);
3046
3047 free (syms);
3048 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3049 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3050 #else
3051 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3052 #endif
3053 }
3054
3055 /**
3056 * Creates a full-duplex pipe (as in socketpair()).
3057 * Sets both ends of the pipe nonblocking.
3058 *
3059 * Marks both file descriptors as close-on-exec
3060 *
3061 * @param fd1 return location for one end
3062 * @param fd2 return location for the other end
3063 * @param blocking #TRUE if pipe should be blocking
3064 * @param error error return
3065 * @returns #FALSE on failure (if error is set)
3066 */
3067 dbus_bool_t
_dbus_full_duplex_pipe(int * fd1,int * fd2,dbus_bool_t blocking,DBusError * error)3068 _dbus_full_duplex_pipe (int *fd1,
3069 int *fd2,
3070 dbus_bool_t blocking,
3071 DBusError *error)
3072 {
3073 #ifdef HAVE_SOCKETPAIR
3074 int fds[2];
3075 int retval;
3076
3077 #ifdef SOCK_CLOEXEC
3078 dbus_bool_t cloexec_done;
3079
3080 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3081 cloexec_done = retval >= 0;
3082
3083 if (retval < 0 && errno == EINVAL)
3084 #endif
3085 {
3086 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3087 }
3088
3089 if (retval < 0)
3090 {
3091 dbus_set_error (error, _dbus_error_from_errno (errno),
3092 "Could not create full-duplex pipe");
3093 return FALSE;
3094 }
3095
3096 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3097
3098 #ifdef SOCK_CLOEXEC
3099 if (!cloexec_done)
3100 #endif
3101 {
3102 _dbus_fd_set_close_on_exec (fds[0]);
3103 _dbus_fd_set_close_on_exec (fds[1]);
3104 }
3105
3106 if (!blocking &&
3107 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3108 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3109 {
3110 dbus_set_error (error, _dbus_error_from_errno (errno),
3111 "Could not set full-duplex pipe nonblocking");
3112
3113 _dbus_close (fds[0], NULL);
3114 _dbus_close (fds[1], NULL);
3115
3116 return FALSE;
3117 }
3118
3119 *fd1 = fds[0];
3120 *fd2 = fds[1];
3121
3122 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3123 *fd1, *fd2);
3124
3125 return TRUE;
3126 #else
3127 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
3128 dbus_set_error (error, DBUS_ERROR_FAILED,
3129 "_dbus_full_duplex_pipe() not implemented on this OS");
3130 return FALSE;
3131 #endif
3132 }
3133
3134 /**
3135 * Measure the length of the given format string and arguments,
3136 * not including the terminating nul.
3137 *
3138 * @param format a printf-style format string
3139 * @param args arguments for the format string
3140 * @returns length of the given format string and args, or -1 if no memory
3141 */
3142 int
_dbus_printf_string_upper_bound(const char * format,va_list args)3143 _dbus_printf_string_upper_bound (const char *format,
3144 va_list args)
3145 {
3146 char static_buf[1024];
3147 int bufsize = sizeof (static_buf);
3148 int len;
3149
3150 len = vsnprintf (static_buf, bufsize, format, args);
3151
3152 /* If vsnprintf() returned non-negative, then either the string fits in
3153 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3154 * returns the number of characters that were needed, or this OS returns the
3155 * truncated length.
3156 *
3157 * We ignore the possibility that snprintf might just ignore the length and
3158 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3159 * If your libc is really that bad, come back when you have a better one. */
3160 if (len == bufsize)
3161 {
3162 /* This could be the truncated length (Tru64 and IRIX have this bug),
3163 * or the real length could be coincidentally the same. Which is it?
3164 * If vsnprintf returns the truncated length, we'll go to the slow
3165 * path. */
3166 if (vsnprintf (static_buf, 1, format, args) == 1)
3167 len = -1;
3168 }
3169
3170 /* If vsnprintf() returned negative, we have to do more work.
3171 * HP-UX returns negative. */
3172 while (len < 0)
3173 {
3174 char *buf;
3175
3176 bufsize *= 2;
3177
3178 buf = dbus_malloc (bufsize);
3179
3180 if (buf == NULL)
3181 return -1;
3182
3183 len = vsnprintf (buf, bufsize, format, args);
3184 dbus_free (buf);
3185
3186 /* If the reported length is exactly the buffer size, round up to the
3187 * next size, in case vsnprintf has been returning the truncated
3188 * length */
3189 if (len == bufsize)
3190 len = -1;
3191 }
3192
3193 return len;
3194 }
3195
3196 /**
3197 * Gets the temporary files directory by inspecting the environment variables
3198 * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
3199 *
3200 * @returns location of temp directory
3201 */
3202 const char*
_dbus_get_tmpdir(void)3203 _dbus_get_tmpdir(void)
3204 {
3205 static const char* tmpdir = NULL;
3206
3207 if (tmpdir == NULL)
3208 {
3209 /* TMPDIR is what glibc uses, then
3210 * glibc falls back to the P_tmpdir macro which
3211 * just expands to "/tmp"
3212 */
3213 if (tmpdir == NULL)
3214 tmpdir = getenv("TMPDIR");
3215
3216 /* These two env variables are probably
3217 * broken, but maybe some OS uses them?
3218 */
3219 if (tmpdir == NULL)
3220 tmpdir = getenv("TMP");
3221 if (tmpdir == NULL)
3222 tmpdir = getenv("TEMP");
3223
3224 /* And this is the sane fallback. */
3225 if (tmpdir == NULL)
3226 tmpdir = "/tmp";
3227 }
3228
3229 _dbus_assert(tmpdir != NULL);
3230
3231 return tmpdir;
3232 }
3233
3234 /**
3235 * Execute a subprocess, returning up to 1024 bytes of output
3236 * into @p result.
3237 *
3238 * If successful, returns #TRUE and appends the output to @p
3239 * result. If a failure happens, returns #FALSE and
3240 * sets an error in @p error.
3241 *
3242 * @note It's not an error if the subprocess terminates normally
3243 * without writing any data to stdout. Verify the @p result length
3244 * before and after this function call to cover this case.
3245 *
3246 * @param progname initial path to exec (may or may not be absolute)
3247 * @param path_fallback if %TRUE, search PATH for executable
3248 * @param argv NULL-terminated list of arguments
3249 * @param result a DBusString where the output can be append
3250 * @param error a DBusError to store the error in case of failure
3251 * @returns #TRUE on success, #FALSE if an error happened
3252 */
3253 static dbus_bool_t
_read_subprocess_line_argv(const char * progpath,dbus_bool_t path_fallback,char * const * argv,DBusString * result,DBusError * error)3254 _read_subprocess_line_argv (const char *progpath,
3255 dbus_bool_t path_fallback,
3256 char * const *argv,
3257 DBusString *result,
3258 DBusError *error)
3259 {
3260 int result_pipe[2] = { -1, -1 };
3261 int errors_pipe[2] = { -1, -1 };
3262 pid_t pid;
3263 int ret;
3264 int status;
3265 int orig_len;
3266
3267 dbus_bool_t retval;
3268 sigset_t new_set, old_set;
3269
3270 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3271 retval = FALSE;
3272
3273 /* We need to block any existing handlers for SIGCHLD temporarily; they
3274 * will cause waitpid() below to fail.
3275 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3276 */
3277 sigemptyset (&new_set);
3278 sigaddset (&new_set, SIGCHLD);
3279 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3280
3281 orig_len = _dbus_string_get_length (result);
3282
3283 #define READ_END 0
3284 #define WRITE_END 1
3285 if (pipe (result_pipe) < 0)
3286 {
3287 dbus_set_error (error, _dbus_error_from_errno (errno),
3288 "Failed to create a pipe to call %s: %s",
3289 progpath, _dbus_strerror (errno));
3290 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3291 progpath, _dbus_strerror (errno));
3292 goto out;
3293 }
3294 if (pipe (errors_pipe) < 0)
3295 {
3296 dbus_set_error (error, _dbus_error_from_errno (errno),
3297 "Failed to create a pipe to call %s: %s",
3298 progpath, _dbus_strerror (errno));
3299 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3300 progpath, _dbus_strerror (errno));
3301 goto out;
3302 }
3303
3304 pid = fork ();
3305 if (pid < 0)
3306 {
3307 dbus_set_error (error, _dbus_error_from_errno (errno),
3308 "Failed to fork() to call %s: %s",
3309 progpath, _dbus_strerror (errno));
3310 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3311 progpath, _dbus_strerror (errno));
3312 goto out;
3313 }
3314
3315 if (pid == 0)
3316 {
3317 /* child process */
3318 int fd;
3319
3320 fd = open ("/dev/null", O_RDWR);
3321 if (fd == -1)
3322 /* huh?! can't open /dev/null? */
3323 _exit (1);
3324
3325 _dbus_verbose ("/dev/null fd %d opened\n", fd);
3326
3327 /* set-up stdXXX */
3328 close (result_pipe[READ_END]);
3329 close (errors_pipe[READ_END]);
3330 close (0); /* close stdin */
3331 close (1); /* close stdout */
3332 close (2); /* close stderr */
3333
3334 if (dup2 (fd, 0) == -1)
3335 _exit (1);
3336 if (dup2 (result_pipe[WRITE_END], 1) == -1)
3337 _exit (1);
3338 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
3339 _exit (1);
3340
3341 _dbus_close_all ();
3342
3343 sigprocmask (SIG_SETMASK, &old_set, NULL);
3344
3345 /* If it looks fully-qualified, try execv first */
3346 if (progpath[0] == '/')
3347 {
3348 execv (progpath, argv);
3349 /* Ok, that failed. Now if path_fallback is given, let's
3350 * try unqualified. This is mostly a hack to work
3351 * around systems which ship dbus-launch in /usr/bin
3352 * but everything else in /bin (because dbus-launch
3353 * depends on X11).
3354 */
3355 if (path_fallback)
3356 /* We must have a slash, because we checked above */
3357 execvp (strrchr (progpath, '/')+1, argv);
3358 }
3359 else
3360 execvp (progpath, argv);
3361
3362 /* still nothing, we failed */
3363 _exit (1);
3364 }
3365
3366 /* parent process */
3367 close (result_pipe[WRITE_END]);
3368 close (errors_pipe[WRITE_END]);
3369 result_pipe[WRITE_END] = -1;
3370 errors_pipe[WRITE_END] = -1;
3371
3372 ret = 0;
3373 do
3374 {
3375 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3376 }
3377 while (ret > 0);
3378
3379 /* reap the child process to avoid it lingering as zombie */
3380 do
3381 {
3382 ret = waitpid (pid, &status, 0);
3383 }
3384 while (ret == -1 && errno == EINTR);
3385
3386 /* We succeeded if the process exited with status 0 and
3387 anything was read */
3388 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3389 {
3390 /* The process ended with error */
3391 DBusString error_message;
3392 if (!_dbus_string_init (&error_message))
3393 {
3394 _DBUS_SET_OOM (error);
3395 goto out;
3396 }
3397
3398 ret = 0;
3399 do
3400 {
3401 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3402 }
3403 while (ret > 0);
3404
3405 _dbus_string_set_length (result, orig_len);
3406 if (_dbus_string_get_length (&error_message) > 0)
3407 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3408 "%s terminated abnormally with the following error: %s",
3409 progpath, _dbus_string_get_data (&error_message));
3410 else
3411 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
3412 "%s terminated abnormally without any error message",
3413 progpath);
3414 goto out;
3415 }
3416
3417 retval = TRUE;
3418
3419 out:
3420 sigprocmask (SIG_SETMASK, &old_set, NULL);
3421
3422 if (retval)
3423 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3424 else
3425 _DBUS_ASSERT_ERROR_IS_SET (error);
3426
3427 if (result_pipe[0] != -1)
3428 close (result_pipe[0]);
3429 if (result_pipe[1] != -1)
3430 close (result_pipe[1]);
3431 if (errors_pipe[0] != -1)
3432 close (errors_pipe[0]);
3433 if (errors_pipe[1] != -1)
3434 close (errors_pipe[1]);
3435
3436 return retval;
3437 }
3438
3439 /**
3440 * Returns the address of a new session bus.
3441 *
3442 * If successful, returns #TRUE and appends the address to @p
3443 * address. If a failure happens, returns #FALSE and
3444 * sets an error in @p error.
3445 *
3446 * @param address a DBusString where the address can be stored
3447 * @param error a DBusError to store the error in case of failure
3448 * @returns #TRUE on success, #FALSE if an error happened
3449 */
3450 dbus_bool_t
_dbus_get_autolaunch_address(const char * scope,DBusString * address,DBusError * error)3451 _dbus_get_autolaunch_address (const char *scope,
3452 DBusString *address,
3453 DBusError *error)
3454 {
3455 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3456 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3457 * but that's done elsewhere, and if it worked, this function wouldn't
3458 * be called.) */
3459 const char *display;
3460 static char *argv[6];
3461 int i;
3462 DBusString uuid;
3463 dbus_bool_t retval;
3464
3465 if (_dbus_check_setuid ())
3466 {
3467 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3468 "Unable to autolaunch when setuid");
3469 return FALSE;
3470 }
3471
3472 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3473 retval = FALSE;
3474
3475 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3476 * dbus-launch-x11 is just going to fail. Rather than trying to
3477 * run it, we might as well bail out early with a nice error. */
3478 display = _dbus_getenv ("DISPLAY");
3479
3480 if (display == NULL || display[0] == '\0')
3481 {
3482 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3483 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3484 return FALSE;
3485 }
3486
3487 if (!_dbus_string_init (&uuid))
3488 {
3489 _DBUS_SET_OOM (error);
3490 return FALSE;
3491 }
3492
3493 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
3494 {
3495 _DBUS_SET_OOM (error);
3496 goto out;
3497 }
3498
3499 i = 0;
3500 argv[i] = "dbus-launch";
3501 ++i;
3502 argv[i] = "--autolaunch";
3503 ++i;
3504 argv[i] = _dbus_string_get_data (&uuid);
3505 ++i;
3506 argv[i] = "--binary-syntax";
3507 ++i;
3508 argv[i] = "--close-stderr";
3509 ++i;
3510 argv[i] = NULL;
3511 ++i;
3512
3513 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3514
3515 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
3516 TRUE,
3517 argv, address, error);
3518
3519 out:
3520 _dbus_string_free (&uuid);
3521 return retval;
3522 #else
3523 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3524 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3525 "set your DBUS_SESSION_BUS_ADDRESS instead");
3526 return FALSE;
3527 #endif
3528 }
3529
3530 /**
3531 * Reads the uuid of the machine we're running on from
3532 * the dbus configuration. Optionally try to create it
3533 * (only root can do this usually).
3534 *
3535 * On UNIX, reads a file that gets created by dbus-uuidgen
3536 * in a post-install script. On Windows, if there's a standard
3537 * machine uuid we could just use that, but I can't find one
3538 * with the right properties (the hardware profile guid can change
3539 * without rebooting I believe). If there's no standard one
3540 * we might want to use the registry instead of a file for
3541 * this, and I'm not sure how we'd ensure the uuid gets created.
3542 *
3543 * @param machine_id guid to init with the machine's uuid
3544 * @param create_if_not_found try to create the uuid if it doesn't exist
3545 * @param error the error return
3546 * @returns #FALSE if the error is set
3547 */
3548 dbus_bool_t
_dbus_read_local_machine_uuid(DBusGUID * machine_id,dbus_bool_t create_if_not_found,DBusError * error)3549 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
3550 dbus_bool_t create_if_not_found,
3551 DBusError *error)
3552 {
3553 DBusString filename;
3554 dbus_bool_t b;
3555
3556 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3557
3558 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
3559 if (b)
3560 return TRUE;
3561
3562 dbus_error_free (error);
3563
3564 /* Fallback to the system machine ID */
3565 _dbus_string_init_const (&filename, "/etc/machine-id");
3566 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3567 }
3568
3569 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
3570 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
3571
3572 /**
3573 * quries launchd for a specific env var which holds the socket path.
3574 * @param launchd_env_var the env var to look up
3575 * @param error a DBusError to store the error in case of failure
3576 * @return the value of the env var
3577 */
3578 dbus_bool_t
_dbus_lookup_launchd_socket(DBusString * socket_path,const char * launchd_env_var,DBusError * error)3579 _dbus_lookup_launchd_socket (DBusString *socket_path,
3580 const char *launchd_env_var,
3581 DBusError *error)
3582 {
3583 #ifdef DBUS_ENABLE_LAUNCHD
3584 char *argv[4];
3585 int i;
3586
3587 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3588
3589 if (_dbus_check_setuid ())
3590 {
3591 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3592 "Unable to find launchd socket when setuid");
3593 return FALSE;
3594 }
3595
3596 i = 0;
3597 argv[i] = "launchctl";
3598 ++i;
3599 argv[i] = "getenv";
3600 ++i;
3601 argv[i] = (char*)launchd_env_var;
3602 ++i;
3603 argv[i] = NULL;
3604 ++i;
3605
3606 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3607
3608 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
3609 {
3610 return FALSE;
3611 }
3612
3613 /* no error, but no result either */
3614 if (_dbus_string_get_length(socket_path) == 0)
3615 {
3616 return FALSE;
3617 }
3618
3619 /* strip the carriage-return */
3620 _dbus_string_shorten(socket_path, 1);
3621 return TRUE;
3622 #else /* DBUS_ENABLE_LAUNCHD */
3623 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
3624 "can't lookup socket from launchd; launchd support not compiled in");
3625 return FALSE;
3626 #endif
3627 }
3628
3629 #ifdef DBUS_ENABLE_LAUNCHD
3630 static dbus_bool_t
_dbus_lookup_session_address_launchd(DBusString * address,DBusError * error)3631 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
3632 {
3633 dbus_bool_t valid_socket;
3634 DBusString socket_path;
3635
3636 if (_dbus_check_setuid ())
3637 {
3638 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
3639 "Unable to find launchd socket when setuid");
3640 return FALSE;
3641 }
3642
3643 if (!_dbus_string_init (&socket_path))
3644 {
3645 _DBUS_SET_OOM (error);
3646 return FALSE;
3647 }
3648
3649 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
3650
3651 if (dbus_error_is_set(error))
3652 {
3653 _dbus_string_free(&socket_path);
3654 return FALSE;
3655 }
3656
3657 if (!valid_socket)
3658 {
3659 dbus_set_error(error, "no socket path",
3660 "launchd did not provide a socket path, "
3661 "verify that org.freedesktop.dbus-session.plist is loaded!");
3662 _dbus_string_free(&socket_path);
3663 return FALSE;
3664 }
3665 if (!_dbus_string_append (address, "unix:path="))
3666 {
3667 _DBUS_SET_OOM (error);
3668 _dbus_string_free(&socket_path);
3669 return FALSE;
3670 }
3671 if (!_dbus_string_copy (&socket_path, 0, address,
3672 _dbus_string_get_length (address)))
3673 {
3674 _DBUS_SET_OOM (error);
3675 _dbus_string_free(&socket_path);
3676 return FALSE;
3677 }
3678
3679 _dbus_string_free(&socket_path);
3680 return TRUE;
3681 }
3682 #endif
3683
3684 /**
3685 * Determines the address of the session bus by querying a
3686 * platform-specific method.
3687 *
3688 * The first parameter will be a boolean specifying whether
3689 * or not a dynamic session lookup is supported on this platform.
3690 *
3691 * If supported is TRUE and the return value is #TRUE, the
3692 * address will be appended to @p address.
3693 * If a failure happens, returns #FALSE and sets an error in
3694 * @p error.
3695 *
3696 * If supported is FALSE, ignore the return value.
3697 *
3698 * @param supported returns whether this method is supported
3699 * @param address a DBusString where the address can be stored
3700 * @param error a DBusError to store the error in case of failure
3701 * @returns #TRUE on success, #FALSE if an error happened
3702 */
3703 dbus_bool_t
_dbus_lookup_session_address(dbus_bool_t * supported,DBusString * address,DBusError * error)3704 _dbus_lookup_session_address (dbus_bool_t *supported,
3705 DBusString *address,
3706 DBusError *error)
3707 {
3708 #ifdef DBUS_ENABLE_LAUNCHD
3709 *supported = TRUE;
3710 return _dbus_lookup_session_address_launchd (address, error);
3711 #else
3712 /* On non-Mac Unix platforms, if the session address isn't already
3713 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
3714 * fall back to the autolaunch: global default; see
3715 * init_session_address in dbus/dbus-bus.c. */
3716 *supported = FALSE;
3717 return TRUE;
3718 #endif
3719 }
3720
3721 /**
3722 * Returns the standard directories for a session bus to look for service
3723 * activation files
3724 *
3725 * On UNIX this should be the standard xdg freedesktop.org data directories:
3726 *
3727 * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share}
3728 * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
3729 *
3730 * and
3731 *
3732 * DBUS_DATADIR
3733 *
3734 * @param dirs the directory list we are returning
3735 * @returns #FALSE on OOM
3736 */
3737
3738 dbus_bool_t
_dbus_get_standard_session_servicedirs(DBusList ** dirs)3739 _dbus_get_standard_session_servicedirs (DBusList **dirs)
3740 {
3741 const char *xdg_data_home;
3742 const char *xdg_data_dirs;
3743 DBusString servicedir_path;
3744
3745 if (!_dbus_string_init (&servicedir_path))
3746 return FALSE;
3747
3748 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
3749 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
3750
3751 if (xdg_data_home != NULL)
3752 {
3753 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
3754 goto oom;
3755 }
3756 else
3757 {
3758 const DBusString *homedir;
3759 DBusString local_share;
3760
3761 if (!_dbus_homedir_from_current_process (&homedir))
3762 goto oom;
3763
3764 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
3765 goto oom;
3766
3767 _dbus_string_init_const (&local_share, "/.local/share");
3768 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
3769 goto oom;
3770 }
3771
3772 if (!_dbus_string_append (&servicedir_path, ":"))
3773 goto oom;
3774
3775 if (xdg_data_dirs != NULL)
3776 {
3777 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
3778 goto oom;
3779
3780 if (!_dbus_string_append (&servicedir_path, ":"))
3781 goto oom;
3782 }
3783 else
3784 {
3785 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
3786 goto oom;
3787 }
3788
3789 /*
3790 * add configured datadir to defaults
3791 * this may be the same as an xdg dir
3792 * however the config parser should take
3793 * care of duplicates
3794 */
3795 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
3796 goto oom;
3797
3798 if (!_dbus_split_paths_and_append (&servicedir_path,
3799 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
3800 dirs))
3801 goto oom;
3802
3803 _dbus_string_free (&servicedir_path);
3804 return TRUE;
3805
3806 oom:
3807 _dbus_string_free (&servicedir_path);
3808 return FALSE;
3809 }
3810
3811
3812 /**
3813 * Returns the standard directories for a system bus to look for service
3814 * activation files
3815 *
3816 * On UNIX this should be the standard xdg freedesktop.org data directories:
3817 *
3818 * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
3819 *
3820 * and
3821 *
3822 * DBUS_DATADIR
3823 *
3824 * On Windows there is no system bus and this function can return nothing.
3825 *
3826 * @param dirs the directory list we are returning
3827 * @returns #FALSE on OOM
3828 */
3829
3830 dbus_bool_t
_dbus_get_standard_system_servicedirs(DBusList ** dirs)3831 _dbus_get_standard_system_servicedirs (DBusList **dirs)
3832 {
3833 /*
3834 * DBUS_DATADIR may be the same as one of the standard directories. However,
3835 * the config parser should take care of the duplicates.
3836 *
3837 * Also, append /lib as counterpart of /usr/share on the root
3838 * directory (the root directory does not know /share), in order to
3839 * facilitate early boot system bus activation where /usr might not
3840 * be available.
3841 */
3842 static const char standard_search_path[] =
3843 "/usr/local/share:"
3844 "/usr/share:"
3845 DBUS_DATADIR ":"
3846 "/lib";
3847 DBusString servicedir_path;
3848
3849 _dbus_string_init_const (&servicedir_path, standard_search_path);
3850
3851 return _dbus_split_paths_and_append (&servicedir_path,
3852 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
3853 dirs);
3854 }
3855
3856 /**
3857 * Append the absolute path of the system.conf file
3858 * (there is no system bus on Windows so this can just
3859 * return FALSE and print a warning or something)
3860 *
3861 * @param str the string to append to
3862 * @returns #FALSE if no memory
3863 */
3864 dbus_bool_t
_dbus_append_system_config_file(DBusString * str)3865 _dbus_append_system_config_file (DBusString *str)
3866 {
3867 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
3868 }
3869
3870 /**
3871 * Append the absolute path of the session.conf file.
3872 *
3873 * @param str the string to append to
3874 * @returns #FALSE if no memory
3875 */
3876 dbus_bool_t
_dbus_append_session_config_file(DBusString * str)3877 _dbus_append_session_config_file (DBusString *str)
3878 {
3879 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
3880 }
3881
3882 /**
3883 * Called when the bus daemon is signaled to reload its configuration; any
3884 * caches should be nuked. Of course any caches that need explicit reload
3885 * are probably broken, but c'est la vie.
3886 *
3887 *
3888 */
3889 void
_dbus_flush_caches(void)3890 _dbus_flush_caches (void)
3891 {
3892 _dbus_user_database_flush_system ();
3893 }
3894
3895 /**
3896 * Appends the directory in which a keyring for the given credentials
3897 * should be stored. The credentials should have either a Windows or
3898 * UNIX user in them. The directory should be an absolute path.
3899 *
3900 * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
3901 * be something else, since the dotfile convention is not normal on Windows.
3902 *
3903 * @param directory string to append directory to
3904 * @param credentials credentials the directory should be for
3905 *
3906 * @returns #FALSE on no memory
3907 */
3908 dbus_bool_t
_dbus_append_keyring_directory_for_credentials(DBusString * directory,DBusCredentials * credentials)3909 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
3910 DBusCredentials *credentials)
3911 {
3912 DBusString homedir;
3913 DBusString dotdir;
3914 dbus_uid_t uid;
3915
3916 _dbus_assert (credentials != NULL);
3917 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
3918
3919 if (!_dbus_string_init (&homedir))
3920 return FALSE;
3921
3922 uid = _dbus_credentials_get_unix_uid (credentials);
3923 _dbus_assert (uid != DBUS_UID_UNSET);
3924
3925 if (!_dbus_homedir_from_uid (uid, &homedir))
3926 goto failed;
3927
3928 #ifdef DBUS_BUILD_TESTS
3929 {
3930 const char *override;
3931
3932 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
3933 if (override != NULL && *override != '\0')
3934 {
3935 _dbus_string_set_length (&homedir, 0);
3936 if (!_dbus_string_append (&homedir, override))
3937 goto failed;
3938
3939 _dbus_verbose ("Using fake homedir for testing: %s\n",
3940 _dbus_string_get_const_data (&homedir));
3941 }
3942 else
3943 {
3944 static dbus_bool_t already_warned = FALSE;
3945 if (!already_warned)
3946 {
3947 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
3948 already_warned = TRUE;
3949 }
3950 }
3951 }
3952 #endif
3953
3954 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
3955 if (!_dbus_concat_dir_and_file (&homedir,
3956 &dotdir))
3957 goto failed;
3958
3959 if (!_dbus_string_copy (&homedir, 0,
3960 directory, _dbus_string_get_length (directory))) {
3961 goto failed;
3962 }
3963
3964 _dbus_string_free (&homedir);
3965 return TRUE;
3966
3967 failed:
3968 _dbus_string_free (&homedir);
3969 return FALSE;
3970 }
3971
3972 //PENDING(kdab) docs
3973 dbus_bool_t
_dbus_daemon_publish_session_bus_address(const char * addr,const char * scope)3974 _dbus_daemon_publish_session_bus_address (const char* addr,
3975 const char *scope)
3976 {
3977 return TRUE;
3978 }
3979
3980 //PENDING(kdab) docs
3981 void
_dbus_daemon_unpublish_session_bus_address(void)3982 _dbus_daemon_unpublish_session_bus_address (void)
3983 {
3984
3985 }
3986
3987 /**
3988 * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
3989 * for Winsock so is abstracted)
3990 *
3991 * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
3992 */
3993 dbus_bool_t
_dbus_get_is_errno_eagain_or_ewouldblock(void)3994 _dbus_get_is_errno_eagain_or_ewouldblock (void)
3995 {
3996 return errno == EAGAIN || errno == EWOULDBLOCK;
3997 }
3998
3999 /**
4000 * Removes a directory; Directory must be empty
4001 *
4002 * @param filename directory filename
4003 * @param error initialized error object
4004 * @returns #TRUE on success
4005 */
4006 dbus_bool_t
_dbus_delete_directory(const DBusString * filename,DBusError * error)4007 _dbus_delete_directory (const DBusString *filename,
4008 DBusError *error)
4009 {
4010 const char *filename_c;
4011
4012 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4013
4014 filename_c = _dbus_string_get_const_data (filename);
4015
4016 if (rmdir (filename_c) != 0)
4017 {
4018 dbus_set_error (error, DBUS_ERROR_FAILED,
4019 "Failed to remove directory %s: %s\n",
4020 filename_c, _dbus_strerror (errno));
4021 return FALSE;
4022 }
4023
4024 return TRUE;
4025 }
4026
4027 /**
4028 * Checks whether file descriptors may be passed via the socket
4029 *
4030 * @param fd the socket
4031 * @return TRUE when fd passing over this socket is supported
4032 *
4033 */
4034 dbus_bool_t
_dbus_socket_can_pass_unix_fd(int fd)4035 _dbus_socket_can_pass_unix_fd(int fd) {
4036
4037 #ifdef SCM_RIGHTS
4038 union {
4039 struct sockaddr sa;
4040 struct sockaddr_storage storage;
4041 struct sockaddr_un un;
4042 } sa_buf;
4043
4044 socklen_t sa_len = sizeof(sa_buf);
4045
4046 _DBUS_ZERO(sa_buf);
4047
4048 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
4049 return FALSE;
4050
4051 return sa_buf.sa.sa_family == AF_UNIX;
4052
4053 #else
4054 return FALSE;
4055
4056 #endif
4057 }
4058
4059
4060 /*
4061 * replaces the term DBUS_PREFIX in configure_time_path by the
4062 * current dbus installation directory. On unix this function is a noop
4063 *
4064 * @param configure_time_path
4065 * @return real path
4066 */
4067 const char *
_dbus_replace_install_prefix(const char * configure_time_path)4068 _dbus_replace_install_prefix (const char *configure_time_path)
4069 {
4070 return configure_time_path;
4071 }
4072
4073 /**
4074 * Closes all file descriptors except the first three (i.e. stdin,
4075 * stdout, stderr).
4076 */
4077 void
_dbus_close_all(void)4078 _dbus_close_all (void)
4079 {
4080 int maxfds, i;
4081
4082 #ifdef __linux__
4083 DIR *d;
4084
4085 /* On Linux we can optimize this a bit if /proc is available. If it
4086 isn't available, fall back to the brute force way. */
4087
4088 d = opendir ("/proc/self/fd");
4089 if (d)
4090 {
4091 for (;;)
4092 {
4093 struct dirent buf, *de;
4094 int k, fd;
4095 long l;
4096 char *e = NULL;
4097
4098 k = readdir_r (d, &buf, &de);
4099 if (k != 0 || !de)
4100 break;
4101
4102 if (de->d_name[0] == '.')
4103 continue;
4104
4105 errno = 0;
4106 l = strtol (de->d_name, &e, 10);
4107 if (errno != 0 || e == NULL || *e != '\0')
4108 continue;
4109
4110 fd = (int) l;
4111 if (fd < 3)
4112 continue;
4113
4114 if (fd == dirfd (d))
4115 continue;
4116
4117 close (fd);
4118 }
4119
4120 closedir (d);
4121 return;
4122 }
4123 #endif
4124
4125 maxfds = sysconf (_SC_OPEN_MAX);
4126
4127 /* Pick something reasonable if for some reason sysconf says
4128 * unlimited.
4129 */
4130 if (maxfds < 0)
4131 maxfds = 1024;
4132
4133 /* close all inherited fds */
4134 for (i = 3; i < maxfds; i++)
4135 close (i);
4136 }
4137
4138 /**
4139 * **NOTE**: If you modify this function, please also consider making
4140 * the corresponding change in GLib. See
4141 * glib/gutils.c:g_check_setuid().
4142 *
4143 * Returns TRUE if the current process was executed as setuid (or an
4144 * equivalent __libc_enable_secure is available). See:
4145 * http://osdir.com/ml/linux.lfs.hardened/2007-04/msg00032.html
4146 */
4147 dbus_bool_t
_dbus_check_setuid(void)4148 _dbus_check_setuid (void)
4149 {
4150 /* TODO: get __libc_enable_secure exported from glibc.
4151 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4152 */
4153 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4154 {
4155 /* See glibc/include/unistd.h */
4156 extern int __libc_enable_secure;
4157 return __libc_enable_secure;
4158 }
4159 #elif defined(HAVE_ISSETUGID)
4160 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4161 return issetugid ();
4162 #else
4163 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4164 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4165
4166 static dbus_bool_t check_setuid_initialised;
4167 static dbus_bool_t is_setuid;
4168
4169 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4170 {
4171 #ifdef HAVE_GETRESUID
4172 if (getresuid (&ruid, &euid, &suid) != 0 ||
4173 getresgid (&rgid, &egid, &sgid) != 0)
4174 #endif /* HAVE_GETRESUID */
4175 {
4176 suid = ruid = getuid ();
4177 sgid = rgid = getgid ();
4178 euid = geteuid ();
4179 egid = getegid ();
4180 }
4181
4182 check_setuid_initialised = TRUE;
4183 is_setuid = (ruid != euid || ruid != suid ||
4184 rgid != egid || rgid != sgid);
4185
4186 }
4187 return is_setuid;
4188 #endif
4189 }
4190
4191 /* tests in dbus-sysdeps-util.c */
4192