D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-sysdeps-util-unix.c Would be in dbus-sysdeps-unix.c, but not used in libdbus 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 #include "dbus-sysdeps.h" 00027 #include "dbus-sysdeps-unix.h" 00028 #include "dbus-internals.h" 00029 #include "dbus-pipe.h" 00030 #include "dbus-protocol.h" 00031 #include "dbus-string.h" 00032 #define DBUS_USERDB_INCLUDES_PRIVATE 1 00033 #include "dbus-userdb.h" 00034 #include "dbus-test.h" 00035 00036 #include <sys/types.h> 00037 #include <stdlib.h> 00038 #include <string.h> 00039 #include <signal.h> 00040 #include <unistd.h> 00041 #include <stdio.h> 00042 #include <errno.h> 00043 #include <fcntl.h> 00044 #include <sys/stat.h> 00045 #ifdef HAVE_SYS_RESOURCE_H 00046 #include <sys/resource.h> 00047 #endif 00048 #include <grp.h> 00049 #include <sys/socket.h> 00050 #include <dirent.h> 00051 #include <sys/un.h> 00052 00053 #ifdef HAVE_SYSLOG_H 00054 #include <syslog.h> 00055 #endif 00056 00057 #ifdef HAVE_SYS_SYSLIMITS_H 00058 #include <sys/syslimits.h> 00059 #endif 00060 00061 #ifdef HAVE_SYSTEMD 00062 #include <systemd/sd-daemon.h> 00063 #endif 00064 00065 #ifndef O_BINARY 00066 #define O_BINARY 0 00067 #endif 00068 00084 dbus_bool_t 00085 _dbus_become_daemon (const DBusString *pidfile, 00086 DBusPipe *print_pid_pipe, 00087 DBusError *error, 00088 dbus_bool_t keep_umask) 00089 { 00090 const char *s; 00091 pid_t child_pid; 00092 int dev_null_fd; 00093 00094 _dbus_verbose ("Becoming a daemon...\n"); 00095 00096 _dbus_verbose ("chdir to /\n"); 00097 if (chdir ("/") < 0) 00098 { 00099 dbus_set_error (error, DBUS_ERROR_FAILED, 00100 "Could not chdir() to root directory"); 00101 return FALSE; 00102 } 00103 00104 _dbus_verbose ("forking...\n"); 00105 switch ((child_pid = fork ())) 00106 { 00107 case -1: 00108 _dbus_verbose ("fork failed\n"); 00109 dbus_set_error (error, _dbus_error_from_errno (errno), 00110 "Failed to fork daemon: %s", _dbus_strerror (errno)); 00111 return FALSE; 00112 break; 00113 00114 case 0: 00115 _dbus_verbose ("in child, closing std file descriptors\n"); 00116 00117 /* silently ignore failures here, if someone 00118 * doesn't have /dev/null we may as well try 00119 * to continue anyhow 00120 */ 00121 00122 dev_null_fd = open ("/dev/null", O_RDWR); 00123 if (dev_null_fd >= 0) 00124 { 00125 dup2 (dev_null_fd, 0); 00126 dup2 (dev_null_fd, 1); 00127 00128 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT"); 00129 if (s == NULL || *s == '\0') 00130 dup2 (dev_null_fd, 2); 00131 else 00132 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n"); 00133 close (dev_null_fd); 00134 } 00135 00136 if (!keep_umask) 00137 { 00138 /* Get a predictable umask */ 00139 _dbus_verbose ("setting umask\n"); 00140 umask (022); 00141 } 00142 00143 _dbus_verbose ("calling setsid()\n"); 00144 if (setsid () == -1) 00145 _dbus_assert_not_reached ("setsid() failed"); 00146 00147 break; 00148 00149 default: 00150 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe, 00151 child_pid, error)) 00152 { 00153 _dbus_verbose ("pid file or pipe write failed: %s\n", 00154 error->message); 00155 kill (child_pid, SIGTERM); 00156 return FALSE; 00157 } 00158 00159 _dbus_verbose ("parent exiting\n"); 00160 _exit (0); 00161 break; 00162 } 00163 00164 return TRUE; 00165 } 00166 00167 00176 static dbus_bool_t 00177 _dbus_write_pid_file (const DBusString *filename, 00178 unsigned long pid, 00179 DBusError *error) 00180 { 00181 const char *cfilename; 00182 int fd; 00183 FILE *f; 00184 00185 cfilename = _dbus_string_get_const_data (filename); 00186 00187 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644); 00188 00189 if (fd < 0) 00190 { 00191 dbus_set_error (error, _dbus_error_from_errno (errno), 00192 "Failed to open \"%s\": %s", cfilename, 00193 _dbus_strerror (errno)); 00194 return FALSE; 00195 } 00196 00197 if ((f = fdopen (fd, "w")) == NULL) 00198 { 00199 dbus_set_error (error, _dbus_error_from_errno (errno), 00200 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno)); 00201 _dbus_close (fd, NULL); 00202 return FALSE; 00203 } 00204 00205 if (fprintf (f, "%lu\n", pid) < 0) 00206 { 00207 dbus_set_error (error, _dbus_error_from_errno (errno), 00208 "Failed to write to \"%s\": %s", cfilename, 00209 _dbus_strerror (errno)); 00210 00211 fclose (f); 00212 return FALSE; 00213 } 00214 00215 if (fclose (f) == EOF) 00216 { 00217 dbus_set_error (error, _dbus_error_from_errno (errno), 00218 "Failed to close \"%s\": %s", cfilename, 00219 _dbus_strerror (errno)); 00220 return FALSE; 00221 } 00222 00223 return TRUE; 00224 } 00225 00237 dbus_bool_t 00238 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile, 00239 DBusPipe *print_pid_pipe, 00240 dbus_pid_t pid_to_write, 00241 DBusError *error) 00242 { 00243 if (pidfile) 00244 { 00245 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile)); 00246 if (!_dbus_write_pid_file (pidfile, 00247 pid_to_write, 00248 error)) 00249 { 00250 _dbus_verbose ("pid file write failed\n"); 00251 _DBUS_ASSERT_ERROR_IS_SET(error); 00252 return FALSE; 00253 } 00254 } 00255 else 00256 { 00257 _dbus_verbose ("No pid file requested\n"); 00258 } 00259 00260 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe)) 00261 { 00262 DBusString pid; 00263 int bytes; 00264 00265 _dbus_verbose ("writing our pid to pipe %d\n", 00266 print_pid_pipe->fd); 00267 00268 if (!_dbus_string_init (&pid)) 00269 { 00270 _DBUS_SET_OOM (error); 00271 return FALSE; 00272 } 00273 00274 if (!_dbus_string_append_int (&pid, pid_to_write) || 00275 !_dbus_string_append (&pid, "\n")) 00276 { 00277 _dbus_string_free (&pid); 00278 _DBUS_SET_OOM (error); 00279 return FALSE; 00280 } 00281 00282 bytes = _dbus_string_get_length (&pid); 00283 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes) 00284 { 00285 /* _dbus_pipe_write sets error only on failure, not short write */ 00286 if (error != NULL && !dbus_error_is_set(error)) 00287 { 00288 dbus_set_error (error, DBUS_ERROR_FAILED, 00289 "Printing message bus PID: did not write enough bytes\n"); 00290 } 00291 _dbus_string_free (&pid); 00292 return FALSE; 00293 } 00294 00295 _dbus_string_free (&pid); 00296 } 00297 else 00298 { 00299 _dbus_verbose ("No pid pipe to write to\n"); 00300 } 00301 00302 return TRUE; 00303 } 00304 00311 dbus_bool_t 00312 _dbus_verify_daemon_user (const char *user) 00313 { 00314 DBusString u; 00315 00316 _dbus_string_init_const (&u, user); 00317 00318 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL); 00319 } 00320 00321 00322 /* The HAVE_LIBAUDIT case lives in selinux.c */ 00323 #ifndef HAVE_LIBAUDIT 00324 00331 dbus_bool_t 00332 _dbus_change_to_daemon_user (const char *user, 00333 DBusError *error) 00334 { 00335 dbus_uid_t uid; 00336 dbus_gid_t gid; 00337 DBusString u; 00338 00339 _dbus_string_init_const (&u, user); 00340 00341 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid)) 00342 { 00343 dbus_set_error (error, DBUS_ERROR_FAILED, 00344 "User '%s' does not appear to exist?", 00345 user); 00346 return FALSE; 00347 } 00348 00349 /* setgroups() only works if we are a privileged process, 00350 * so we don't return error on failure; the only possible 00351 * failure is that we don't have perms to do it. 00352 * 00353 * not sure this is right, maybe if setuid() 00354 * is going to work then setgroups() should also work. 00355 */ 00356 if (setgroups (0, NULL) < 0) 00357 _dbus_warn ("Failed to drop supplementary groups: %s\n", 00358 _dbus_strerror (errno)); 00359 00360 /* Set GID first, or the setuid may remove our permission 00361 * to change the GID 00362 */ 00363 if (setgid (gid) < 0) 00364 { 00365 dbus_set_error (error, _dbus_error_from_errno (errno), 00366 "Failed to set GID to %lu: %s", gid, 00367 _dbus_strerror (errno)); 00368 return FALSE; 00369 } 00370 00371 if (setuid (uid) < 0) 00372 { 00373 dbus_set_error (error, _dbus_error_from_errno (errno), 00374 "Failed to set UID to %lu: %s", uid, 00375 _dbus_strerror (errno)); 00376 return FALSE; 00377 } 00378 00379 return TRUE; 00380 } 00381 #endif /* !HAVE_LIBAUDIT */ 00382 00383 #ifdef HAVE_SETRLIMIT 00384 00385 /* We assume that if we have setrlimit, we also have getrlimit and 00386 * struct rlimit. 00387 */ 00388 00389 struct DBusRLimit { 00390 struct rlimit lim; 00391 }; 00392 00393 DBusRLimit * 00394 _dbus_rlimit_save_fd_limit (DBusError *error) 00395 { 00396 DBusRLimit *self; 00397 00398 self = dbus_new0 (DBusRLimit, 1); 00399 00400 if (self == NULL) 00401 { 00402 _DBUS_SET_OOM (error); 00403 return NULL; 00404 } 00405 00406 if (getrlimit (RLIMIT_NOFILE, &self->lim) < 0) 00407 { 00408 dbus_set_error (error, _dbus_error_from_errno (errno), 00409 "Failed to get fd limit: %s", _dbus_strerror (errno)); 00410 dbus_free (self); 00411 return NULL; 00412 } 00413 00414 return self; 00415 } 00416 00417 dbus_bool_t 00418 _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired, 00419 DBusError *error) 00420 { 00421 struct rlimit lim; 00422 00423 /* No point to doing this practically speaking 00424 * if we're not uid 0. We expect the system 00425 * bus to use this before we change UID, and 00426 * the session bus takes the Linux default, 00427 * currently 1024 for cur and 4096 for max. 00428 */ 00429 if (getuid () != 0) 00430 { 00431 /* not an error, we're probably the session bus */ 00432 return TRUE; 00433 } 00434 00435 if (getrlimit (RLIMIT_NOFILE, &lim) < 0) 00436 { 00437 dbus_set_error (error, _dbus_error_from_errno (errno), 00438 "Failed to get fd limit: %s", _dbus_strerror (errno)); 00439 return FALSE; 00440 } 00441 00442 if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= desired) 00443 { 00444 /* not an error, everything is fine */ 00445 return TRUE; 00446 } 00447 00448 /* Ignore "maximum limit", assume we have the "superuser" 00449 * privileges. On Linux this is CAP_SYS_RESOURCE. 00450 */ 00451 lim.rlim_cur = lim.rlim_max = desired; 00452 00453 if (setrlimit (RLIMIT_NOFILE, &lim) < 0) 00454 { 00455 dbus_set_error (error, _dbus_error_from_errno (errno), 00456 "Failed to set fd limit to %u: %s", 00457 desired, _dbus_strerror (errno)); 00458 return FALSE; 00459 } 00460 00461 return TRUE; 00462 } 00463 00464 dbus_bool_t 00465 _dbus_rlimit_restore_fd_limit (DBusRLimit *saved, 00466 DBusError *error) 00467 { 00468 if (setrlimit (RLIMIT_NOFILE, &saved->lim) < 0) 00469 { 00470 dbus_set_error (error, _dbus_error_from_errno (errno), 00471 "Failed to restore old fd limit: %s", 00472 _dbus_strerror (errno)); 00473 return FALSE; 00474 } 00475 00476 return TRUE; 00477 } 00478 00479 #else /* !HAVE_SETRLIMIT */ 00480 00481 static void 00482 fd_limit_not_supported (DBusError *error) 00483 { 00484 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00485 "cannot change fd limit on this platform"); 00486 } 00487 00488 DBusRLimit * 00489 _dbus_rlimit_save_fd_limit (DBusError *error) 00490 { 00491 fd_limit_not_supported (error); 00492 return NULL; 00493 } 00494 00495 dbus_bool_t 00496 _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired, 00497 DBusError *error) 00498 { 00499 fd_limit_not_supported (error); 00500 return FALSE; 00501 } 00502 00503 dbus_bool_t 00504 _dbus_rlimit_restore_fd_limit (DBusRLimit *saved, 00505 DBusError *error) 00506 { 00507 fd_limit_not_supported (error); 00508 return FALSE; 00509 } 00510 00511 #endif 00512 00513 void 00514 _dbus_rlimit_free (DBusRLimit *lim) 00515 { 00516 dbus_free (lim); 00517 } 00518 00519 void 00520 _dbus_init_system_log (dbus_bool_t is_daemon) 00521 { 00522 #ifdef HAVE_SYSLOG_H 00523 int logopts = LOG_PID; 00524 00525 #if HAVE_DECL_LOG_PERROR 00526 #ifdef HAVE_SYSTEMD 00527 if (!is_daemon || sd_booted () <= 0) 00528 #endif 00529 logopts |= LOG_PERROR; 00530 #endif 00531 00532 openlog ("dbus", logopts, LOG_DAEMON); 00533 #endif 00534 } 00535 00542 void 00543 _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) 00544 { 00545 va_list args; 00546 00547 va_start (args, msg); 00548 00549 _dbus_system_logv (severity, msg, args); 00550 00551 va_end (args); 00552 } 00553 00564 void 00565 _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args) 00566 { 00567 va_list tmp; 00568 #ifdef HAVE_SYSLOG_H 00569 int flags; 00570 switch (severity) 00571 { 00572 case DBUS_SYSTEM_LOG_INFO: 00573 flags = LOG_DAEMON | LOG_NOTICE; 00574 break; 00575 case DBUS_SYSTEM_LOG_WARNING: 00576 flags = LOG_DAEMON | LOG_WARNING; 00577 break; 00578 case DBUS_SYSTEM_LOG_SECURITY: 00579 flags = LOG_AUTH | LOG_NOTICE; 00580 break; 00581 case DBUS_SYSTEM_LOG_FATAL: 00582 flags = LOG_DAEMON|LOG_CRIT; 00583 break; 00584 default: 00585 return; 00586 } 00587 00588 DBUS_VA_COPY (tmp, args); 00589 vsyslog (flags, msg, tmp); 00590 va_end (tmp); 00591 #endif 00592 00593 #if !defined(HAVE_SYSLOG_H) || !HAVE_DECL_LOG_PERROR 00594 { 00595 /* vsyslog() won't write to stderr, so we'd better do it */ 00596 DBUS_VA_COPY (tmp, args); 00597 fprintf (stderr, "dbus[" DBUS_PID_FORMAT "]: ", _dbus_getpid ()); 00598 vfprintf (stderr, msg, tmp); 00599 fputc ('\n', stderr); 00600 va_end (tmp); 00601 } 00602 #endif 00603 00604 if (severity == DBUS_SYSTEM_LOG_FATAL) 00605 exit (1); 00606 } 00607 00613 void 00614 _dbus_set_signal_handler (int sig, 00615 DBusSignalHandler handler) 00616 { 00617 struct sigaction act; 00618 sigset_t empty_mask; 00619 00620 sigemptyset (&empty_mask); 00621 act.sa_handler = handler; 00622 act.sa_mask = empty_mask; 00623 act.sa_flags = 0; 00624 sigaction (sig, &act, NULL); 00625 } 00626 00632 dbus_bool_t 00633 _dbus_file_exists (const char *file) 00634 { 00635 return (access (file, F_OK) == 0); 00636 } 00637 00644 dbus_bool_t 00645 _dbus_user_at_console (const char *username, 00646 DBusError *error) 00647 { 00648 00649 DBusString u, f; 00650 dbus_bool_t result; 00651 00652 result = FALSE; 00653 if (!_dbus_string_init (&f)) 00654 { 00655 _DBUS_SET_OOM (error); 00656 return FALSE; 00657 } 00658 00659 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR)) 00660 { 00661 _DBUS_SET_OOM (error); 00662 goto out; 00663 } 00664 00665 _dbus_string_init_const (&u, username); 00666 00667 if (!_dbus_concat_dir_and_file (&f, &u)) 00668 { 00669 _DBUS_SET_OOM (error); 00670 goto out; 00671 } 00672 00673 result = _dbus_file_exists (_dbus_string_get_const_data (&f)); 00674 00675 out: 00676 _dbus_string_free (&f); 00677 00678 return result; 00679 } 00680 00681 00688 dbus_bool_t 00689 _dbus_path_is_absolute (const DBusString *filename) 00690 { 00691 if (_dbus_string_get_length (filename) > 0) 00692 return _dbus_string_get_byte (filename, 0) == '/'; 00693 else 00694 return FALSE; 00695 } 00696 00705 dbus_bool_t 00706 _dbus_stat (const DBusString *filename, 00707 DBusStat *statbuf, 00708 DBusError *error) 00709 { 00710 const char *filename_c; 00711 struct stat sb; 00712 00713 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00714 00715 filename_c = _dbus_string_get_const_data (filename); 00716 00717 if (stat (filename_c, &sb) < 0) 00718 { 00719 dbus_set_error (error, _dbus_error_from_errno (errno), 00720 "%s", _dbus_strerror (errno)); 00721 return FALSE; 00722 } 00723 00724 statbuf->mode = sb.st_mode; 00725 statbuf->nlink = sb.st_nlink; 00726 statbuf->uid = sb.st_uid; 00727 statbuf->gid = sb.st_gid; 00728 statbuf->size = sb.st_size; 00729 statbuf->atime = sb.st_atime; 00730 statbuf->mtime = sb.st_mtime; 00731 statbuf->ctime = sb.st_ctime; 00732 00733 return TRUE; 00734 } 00735 00736 00740 struct DBusDirIter 00741 { 00742 DIR *d; 00744 }; 00745 00753 DBusDirIter* 00754 _dbus_directory_open (const DBusString *filename, 00755 DBusError *error) 00756 { 00757 DIR *d; 00758 DBusDirIter *iter; 00759 const char *filename_c; 00760 00761 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00762 00763 filename_c = _dbus_string_get_const_data (filename); 00764 00765 d = opendir (filename_c); 00766 if (d == NULL) 00767 { 00768 dbus_set_error (error, _dbus_error_from_errno (errno), 00769 "Failed to read directory \"%s\": %s", 00770 filename_c, 00771 _dbus_strerror (errno)); 00772 return NULL; 00773 } 00774 iter = dbus_new0 (DBusDirIter, 1); 00775 if (iter == NULL) 00776 { 00777 closedir (d); 00778 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00779 "Could not allocate memory for directory iterator"); 00780 return NULL; 00781 } 00782 00783 iter->d = d; 00784 00785 return iter; 00786 } 00787 00801 dbus_bool_t 00802 _dbus_directory_get_next_file (DBusDirIter *iter, 00803 DBusString *filename, 00804 DBusError *error) 00805 { 00806 struct dirent *ent; 00807 int err; 00808 00809 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00810 00811 again: 00812 errno = 0; 00813 ent = readdir (iter->d); 00814 00815 if (!ent) 00816 { 00817 err = errno; 00818 00819 if (err != 0) 00820 dbus_set_error (error, 00821 _dbus_error_from_errno (err), 00822 "%s", _dbus_strerror (err)); 00823 00824 return FALSE; 00825 } 00826 else if (ent->d_name[0] == '.' && 00827 (ent->d_name[1] == '\0' || 00828 (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) 00829 goto again; 00830 else 00831 { 00832 _dbus_string_set_length (filename, 0); 00833 if (!_dbus_string_append (filename, ent->d_name)) 00834 { 00835 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00836 "No memory to read directory entry"); 00837 return FALSE; 00838 } 00839 else 00840 { 00841 return TRUE; 00842 } 00843 } 00844 } 00845 00849 void 00850 _dbus_directory_close (DBusDirIter *iter) 00851 { 00852 closedir (iter->d); 00853 dbus_free (iter); 00854 } 00855 00856 static dbus_bool_t 00857 fill_user_info_from_group (struct group *g, 00858 DBusGroupInfo *info, 00859 DBusError *error) 00860 { 00861 _dbus_assert (g->gr_name != NULL); 00862 00863 info->gid = g->gr_gid; 00864 info->groupname = _dbus_strdup (g->gr_name); 00865 00866 /* info->members = dbus_strdupv (g->gr_mem) */ 00867 00868 if (info->groupname == NULL) 00869 { 00870 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00871 return FALSE; 00872 } 00873 00874 return TRUE; 00875 } 00876 00877 static dbus_bool_t 00878 fill_group_info (DBusGroupInfo *info, 00879 dbus_gid_t gid, 00880 const DBusString *groupname, 00881 DBusError *error) 00882 { 00883 const char *group_c_str; 00884 00885 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET); 00886 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET); 00887 00888 if (groupname) 00889 group_c_str = _dbus_string_get_const_data (groupname); 00890 else 00891 group_c_str = NULL; 00892 00893 /* For now assuming that the getgrnam() and getgrgid() flavors 00894 * always correspond to the pwnam flavors, if not we have 00895 * to add more configure checks. 00896 */ 00897 00898 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 00899 { 00900 struct group *g; 00901 int result; 00902 size_t buflen; 00903 char *buf; 00904 struct group g_str; 00905 dbus_bool_t b; 00906 00907 /* retrieve maximum needed size for buf */ 00908 buflen = sysconf (_SC_GETGR_R_SIZE_MAX); 00909 00910 /* sysconf actually returns a long, but everything else expects size_t, 00911 * so just recast here. 00912 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 00913 */ 00914 if ((long) buflen <= 0) 00915 buflen = 1024; 00916 00917 result = -1; 00918 while (1) 00919 { 00920 buf = dbus_malloc (buflen); 00921 if (buf == NULL) 00922 { 00923 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00924 return FALSE; 00925 } 00926 00927 g = NULL; 00928 #ifdef HAVE_POSIX_GETPWNAM_R 00929 if (group_c_str) 00930 result = getgrnam_r (group_c_str, &g_str, buf, buflen, 00931 &g); 00932 else 00933 result = getgrgid_r (gid, &g_str, buf, buflen, 00934 &g); 00935 #else 00936 g = getgrnam_r (group_c_str, &g_str, buf, buflen); 00937 result = 0; 00938 #endif /* !HAVE_POSIX_GETPWNAM_R */ 00939 /* Try a bigger buffer if ERANGE was returned: 00940 https://bugs.freedesktop.org/show_bug.cgi?id=16727 00941 */ 00942 if (result == ERANGE && buflen < 512 * 1024) 00943 { 00944 dbus_free (buf); 00945 buflen *= 2; 00946 } 00947 else 00948 { 00949 break; 00950 } 00951 } 00952 00953 if (result == 0 && g == &g_str) 00954 { 00955 b = fill_user_info_from_group (g, info, error); 00956 dbus_free (buf); 00957 return b; 00958 } 00959 else 00960 { 00961 dbus_set_error (error, _dbus_error_from_errno (errno), 00962 "Group %s unknown or failed to look it up\n", 00963 group_c_str ? group_c_str : "???"); 00964 dbus_free (buf); 00965 return FALSE; 00966 } 00967 } 00968 #else /* ! HAVE_GETPWNAM_R */ 00969 { 00970 /* I guess we're screwed on thread safety here */ 00971 struct group *g; 00972 00973 g = getgrnam (group_c_str); 00974 00975 if (g != NULL) 00976 { 00977 return fill_user_info_from_group (g, info, error); 00978 } 00979 else 00980 { 00981 dbus_set_error (error, _dbus_error_from_errno (errno), 00982 "Group %s unknown or failed to look it up\n", 00983 group_c_str ? group_c_str : "???"); 00984 return FALSE; 00985 } 00986 } 00987 #endif /* ! HAVE_GETPWNAM_R */ 00988 } 00989 00999 dbus_bool_t 01000 _dbus_group_info_fill (DBusGroupInfo *info, 01001 const DBusString *groupname, 01002 DBusError *error) 01003 { 01004 return fill_group_info (info, DBUS_GID_UNSET, 01005 groupname, error); 01006 01007 } 01008 01018 dbus_bool_t 01019 _dbus_group_info_fill_gid (DBusGroupInfo *info, 01020 dbus_gid_t gid, 01021 DBusError *error) 01022 { 01023 return fill_group_info (info, gid, NULL, error); 01024 } 01025 01034 dbus_bool_t 01035 _dbus_parse_unix_user_from_config (const DBusString *username, 01036 dbus_uid_t *uid_p) 01037 { 01038 return _dbus_get_user_id (username, uid_p); 01039 01040 } 01041 01050 dbus_bool_t 01051 _dbus_parse_unix_group_from_config (const DBusString *groupname, 01052 dbus_gid_t *gid_p) 01053 { 01054 return _dbus_get_group_id (groupname, gid_p); 01055 } 01056 01067 dbus_bool_t 01068 _dbus_unix_groups_from_uid (dbus_uid_t uid, 01069 dbus_gid_t **group_ids, 01070 int *n_group_ids) 01071 { 01072 return _dbus_groups_from_uid (uid, group_ids, n_group_ids); 01073 } 01074 01084 dbus_bool_t 01085 _dbus_unix_user_is_at_console (dbus_uid_t uid, 01086 DBusError *error) 01087 { 01088 return _dbus_is_console_user (uid, error); 01089 01090 } 01091 01099 dbus_bool_t 01100 _dbus_unix_user_is_process_owner (dbus_uid_t uid) 01101 { 01102 return uid == _dbus_geteuid (); 01103 } 01104 01112 dbus_bool_t 01113 _dbus_windows_user_is_process_owner (const char *windows_sid) 01114 { 01115 return FALSE; 01116 } 01117 /* End of DBusInternalsUtils functions */ 01119 01131 dbus_bool_t 01132 _dbus_string_get_dirname (const DBusString *filename, 01133 DBusString *dirname) 01134 { 01135 int sep; 01136 01137 _dbus_assert (filename != dirname); 01138 _dbus_assert (filename != NULL); 01139 _dbus_assert (dirname != NULL); 01140 01141 /* Ignore any separators on the end */ 01142 sep = _dbus_string_get_length (filename); 01143 if (sep == 0) 01144 return _dbus_string_append (dirname, "."); /* empty string passed in */ 01145 01146 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') 01147 --sep; 01148 01149 _dbus_assert (sep >= 0); 01150 01151 if (sep == 0) 01152 return _dbus_string_append (dirname, "/"); 01153 01154 /* Now find the previous separator */ 01155 _dbus_string_find_byte_backward (filename, sep, '/', &sep); 01156 if (sep < 0) 01157 return _dbus_string_append (dirname, "."); 01158 01159 /* skip multiple separators */ 01160 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') 01161 --sep; 01162 01163 _dbus_assert (sep >= 0); 01164 01165 if (sep == 0 && 01166 _dbus_string_get_byte (filename, 0) == '/') 01167 return _dbus_string_append (dirname, "/"); 01168 else 01169 return _dbus_string_copy_len (filename, 0, sep - 0, 01170 dirname, _dbus_string_get_length (dirname)); 01171 } /* DBusString stuff */ 01173 01174 static void 01175 string_squash_nonprintable (DBusString *str) 01176 { 01177 unsigned char *buf; 01178 int i, len; 01179 01180 buf = _dbus_string_get_data (str); 01181 len = _dbus_string_get_length (str); 01182 01183 for (i = 0; i < len; i++) 01184 { 01185 unsigned char c = (unsigned char) buf[i]; 01186 if (c == '\0') 01187 buf[i] = ' '; 01188 else if (c < 0x20 || c > 127) 01189 buf[i] = '?'; 01190 } 01191 } 01192 01207 dbus_bool_t 01208 _dbus_command_for_pid (unsigned long pid, 01209 DBusString *str, 01210 int max_len, 01211 DBusError *error) 01212 { 01213 /* This is all Linux-specific for now */ 01214 DBusString path; 01215 DBusString cmdline; 01216 int fd; 01217 01218 if (!_dbus_string_init (&path)) 01219 { 01220 _DBUS_SET_OOM (error); 01221 return FALSE; 01222 } 01223 01224 if (!_dbus_string_init (&cmdline)) 01225 { 01226 _DBUS_SET_OOM (error); 01227 _dbus_string_free (&path); 01228 return FALSE; 01229 } 01230 01231 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid)) 01232 goto oom; 01233 01234 fd = open (_dbus_string_get_const_data (&path), O_RDONLY); 01235 if (fd < 0) 01236 { 01237 dbus_set_error (error, 01238 _dbus_error_from_errno (errno), 01239 "Failed to open \"%s\": %s", 01240 _dbus_string_get_const_data (&path), 01241 _dbus_strerror (errno)); 01242 goto fail; 01243 } 01244 01245 if (!_dbus_read (fd, &cmdline, max_len)) 01246 { 01247 dbus_set_error (error, 01248 _dbus_error_from_errno (errno), 01249 "Failed to read from \"%s\": %s", 01250 _dbus_string_get_const_data (&path), 01251 _dbus_strerror (errno)); 01252 _dbus_close (fd, NULL); 01253 goto fail; 01254 } 01255 01256 if (!_dbus_close (fd, error)) 01257 goto fail; 01258 01259 string_squash_nonprintable (&cmdline); 01260 01261 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str))) 01262 goto oom; 01263 01264 _dbus_string_free (&cmdline); 01265 _dbus_string_free (&path); 01266 return TRUE; 01267 oom: 01268 _DBUS_SET_OOM (error); 01269 fail: 01270 _dbus_string_free (&cmdline); 01271 _dbus_string_free (&path); 01272 return FALSE; 01273 } 01274 01275 /* 01276 * replaces the term DBUS_PREFIX in configure_time_path by the 01277 * current dbus installation directory. On unix this function is a noop 01278 * 01279 * @param configure_time_path 01280 * @return real path 01281 */ 01282 const char * 01283 _dbus_replace_install_prefix (const char *configure_time_path) 01284 { 01285 return configure_time_path; 01286 } 01287 01288 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 01289 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 01290 01308 dbus_bool_t 01309 _dbus_get_standard_session_servicedirs (DBusList **dirs) 01310 { 01311 const char *xdg_data_home; 01312 const char *xdg_data_dirs; 01313 DBusString servicedir_path; 01314 01315 if (!_dbus_string_init (&servicedir_path)) 01316 return FALSE; 01317 01318 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 01319 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 01320 01321 if (xdg_data_home != NULL) 01322 { 01323 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 01324 goto oom; 01325 } 01326 else 01327 { 01328 const DBusString *homedir; 01329 DBusString local_share; 01330 01331 if (!_dbus_homedir_from_current_process (&homedir)) 01332 goto oom; 01333 01334 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 01335 goto oom; 01336 01337 _dbus_string_init_const (&local_share, "/.local/share"); 01338 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 01339 goto oom; 01340 } 01341 01342 if (!_dbus_string_append (&servicedir_path, ":")) 01343 goto oom; 01344 01345 if (xdg_data_dirs != NULL) 01346 { 01347 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 01348 goto oom; 01349 01350 if (!_dbus_string_append (&servicedir_path, ":")) 01351 goto oom; 01352 } 01353 else 01354 { 01355 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 01356 goto oom; 01357 } 01358 01359 /* 01360 * add configured datadir to defaults 01361 * this may be the same as an xdg dir 01362 * however the config parser should take 01363 * care of duplicates 01364 */ 01365 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 01366 goto oom; 01367 01368 if (!_dbus_split_paths_and_append (&servicedir_path, 01369 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 01370 dirs)) 01371 goto oom; 01372 01373 _dbus_string_free (&servicedir_path); 01374 return TRUE; 01375 01376 oom: 01377 _dbus_string_free (&servicedir_path); 01378 return FALSE; 01379 } 01380 01381 01400 dbus_bool_t 01401 _dbus_get_standard_system_servicedirs (DBusList **dirs) 01402 { 01403 /* 01404 * DBUS_DATADIR may be the same as one of the standard directories. However, 01405 * the config parser should take care of the duplicates. 01406 * 01407 * Also, append /lib as counterpart of /usr/share on the root 01408 * directory (the root directory does not know /share), in order to 01409 * facilitate early boot system bus activation where /usr might not 01410 * be available. 01411 */ 01412 static const char standard_search_path[] = 01413 "/usr/local/share:" 01414 "/usr/share:" 01415 DBUS_DATADIR ":" 01416 "/lib"; 01417 DBusString servicedir_path; 01418 01419 _dbus_string_init_const (&servicedir_path, standard_search_path); 01420 01421 return _dbus_split_paths_and_append (&servicedir_path, 01422 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 01423 dirs); 01424 } 01425 01434 dbus_bool_t 01435 _dbus_append_system_config_file (DBusString *str) 01436 { 01437 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 01438 } 01439 01446 dbus_bool_t 01447 _dbus_append_session_config_file (DBusString *str) 01448 { 01449 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 01450 }