1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-util-unix.c Would be in dbus-sysdeps-unix.c, but not used in libdbus
3 *
4 * Copyright (C) 2002, 2003, 2004, 2005 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 #include "dbus-sysdeps.h"
27 #include "dbus-sysdeps-unix.h"
28 #include "dbus-internals.h"
29 #include "dbus-pipe.h"
30 #include "dbus-protocol.h"
31 #include "dbus-string.h"
32 #define DBUS_USERDB_INCLUDES_PRIVATE 1
33 #include "dbus-userdb.h"
34 #include "dbus-test.h"
35
36 #include <sys/types.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <signal.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include <grp.h>
46 #include <sys/socket.h>
47 #include <dirent.h>
48 #include <sys/un.h>
49 #include <syslog.h>
50
51 #ifdef HAVE_SYS_SYSLIMITS_H
52 #include <sys/syslimits.h>
53 #endif
54
55 #ifndef O_BINARY
56 #define O_BINARY 0
57 #endif
58
59 /**
60 * @addtogroup DBusInternalsUtils
61 * @{
62 */
63
64
65 /**
66 * Does the chdir, fork, setsid, etc. to become a daemon process.
67 *
68 * @param pidfile #NULL, or pidfile to create
69 * @param print_pid_pipe pipe to print daemon's pid to, or -1 for none
70 * @param error return location for errors
71 * @param keep_umask #TRUE to keep the original umask
72 * @returns #FALSE on failure
73 */
74 dbus_bool_t
_dbus_become_daemon(const DBusString * pidfile,DBusPipe * print_pid_pipe,DBusError * error,dbus_bool_t keep_umask)75 _dbus_become_daemon (const DBusString *pidfile,
76 DBusPipe *print_pid_pipe,
77 DBusError *error,
78 dbus_bool_t keep_umask)
79 {
80 const char *s;
81 pid_t child_pid;
82 int dev_null_fd;
83
84 _dbus_verbose ("Becoming a daemon...\n");
85
86 _dbus_verbose ("chdir to /\n");
87 if (chdir ("/") < 0)
88 {
89 dbus_set_error (error, DBUS_ERROR_FAILED,
90 "Could not chdir() to root directory");
91 return FALSE;
92 }
93
94 _dbus_verbose ("forking...\n");
95 switch ((child_pid = fork ()))
96 {
97 case -1:
98 _dbus_verbose ("fork failed\n");
99 dbus_set_error (error, _dbus_error_from_errno (errno),
100 "Failed to fork daemon: %s", _dbus_strerror (errno));
101 return FALSE;
102 break;
103
104 case 0:
105 _dbus_verbose ("in child, closing std file descriptors\n");
106
107 /* silently ignore failures here, if someone
108 * doesn't have /dev/null we may as well try
109 * to continue anyhow
110 */
111
112 dev_null_fd = open ("/dev/null", O_RDWR);
113 if (dev_null_fd >= 0)
114 {
115 dup2 (dev_null_fd, 0);
116 dup2 (dev_null_fd, 1);
117
118 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
119 if (s == NULL || *s == '\0')
120 dup2 (dev_null_fd, 2);
121 else
122 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
123 }
124
125 if (!keep_umask)
126 {
127 /* Get a predictable umask */
128 _dbus_verbose ("setting umask\n");
129 umask (022);
130 }
131
132 _dbus_verbose ("calling setsid()\n");
133 if (setsid () == -1)
134 _dbus_assert_not_reached ("setsid() failed");
135
136 break;
137
138 default:
139 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
140 child_pid, error))
141 {
142 _dbus_verbose ("pid file or pipe write failed: %s\n",
143 error->message);
144 kill (child_pid, SIGTERM);
145 return FALSE;
146 }
147
148 _dbus_verbose ("parent exiting\n");
149 _exit (0);
150 break;
151 }
152
153 return TRUE;
154 }
155
156
157 /**
158 * Creates a file containing the process ID.
159 *
160 * @param filename the filename to write to
161 * @param pid our process ID
162 * @param error return location for errors
163 * @returns #FALSE on failure
164 */
165 static dbus_bool_t
_dbus_write_pid_file(const DBusString * filename,unsigned long pid,DBusError * error)166 _dbus_write_pid_file (const DBusString *filename,
167 unsigned long pid,
168 DBusError *error)
169 {
170 const char *cfilename;
171 int fd;
172 FILE *f;
173
174 cfilename = _dbus_string_get_const_data (filename);
175
176 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
177
178 if (fd < 0)
179 {
180 dbus_set_error (error, _dbus_error_from_errno (errno),
181 "Failed to open \"%s\": %s", cfilename,
182 _dbus_strerror (errno));
183 return FALSE;
184 }
185
186 if ((f = fdopen (fd, "w")) == NULL)
187 {
188 dbus_set_error (error, _dbus_error_from_errno (errno),
189 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
190 _dbus_close (fd, NULL);
191 return FALSE;
192 }
193
194 if (fprintf (f, "%lu\n", pid) < 0)
195 {
196 dbus_set_error (error, _dbus_error_from_errno (errno),
197 "Failed to write to \"%s\": %s", cfilename,
198 _dbus_strerror (errno));
199
200 fclose (f);
201 return FALSE;
202 }
203
204 if (fclose (f) == EOF)
205 {
206 dbus_set_error (error, _dbus_error_from_errno (errno),
207 "Failed to close \"%s\": %s", cfilename,
208 _dbus_strerror (errno));
209 return FALSE;
210 }
211
212 return TRUE;
213 }
214
215 /**
216 * Writes the given pid_to_write to a pidfile (if non-NULL) and/or to a
217 * pipe (if non-NULL). Does nothing if pidfile and print_pid_pipe are both
218 * NULL.
219 *
220 * @param pidfile the file to write to or #NULL
221 * @param print_pid_pipe the pipe to write to or #NULL
222 * @param pid_to_write the pid to write out
223 * @param error error on failure
224 * @returns FALSE if error is set
225 */
226 dbus_bool_t
_dbus_write_pid_to_file_and_pipe(const DBusString * pidfile,DBusPipe * print_pid_pipe,dbus_pid_t pid_to_write,DBusError * error)227 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
228 DBusPipe *print_pid_pipe,
229 dbus_pid_t pid_to_write,
230 DBusError *error)
231 {
232 if (pidfile)
233 {
234 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
235 if (!_dbus_write_pid_file (pidfile,
236 pid_to_write,
237 error))
238 {
239 _dbus_verbose ("pid file write failed\n");
240 _DBUS_ASSERT_ERROR_IS_SET(error);
241 return FALSE;
242 }
243 }
244 else
245 {
246 _dbus_verbose ("No pid file requested\n");
247 }
248
249 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
250 {
251 DBusString pid;
252 int bytes;
253
254 _dbus_verbose ("writing our pid to pipe %"PRIuPTR"\n",
255 print_pid_pipe->fd_or_handle);
256
257 if (!_dbus_string_init (&pid))
258 {
259 _DBUS_SET_OOM (error);
260 return FALSE;
261 }
262
263 if (!_dbus_string_append_int (&pid, pid_to_write) ||
264 !_dbus_string_append (&pid, "\n"))
265 {
266 _dbus_string_free (&pid);
267 _DBUS_SET_OOM (error);
268 return FALSE;
269 }
270
271 bytes = _dbus_string_get_length (&pid);
272 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
273 {
274 /* _dbus_pipe_write sets error only on failure, not short write */
275 if (error != NULL && !dbus_error_is_set(error))
276 {
277 dbus_set_error (error, DBUS_ERROR_FAILED,
278 "Printing message bus PID: did not write enough bytes\n");
279 }
280 _dbus_string_free (&pid);
281 return FALSE;
282 }
283
284 _dbus_string_free (&pid);
285 }
286 else
287 {
288 _dbus_verbose ("No pid pipe to write to\n");
289 }
290
291 return TRUE;
292 }
293
294 /**
295 * Verify that after the fork we can successfully change to this user.
296 *
297 * @param user the username given in the daemon configuration
298 * @returns #TRUE if username is valid
299 */
300 dbus_bool_t
_dbus_verify_daemon_user(const char * user)301 _dbus_verify_daemon_user (const char *user)
302 {
303 DBusString u;
304
305 _dbus_string_init_const (&u, user);
306
307 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
308 }
309
310
311 /* The HAVE_LIBAUDIT case lives in selinux.c */
312 #ifndef HAVE_LIBAUDIT
313 /**
314 * Changes the user and group the bus is running as.
315 *
316 * @param user the user to become
317 * @param error return location for errors
318 * @returns #FALSE on failure
319 */
320 dbus_bool_t
_dbus_change_to_daemon_user(const char * user,DBusError * error)321 _dbus_change_to_daemon_user (const char *user,
322 DBusError *error)
323 {
324 dbus_uid_t uid;
325 dbus_gid_t gid;
326 DBusString u;
327
328 _dbus_string_init_const (&u, user);
329
330 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
331 {
332 dbus_set_error (error, DBUS_ERROR_FAILED,
333 "User '%s' does not appear to exist?",
334 user);
335 return FALSE;
336 }
337
338 /* setgroups() only works if we are a privileged process,
339 * so we don't return error on failure; the only possible
340 * failure is that we don't have perms to do it.
341 *
342 * not sure this is right, maybe if setuid()
343 * is going to work then setgroups() should also work.
344 */
345 if (setgroups (0, NULL) < 0)
346 _dbus_warn ("Failed to drop supplementary groups: %s\n",
347 _dbus_strerror (errno));
348
349 /* Set GID first, or the setuid may remove our permission
350 * to change the GID
351 */
352 if (setgid (gid) < 0)
353 {
354 dbus_set_error (error, _dbus_error_from_errno (errno),
355 "Failed to set GID to %lu: %s", gid,
356 _dbus_strerror (errno));
357 return FALSE;
358 }
359
360 if (setuid (uid) < 0)
361 {
362 dbus_set_error (error, _dbus_error_from_errno (errno),
363 "Failed to set UID to %lu: %s", uid,
364 _dbus_strerror (errno));
365 return FALSE;
366 }
367
368 return TRUE;
369 }
370 #endif /* !HAVE_LIBAUDIT */
371
372 void
_dbus_init_system_log(void)373 _dbus_init_system_log (void)
374 {
375 openlog ("dbus", LOG_PID, LOG_DAEMON);
376 }
377 /**
378 * Log a message to the system log file (e.g. syslog on Unix).
379 *
380 * @param severity a severity value
381 * @param msg a printf-style format string
382 * @param args arguments for the format string
383 *
384 */
385 void
_dbus_system_log(DBusSystemLogSeverity severity,const char * msg,...)386 _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
387 {
388 va_list args;
389
390 va_start (args, msg);
391
392 _dbus_system_logv (severity, msg, args);
393
394 va_end (args);
395 }
396
397 /**
398 * Log a message to the system log file (e.g. syslog on Unix).
399 *
400 * @param severity a severity value
401 * @param msg a printf-style format string
402 * @param args arguments for the format string
403 *
404 * If the FATAL severity is given, this function will terminate the program
405 * with an error code.
406 */
407 void
_dbus_system_logv(DBusSystemLogSeverity severity,const char * msg,va_list args)408 _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
409 {
410 int flags;
411 switch (severity)
412 {
413 case DBUS_SYSTEM_LOG_INFO:
414 flags = LOG_DAEMON | LOG_NOTICE;
415 break;
416 case DBUS_SYSTEM_LOG_SECURITY:
417 flags = LOG_AUTH | LOG_NOTICE;
418 break;
419 case DBUS_SYSTEM_LOG_FATAL:
420 flags = LOG_DAEMON|LOG_CRIT;
421 default:
422 return;
423 }
424
425 vsyslog (flags, msg, args);
426
427 if (severity == DBUS_SYSTEM_LOG_FATAL)
428 exit (1);
429 }
430
431 /** Installs a UNIX signal handler
432 *
433 * @param sig the signal to handle
434 * @param handler the handler
435 */
436 void
_dbus_set_signal_handler(int sig,DBusSignalHandler handler)437 _dbus_set_signal_handler (int sig,
438 DBusSignalHandler handler)
439 {
440 struct sigaction act;
441 sigset_t empty_mask;
442
443 sigemptyset (&empty_mask);
444 act.sa_handler = handler;
445 act.sa_mask = empty_mask;
446 act.sa_flags = 0;
447 sigaction (sig, &act, NULL);
448 }
449
450 /** Checks if a file exists
451 *
452 * @param file full path to the file
453 * @returns #TRUE if file exists
454 */
455 dbus_bool_t
_dbus_file_exists(const char * file)456 _dbus_file_exists (const char *file)
457 {
458 return (access (file, F_OK) == 0);
459 }
460
461 /** Checks if user is at the console
462 *
463 * @param username user to check
464 * @param error return location for errors
465 * @returns #TRUE is the user is at the consolei and there are no errors
466 */
467 dbus_bool_t
_dbus_user_at_console(const char * username,DBusError * error)468 _dbus_user_at_console (const char *username,
469 DBusError *error)
470 {
471
472 DBusString f;
473 dbus_bool_t result;
474
475 result = FALSE;
476 if (!_dbus_string_init (&f))
477 {
478 _DBUS_SET_OOM (error);
479 return FALSE;
480 }
481
482 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
483 {
484 _DBUS_SET_OOM (error);
485 goto out;
486 }
487
488
489 if (!_dbus_string_append (&f, username))
490 {
491 _DBUS_SET_OOM (error);
492 goto out;
493 }
494
495 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
496
497 out:
498 _dbus_string_free (&f);
499
500 return result;
501 }
502
503
504 /**
505 * Checks whether the filename is an absolute path
506 *
507 * @param filename the filename
508 * @returns #TRUE if an absolute path
509 */
510 dbus_bool_t
_dbus_path_is_absolute(const DBusString * filename)511 _dbus_path_is_absolute (const DBusString *filename)
512 {
513 if (_dbus_string_get_length (filename) > 0)
514 return _dbus_string_get_byte (filename, 0) == '/';
515 else
516 return FALSE;
517 }
518
519 /**
520 * stat() wrapper.
521 *
522 * @param filename the filename to stat
523 * @param statbuf the stat info to fill in
524 * @param error return location for error
525 * @returns #FALSE if error was set
526 */
527 dbus_bool_t
_dbus_stat(const DBusString * filename,DBusStat * statbuf,DBusError * error)528 _dbus_stat (const DBusString *filename,
529 DBusStat *statbuf,
530 DBusError *error)
531 {
532 const char *filename_c;
533 struct stat sb;
534
535 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
536
537 filename_c = _dbus_string_get_const_data (filename);
538
539 if (stat (filename_c, &sb) < 0)
540 {
541 dbus_set_error (error, _dbus_error_from_errno (errno),
542 "%s", _dbus_strerror (errno));
543 return FALSE;
544 }
545
546 statbuf->mode = sb.st_mode;
547 statbuf->nlink = sb.st_nlink;
548 statbuf->uid = sb.st_uid;
549 statbuf->gid = sb.st_gid;
550 statbuf->size = sb.st_size;
551 statbuf->atime = sb.st_atime;
552 statbuf->mtime = sb.st_mtime;
553 statbuf->ctime = sb.st_ctime;
554
555 return TRUE;
556 }
557
558
559 /**
560 * Internals of directory iterator
561 */
562 struct DBusDirIter
563 {
564 DIR *d; /**< The DIR* from opendir() */
565
566 };
567
568 /**
569 * Open a directory to iterate over.
570 *
571 * @param filename the directory name
572 * @param error exception return object or #NULL
573 * @returns new iterator, or #NULL on error
574 */
575 DBusDirIter*
_dbus_directory_open(const DBusString * filename,DBusError * error)576 _dbus_directory_open (const DBusString *filename,
577 DBusError *error)
578 {
579 DIR *d;
580 DBusDirIter *iter;
581 const char *filename_c;
582
583 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
584
585 filename_c = _dbus_string_get_const_data (filename);
586
587 d = opendir (filename_c);
588 if (d == NULL)
589 {
590 dbus_set_error (error, _dbus_error_from_errno (errno),
591 "Failed to read directory \"%s\": %s",
592 filename_c,
593 _dbus_strerror (errno));
594 return NULL;
595 }
596 iter = dbus_new0 (DBusDirIter, 1);
597 if (iter == NULL)
598 {
599 closedir (d);
600 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
601 "Could not allocate memory for directory iterator");
602 return NULL;
603 }
604
605 iter->d = d;
606
607 return iter;
608 }
609
610 /* it is never safe to retrun a size smaller than sizeof(struct dirent)
611 * because the libc *could* try to access the whole structure
612 * (for instance it could try to memset it).
613 * it is also incorrect to return a size bigger than that, because
614 * the libc would never use it.
615 * The only correct and safe value this function can ever return is
616 * sizeof(struct dirent).
617 */
618 static dbus_bool_t
dirent_buf_size(DIR * dirp,size_t * size)619 dirent_buf_size(DIR * dirp, size_t *size)
620 {
621 *size = sizeof(struct dirent);
622 return TRUE;
623 }
624
625 /**
626 * Get next file in the directory. Will not return "." or ".." on
627 * UNIX. If an error occurs, the contents of "filename" are
628 * undefined. The error is never set if the function succeeds.
629 *
630 * @param iter the iterator
631 * @param filename string to be set to the next file in the dir
632 * @param error return location for error
633 * @returns #TRUE if filename was filled in with a new filename
634 */
635 dbus_bool_t
_dbus_directory_get_next_file(DBusDirIter * iter,DBusString * filename,DBusError * error)636 _dbus_directory_get_next_file (DBusDirIter *iter,
637 DBusString *filename,
638 DBusError *error)
639 {
640 struct dirent *d, *ent;
641 size_t buf_size;
642 int err;
643
644 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
645
646 if (!dirent_buf_size (iter->d, &buf_size))
647 {
648 dbus_set_error (error, DBUS_ERROR_FAILED,
649 "Can't calculate buffer size when reading directory");
650 return FALSE;
651 }
652
653 d = (struct dirent *)dbus_malloc (buf_size);
654 if (!d)
655 {
656 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
657 "No memory to read directory entry");
658 return FALSE;
659 }
660
661 again:
662 err = readdir_r (iter->d, d, &ent);
663 if (err || !ent)
664 {
665 if (err != 0)
666 dbus_set_error (error,
667 _dbus_error_from_errno (err),
668 "%s", _dbus_strerror (err));
669
670 dbus_free (d);
671 return FALSE;
672 }
673 else if (ent->d_name[0] == '.' &&
674 (ent->d_name[1] == '\0' ||
675 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
676 goto again;
677 else
678 {
679 _dbus_string_set_length (filename, 0);
680 if (!_dbus_string_append (filename, ent->d_name))
681 {
682 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
683 "No memory to read directory entry");
684 dbus_free (d);
685 return FALSE;
686 }
687 else
688 {
689 dbus_free (d);
690 return TRUE;
691 }
692 }
693 }
694
695 /**
696 * Closes a directory iteration.
697 */
698 void
_dbus_directory_close(DBusDirIter * iter)699 _dbus_directory_close (DBusDirIter *iter)
700 {
701 closedir (iter->d);
702 dbus_free (iter);
703 }
704
705 static dbus_bool_t
fill_user_info_from_group(struct group * g,DBusGroupInfo * info,DBusError * error)706 fill_user_info_from_group (struct group *g,
707 DBusGroupInfo *info,
708 DBusError *error)
709 {
710 _dbus_assert (g->gr_name != NULL);
711
712 info->gid = g->gr_gid;
713 info->groupname = _dbus_strdup (g->gr_name);
714
715 /* info->members = dbus_strdupv (g->gr_mem) */
716
717 if (info->groupname == NULL)
718 {
719 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
720 return FALSE;
721 }
722
723 return TRUE;
724 }
725
726 static dbus_bool_t
fill_group_info(DBusGroupInfo * info,dbus_gid_t gid,const DBusString * groupname,DBusError * error)727 fill_group_info (DBusGroupInfo *info,
728 dbus_gid_t gid,
729 const DBusString *groupname,
730 DBusError *error)
731 {
732 const char *group_c_str;
733
734 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
735 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
736
737 if (groupname)
738 group_c_str = _dbus_string_get_const_data (groupname);
739 else
740 group_c_str = NULL;
741
742 /* For now assuming that the getgrnam() and getgrgid() flavors
743 * always correspond to the pwnam flavors, if not we have
744 * to add more configure checks.
745 */
746
747 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
748 {
749 struct group *g;
750 int result;
751 size_t buflen;
752 char *buf;
753 struct group g_str;
754 dbus_bool_t b;
755
756 /* retrieve maximum needed size for buf */
757 buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
758
759 /* sysconf actually returns a long, but everything else expects size_t,
760 * so just recast here.
761 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
762 */
763 if ((long) buflen <= 0)
764 buflen = 1024;
765
766 result = -1;
767 while (1)
768 {
769 buf = dbus_malloc (buflen);
770 if (buf == NULL)
771 {
772 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
773 return FALSE;
774 }
775
776 g = NULL;
777 #ifdef HAVE_POSIX_GETPWNAM_R
778 if (group_c_str)
779 result = getgrnam_r (group_c_str, &g_str, buf, buflen,
780 &g);
781 else
782 result = getgrgid_r (gid, &g_str, buf, buflen,
783 &g);
784 #else
785 g = getgrnam_r (group_c_str, &g_str, buf, buflen);
786 result = 0;
787 #endif /* !HAVE_POSIX_GETPWNAM_R */
788 /* Try a bigger buffer if ERANGE was returned:
789 https://bugs.freedesktop.org/show_bug.cgi?id=16727
790 */
791 if (result == ERANGE && buflen < 512 * 1024)
792 {
793 dbus_free (buf);
794 buflen *= 2;
795 }
796 else
797 {
798 break;
799 }
800 }
801
802 if (result == 0 && g == &g_str)
803 {
804 b = fill_user_info_from_group (g, info, error);
805 dbus_free (buf);
806 return b;
807 }
808 else
809 {
810 dbus_set_error (error, _dbus_error_from_errno (errno),
811 "Group %s unknown or failed to look it up\n",
812 group_c_str ? group_c_str : "???");
813 dbus_free (buf);
814 return FALSE;
815 }
816 }
817 #else /* ! HAVE_GETPWNAM_R */
818 {
819 /* I guess we're screwed on thread safety here */
820 struct group *g;
821
822 g = getgrnam (group_c_str);
823
824 if (g != NULL)
825 {
826 return fill_user_info_from_group (g, info, error);
827 }
828 else
829 {
830 dbus_set_error (error, _dbus_error_from_errno (errno),
831 "Group %s unknown or failed to look it up\n",
832 group_c_str ? group_c_str : "???");
833 return FALSE;
834 }
835 }
836 #endif /* ! HAVE_GETPWNAM_R */
837 }
838
839 /**
840 * Initializes the given DBusGroupInfo struct
841 * with information about the given group name.
842 *
843 * @param info the group info struct
844 * @param groupname name of group
845 * @param error the error return
846 * @returns #FALSE if error is set
847 */
848 dbus_bool_t
_dbus_group_info_fill(DBusGroupInfo * info,const DBusString * groupname,DBusError * error)849 _dbus_group_info_fill (DBusGroupInfo *info,
850 const DBusString *groupname,
851 DBusError *error)
852 {
853 return fill_group_info (info, DBUS_GID_UNSET,
854 groupname, error);
855
856 }
857
858 /**
859 * Initializes the given DBusGroupInfo struct
860 * with information about the given group ID.
861 *
862 * @param info the group info struct
863 * @param gid group ID
864 * @param error the error return
865 * @returns #FALSE if error is set
866 */
867 dbus_bool_t
_dbus_group_info_fill_gid(DBusGroupInfo * info,dbus_gid_t gid,DBusError * error)868 _dbus_group_info_fill_gid (DBusGroupInfo *info,
869 dbus_gid_t gid,
870 DBusError *error)
871 {
872 return fill_group_info (info, gid, NULL, error);
873 }
874
875 /**
876 * Parse a UNIX user from the bus config file. On Windows, this should
877 * simply always fail (just return #FALSE).
878 *
879 * @param username the username text
880 * @param uid_p place to return the uid
881 * @returns #TRUE on success
882 */
883 dbus_bool_t
_dbus_parse_unix_user_from_config(const DBusString * username,dbus_uid_t * uid_p)884 _dbus_parse_unix_user_from_config (const DBusString *username,
885 dbus_uid_t *uid_p)
886 {
887 return _dbus_get_user_id (username, uid_p);
888
889 }
890
891 /**
892 * Parse a UNIX group from the bus config file. On Windows, this should
893 * simply always fail (just return #FALSE).
894 *
895 * @param groupname the groupname text
896 * @param gid_p place to return the gid
897 * @returns #TRUE on success
898 */
899 dbus_bool_t
_dbus_parse_unix_group_from_config(const DBusString * groupname,dbus_gid_t * gid_p)900 _dbus_parse_unix_group_from_config (const DBusString *groupname,
901 dbus_gid_t *gid_p)
902 {
903 return _dbus_get_group_id (groupname, gid_p);
904 }
905
906 /**
907 * Gets all groups corresponding to the given UNIX user ID. On UNIX,
908 * just calls _dbus_groups_from_uid(). On Windows, should always
909 * fail since we don't know any UNIX groups.
910 *
911 * @param uid the UID
912 * @param group_ids return location for array of group IDs
913 * @param n_group_ids return location for length of returned array
914 * @returns #TRUE if the UID existed and we got some credentials
915 */
916 dbus_bool_t
_dbus_unix_groups_from_uid(dbus_uid_t uid,dbus_gid_t ** group_ids,int * n_group_ids)917 _dbus_unix_groups_from_uid (dbus_uid_t uid,
918 dbus_gid_t **group_ids,
919 int *n_group_ids)
920 {
921 return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
922 }
923
924 /**
925 * Checks to see if the UNIX user ID is at the console.
926 * Should always fail on Windows (set the error to
927 * #DBUS_ERROR_NOT_SUPPORTED).
928 *
929 * @param uid UID of person to check
930 * @param error return location for errors
931 * @returns #TRUE if the UID is the same as the console user and there are no errors
932 */
933 dbus_bool_t
_dbus_unix_user_is_at_console(dbus_uid_t uid,DBusError * error)934 _dbus_unix_user_is_at_console (dbus_uid_t uid,
935 DBusError *error)
936 {
937 return _dbus_is_console_user (uid, error);
938
939 }
940
941 /**
942 * Checks to see if the UNIX user ID matches the UID of
943 * the process. Should always return #FALSE on Windows.
944 *
945 * @param uid the UNIX user ID
946 * @returns #TRUE if this uid owns the process.
947 */
948 dbus_bool_t
_dbus_unix_user_is_process_owner(dbus_uid_t uid)949 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
950 {
951 return uid == _dbus_geteuid ();
952 }
953
954 /**
955 * Checks to see if the Windows user SID matches the owner of
956 * the process. Should always return #FALSE on UNIX.
957 *
958 * @param windows_sid the Windows user SID
959 * @returns #TRUE if this user owns the process.
960 */
961 dbus_bool_t
_dbus_windows_user_is_process_owner(const char * windows_sid)962 _dbus_windows_user_is_process_owner (const char *windows_sid)
963 {
964 return FALSE;
965 }
966
967 /** @} */ /* End of DBusInternalsUtils functions */
968
969 /**
970 * @addtogroup DBusString
971 *
972 * @{
973 */
974 /**
975 * Get the directory name from a complete filename
976 * @param filename the filename
977 * @param dirname string to append directory name to
978 * @returns #FALSE if no memory
979 */
980 dbus_bool_t
_dbus_string_get_dirname(const DBusString * filename,DBusString * dirname)981 _dbus_string_get_dirname (const DBusString *filename,
982 DBusString *dirname)
983 {
984 int sep;
985
986 _dbus_assert (filename != dirname);
987 _dbus_assert (filename != NULL);
988 _dbus_assert (dirname != NULL);
989
990 /* Ignore any separators on the end */
991 sep = _dbus_string_get_length (filename);
992 if (sep == 0)
993 return _dbus_string_append (dirname, "."); /* empty string passed in */
994
995 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
996 --sep;
997
998 _dbus_assert (sep >= 0);
999
1000 if (sep == 0)
1001 return _dbus_string_append (dirname, "/");
1002
1003 /* Now find the previous separator */
1004 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
1005 if (sep < 0)
1006 return _dbus_string_append (dirname, ".");
1007
1008 /* skip multiple separators */
1009 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
1010 --sep;
1011
1012 _dbus_assert (sep >= 0);
1013
1014 if (sep == 0 &&
1015 _dbus_string_get_byte (filename, 0) == '/')
1016 return _dbus_string_append (dirname, "/");
1017 else
1018 return _dbus_string_copy_len (filename, 0, sep - 0,
1019 dirname, _dbus_string_get_length (dirname));
1020 }
1021 /** @} */ /* DBusString stuff */
1022
1023 static void
string_squash_nonprintable(DBusString * str)1024 string_squash_nonprintable (DBusString *str)
1025 {
1026 unsigned char *buf;
1027 int i, len;
1028
1029 buf = _dbus_string_get_data (str);
1030 len = _dbus_string_get_length (str);
1031
1032 for (i = 0; i < len; i++)
1033 {
1034 unsigned char c = (unsigned char) buf[i];
1035 if (c == '\0')
1036 c = ' ';
1037 else if (c < 0x20 || c > 127)
1038 c = '?';
1039 }
1040 }
1041
1042 /**
1043 * Get a printable string describing the command used to execute
1044 * the process with pid. This string should only be used for
1045 * informative purposes such as logging; it may not be trusted.
1046 *
1047 * The command is guaranteed to be printable ASCII and no longer
1048 * than max_len.
1049 *
1050 * @param pid Process id
1051 * @param str Append command to this string
1052 * @param max_len Maximum length of returned command
1053 * @param error return location for errors
1054 * @returns #FALSE on error
1055 */
1056 dbus_bool_t
_dbus_command_for_pid(unsigned long pid,DBusString * str,int max_len,DBusError * error)1057 _dbus_command_for_pid (unsigned long pid,
1058 DBusString *str,
1059 int max_len,
1060 DBusError *error)
1061 {
1062 /* This is all Linux-specific for now */
1063 DBusString path;
1064 DBusString cmdline;
1065 int fd;
1066
1067 if (!_dbus_string_init (&path))
1068 {
1069 _DBUS_SET_OOM (error);
1070 return FALSE;
1071 }
1072
1073 if (!_dbus_string_init (&cmdline))
1074 {
1075 _DBUS_SET_OOM (error);
1076 _dbus_string_free (&path);
1077 return FALSE;
1078 }
1079
1080 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
1081 goto oom;
1082
1083 fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
1084 if (fd < 0)
1085 {
1086 dbus_set_error (error,
1087 _dbus_error_from_errno (errno),
1088 "Failed to open \"%s\": %s",
1089 _dbus_string_get_const_data (&path),
1090 _dbus_strerror (errno));
1091 goto fail;
1092 }
1093
1094 if (!_dbus_read (fd, &cmdline, max_len))
1095 {
1096 dbus_set_error (error,
1097 _dbus_error_from_errno (errno),
1098 "Failed to read from \"%s\": %s",
1099 _dbus_string_get_const_data (&path),
1100 _dbus_strerror (errno));
1101 goto fail;
1102 }
1103
1104 if (!_dbus_close (fd, error))
1105 goto fail;
1106
1107 string_squash_nonprintable (&cmdline);
1108
1109 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
1110 goto oom;
1111
1112 _dbus_string_free (&cmdline);
1113 _dbus_string_free (&path);
1114 return TRUE;
1115 oom:
1116 _DBUS_SET_OOM (error);
1117 fail:
1118 _dbus_string_free (&cmdline);
1119 _dbus_string_free (&path);
1120 return FALSE;
1121 }
1122