00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "dbus-sysdeps.h"
00025 #include "dbus-sysdeps-unix.h"
00026 #include "dbus-internals.h"
00027 #include "dbus-protocol.h"
00028 #include "dbus-string.h"
00029 #define DBUS_USERDB_INCLUDES_PRIVATE 1
00030 #include "dbus-userdb.h"
00031 #include "dbus-test.h"
00032
00033 #include <sys/types.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <signal.h>
00037 #include <unistd.h>
00038 #include <stdio.h>
00039 #include <errno.h>
00040 #include <fcntl.h>
00041 #include <sys/stat.h>
00042 #include <grp.h>
00043 #include <sys/socket.h>
00044 #include <dirent.h>
00045 #include <sys/un.h>
00046 #ifdef HAVE_LIBAUDIT
00047 #include <sys/prctl.h>
00048 #include <sys/capability.h>
00049 #include <libaudit.h>
00050 #endif
00051
00052 #ifdef HAVE_SYS_SYSLIMITS_H
00053 #include <sys/syslimits.h>
00054 #endif
00055
00056 #ifndef O_BINARY
00057 #define O_BINARY 0
00058 #endif
00059
00073 dbus_bool_t
00074 _dbus_become_daemon (const DBusString *pidfile,
00075 int print_pid_fd,
00076 DBusError *error)
00077 {
00078 const char *s;
00079 pid_t child_pid;
00080 int dev_null_fd;
00081
00082 _dbus_verbose ("Becoming a daemon...\n");
00083
00084 _dbus_verbose ("chdir to /\n");
00085 if (chdir ("/") < 0)
00086 {
00087 dbus_set_error (error, DBUS_ERROR_FAILED,
00088 "Could not chdir() to root directory");
00089 return FALSE;
00090 }
00091
00092 _dbus_verbose ("forking...\n");
00093 switch ((child_pid = fork ()))
00094 {
00095 case -1:
00096 _dbus_verbose ("fork failed\n");
00097 dbus_set_error (error, _dbus_error_from_errno (errno),
00098 "Failed to fork daemon: %s", _dbus_strerror (errno));
00099 return FALSE;
00100 break;
00101
00102 case 0:
00103 _dbus_verbose ("in child, closing std file descriptors\n");
00104
00105
00106
00107
00108
00109
00110 dev_null_fd = open ("/dev/null", O_RDWR);
00111 if (dev_null_fd >= 0)
00112 {
00113 dup2 (dev_null_fd, 0);
00114 dup2 (dev_null_fd, 1);
00115
00116 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00117 if (s == NULL || *s == '\0')
00118 dup2 (dev_null_fd, 2);
00119 else
00120 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00121 }
00122
00123
00124 _dbus_verbose ("setting umask\n");
00125 umask (022);
00126 break;
00127
00128 default:
00129 if (pidfile)
00130 {
00131 _dbus_verbose ("parent writing pid file\n");
00132 if (!_dbus_write_pid_file (pidfile,
00133 child_pid,
00134 error))
00135 {
00136 _dbus_verbose ("pid file write failed, killing child\n");
00137 kill (child_pid, SIGTERM);
00138 return FALSE;
00139 }
00140 }
00141
00142
00143 if (print_pid_fd >= 0)
00144 {
00145 DBusString pid;
00146 int bytes;
00147
00148 if (!_dbus_string_init (&pid))
00149 {
00150 _DBUS_SET_OOM (error);
00151 kill (child_pid, SIGTERM);
00152 return FALSE;
00153 }
00154
00155 if (!_dbus_string_append_int (&pid, child_pid) ||
00156 !_dbus_string_append (&pid, "\n"))
00157 {
00158 _dbus_string_free (&pid);
00159 _DBUS_SET_OOM (error);
00160 kill (child_pid, SIGTERM);
00161 return FALSE;
00162 }
00163
00164 bytes = _dbus_string_get_length (&pid);
00165 if (_dbus_write_socket (print_pid_fd, &pid, 0, bytes) != bytes)
00166 {
00167 dbus_set_error (error, DBUS_ERROR_FAILED,
00168 "Printing message bus PID: %s\n",
00169 _dbus_strerror (errno));
00170 _dbus_string_free (&pid);
00171 kill (child_pid, SIGTERM);
00172 return FALSE;
00173 }
00174
00175 _dbus_string_free (&pid);
00176 }
00177 _dbus_verbose ("parent exiting\n");
00178 _exit (0);
00179 break;
00180 }
00181
00182 _dbus_verbose ("calling setsid()\n");
00183 if (setsid () == -1)
00184 _dbus_assert_not_reached ("setsid() failed");
00185
00186 return TRUE;
00187 }
00188
00189
00198 dbus_bool_t
00199 _dbus_write_pid_file (const DBusString *filename,
00200 unsigned long pid,
00201 DBusError *error)
00202 {
00203 const char *cfilename;
00204 int fd;
00205 FILE *f;
00206
00207 cfilename = _dbus_string_get_const_data (filename);
00208
00209 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00210
00211 if (fd < 0)
00212 {
00213 dbus_set_error (error, _dbus_error_from_errno (errno),
00214 "Failed to open \"%s\": %s", cfilename,
00215 _dbus_strerror (errno));
00216 return FALSE;
00217 }
00218
00219 if ((f = fdopen (fd, "w")) == NULL)
00220 {
00221 dbus_set_error (error, _dbus_error_from_errno (errno),
00222 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00223 _dbus_close (fd, NULL);
00224 return FALSE;
00225 }
00226
00227 if (fprintf (f, "%lu\n", pid) < 0)
00228 {
00229 dbus_set_error (error, _dbus_error_from_errno (errno),
00230 "Failed to write to \"%s\": %s", cfilename,
00231 _dbus_strerror (errno));
00232
00233 fclose (f);
00234 return FALSE;
00235 }
00236
00237 if (fclose (f) == EOF)
00238 {
00239 dbus_set_error (error, _dbus_error_from_errno (errno),
00240 "Failed to close \"%s\": %s", cfilename,
00241 _dbus_strerror (errno));
00242 return FALSE;
00243 }
00244
00245 return TRUE;
00246 }
00247
00248
00257 dbus_bool_t
00258 _dbus_change_identity (dbus_uid_t uid,
00259 dbus_gid_t gid,
00260 DBusError *error)
00261 {
00262 int priv = FALSE;
00263
00264 #ifdef HAVE_LIBAUDIT
00265
00266
00267
00268 cap_t new_caps = NULL;
00269
00270 priv = !getuid();
00271 if (priv)
00272 {
00273 cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
00274 cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
00275 cap_t tmp_caps = cap_init();
00276
00277 if (!tmp_caps || !(new_caps = cap_init()))
00278 {
00279 dbus_set_error (error, DBUS_ERROR_FAILED,
00280 "Failed to initialize drop of capabilities\n");
00281 if (tmp_caps)
00282 cap_free(tmp_caps);
00283 return FALSE;
00284 }
00285
00286
00287 cap_set_flag(new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
00288 cap_set_flag(new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
00289 cap_set_flag(tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
00290 cap_set_flag(tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
00291
00292 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
00293 {
00294 dbus_set_error (error, _dbus_error_from_errno (errno),
00295 "Failed to set keep-capabilities: %s\n",
00296 _dbus_strerror (errno));
00297 cap_free(tmp_caps);
00298 goto fail;
00299 }
00300 if (cap_set_proc(tmp_caps))
00301 {
00302 dbus_set_error (error, DBUS_ERROR_FAILED,
00303 "Failed to drop capabilities\n");
00304 cap_free(tmp_caps);
00305 goto fail;
00306 }
00307 cap_free(tmp_caps);
00308 }
00309 #endif
00310
00311
00312
00313
00314
00315
00316
00317
00318 if (setgroups (0, NULL) < 0)
00319 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00320 _dbus_strerror (errno));
00321
00322
00323
00324
00325 if (setgid (gid) < 0)
00326 {
00327 dbus_set_error (error, _dbus_error_from_errno (errno),
00328 "Failed to set GID to %lu: %s", gid,
00329 _dbus_strerror (errno));
00330 goto fail;
00331 }
00332
00333 if (setuid (uid) < 0)
00334 {
00335 dbus_set_error (error, _dbus_error_from_errno (errno),
00336 "Failed to set UID to %lu: %s", uid,
00337 _dbus_strerror (errno));
00338 goto fail;
00339 }
00340
00341 #ifdef HAVE_LIBAUDIT
00342 if (priv)
00343 {
00344 if (cap_set_proc(new_caps))
00345 {
00346 dbus_set_error (error, DBUS_ERROR_FAILED,
00347 "Failed to drop capabilities\n");
00348 goto fail;
00349 }
00350 cap_free(new_caps);
00351
00352 if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
00353 {
00354 dbus_set_error (error, _dbus_error_from_errno (errno),
00355 "Failed to unset keep-capabilities: %s\n",
00356 _dbus_strerror (errno));
00357 return FALSE;
00358 }
00359 }
00360 #endif
00361
00362 return TRUE;
00363
00364 fail:
00365 #ifdef HAVE_LIBAUDIT
00366 if (priv)
00367 {
00368
00369 prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
00370 cap_free(new_caps);
00371 }
00372 #endif
00373 return FALSE;
00374 }
00375
00381 void
00382 _dbus_set_signal_handler (int sig,
00383 DBusSignalHandler handler)
00384 {
00385 struct sigaction act;
00386 sigset_t empty_mask;
00387
00388 sigemptyset (&empty_mask);
00389 act.sa_handler = handler;
00390 act.sa_mask = empty_mask;
00391 act.sa_flags = 0;
00392 sigaction (sig, &act, NULL);
00393 }
00394
00395
00403 dbus_bool_t
00404 _dbus_delete_directory (const DBusString *filename,
00405 DBusError *error)
00406 {
00407 const char *filename_c;
00408
00409 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00410
00411 filename_c = _dbus_string_get_const_data (filename);
00412
00413 if (rmdir (filename_c) != 0)
00414 {
00415 dbus_set_error (error, DBUS_ERROR_FAILED,
00416 "Failed to remove directory %s: %s\n",
00417 filename_c, _dbus_strerror (errno));
00418 return FALSE;
00419 }
00420
00421 return TRUE;
00422 }
00423
00429 dbus_bool_t
00430 _dbus_file_exists (const char *file)
00431 {
00432 return (access (file, F_OK) == 0);
00433 }
00434
00441 dbus_bool_t
00442 _dbus_user_at_console (const char *username,
00443 DBusError *error)
00444 {
00445
00446 DBusString f;
00447 dbus_bool_t result;
00448
00449 result = FALSE;
00450 if (!_dbus_string_init (&f))
00451 {
00452 _DBUS_SET_OOM (error);
00453 return FALSE;
00454 }
00455
00456 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00457 {
00458 _DBUS_SET_OOM (error);
00459 goto out;
00460 }
00461
00462
00463 if (!_dbus_string_append (&f, username))
00464 {
00465 _DBUS_SET_OOM (error);
00466 goto out;
00467 }
00468
00469 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00470
00471 out:
00472 _dbus_string_free (&f);
00473
00474 return result;
00475 }
00476
00477
00484 dbus_bool_t
00485 _dbus_path_is_absolute (const DBusString *filename)
00486 {
00487 if (_dbus_string_get_length (filename) > 0)
00488 return _dbus_string_get_byte (filename, 0) == '/';
00489 else
00490 return FALSE;
00491 }
00492
00501 dbus_bool_t
00502 _dbus_stat (const DBusString *filename,
00503 DBusStat *statbuf,
00504 DBusError *error)
00505 {
00506 const char *filename_c;
00507 struct stat sb;
00508
00509 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00510
00511 filename_c = _dbus_string_get_const_data (filename);
00512
00513 if (stat (filename_c, &sb) < 0)
00514 {
00515 dbus_set_error (error, _dbus_error_from_errno (errno),
00516 "%s", _dbus_strerror (errno));
00517 return FALSE;
00518 }
00519
00520 statbuf->mode = sb.st_mode;
00521 statbuf->nlink = sb.st_nlink;
00522 statbuf->uid = sb.st_uid;
00523 statbuf->gid = sb.st_gid;
00524 statbuf->size = sb.st_size;
00525 statbuf->atime = sb.st_atime;
00526 statbuf->mtime = sb.st_mtime;
00527 statbuf->ctime = sb.st_ctime;
00528
00529 return TRUE;
00530 }
00531
00532
00536 struct DBusDirIter
00537 {
00538 DIR *d;
00540 };
00541
00549 DBusDirIter*
00550 _dbus_directory_open (const DBusString *filename,
00551 DBusError *error)
00552 {
00553 DIR *d;
00554 DBusDirIter *iter;
00555 const char *filename_c;
00556
00557 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00558
00559 filename_c = _dbus_string_get_const_data (filename);
00560
00561 d = opendir (filename_c);
00562 if (d == NULL)
00563 {
00564 dbus_set_error (error, _dbus_error_from_errno (errno),
00565 "Failed to read directory \"%s\": %s",
00566 filename_c,
00567 _dbus_strerror (errno));
00568 return NULL;
00569 }
00570 iter = dbus_new0 (DBusDirIter, 1);
00571 if (iter == NULL)
00572 {
00573 closedir (d);
00574 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00575 "Could not allocate memory for directory iterator");
00576 return NULL;
00577 }
00578
00579 iter->d = d;
00580
00581 return iter;
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 static dbus_bool_t
00593 dirent_buf_size(DIR * dirp, size_t *size)
00594 {
00595 long name_max;
00596 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00597 # if defined(HAVE_DIRFD)
00598 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00599 # elif defined(HAVE_DDFD)
00600 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00601 # else
00602 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00603 # endif
00604 if (name_max == -1)
00605 # if defined(NAME_MAX)
00606 name_max = NAME_MAX;
00607 # else
00608 return FALSE;
00609 # endif
00610 # elif defined(MAXNAMELEN)
00611 name_max = MAXNAMELEN;
00612 # else
00613 # if defined(NAME_MAX)
00614 name_max = NAME_MAX;
00615 # else
00616 # error "buffer size for readdir_r cannot be determined"
00617 # endif
00618 # endif
00619 if (size)
00620 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00621 else
00622 return FALSE;
00623
00624 return TRUE;
00625 }
00626
00637 dbus_bool_t
00638 _dbus_directory_get_next_file (DBusDirIter *iter,
00639 DBusString *filename,
00640 DBusError *error)
00641 {
00642 struct dirent *d, *ent;
00643 size_t buf_size;
00644 int err;
00645
00646 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00647
00648 if (!dirent_buf_size (iter->d, &buf_size))
00649 {
00650 dbus_set_error (error, DBUS_ERROR_FAILED,
00651 "Can't calculate buffer size when reading directory");
00652 return FALSE;
00653 }
00654
00655 d = (struct dirent *)dbus_malloc (buf_size);
00656 if (!d)
00657 {
00658 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00659 "No memory to read directory entry");
00660 return FALSE;
00661 }
00662
00663 again:
00664 err = readdir_r (iter->d, d, &ent);
00665 if (err || !ent)
00666 {
00667 if (err != 0)
00668 dbus_set_error (error,
00669 _dbus_error_from_errno (err),
00670 "%s", _dbus_strerror (err));
00671
00672 dbus_free (d);
00673 return FALSE;
00674 }
00675 else if (ent->d_name[0] == '.' &&
00676 (ent->d_name[1] == '\0' ||
00677 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00678 goto again;
00679 else
00680 {
00681 _dbus_string_set_length (filename, 0);
00682 if (!_dbus_string_append (filename, ent->d_name))
00683 {
00684 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00685 "No memory to read directory entry");
00686 dbus_free (d);
00687 return FALSE;
00688 }
00689 else
00690 {
00691 dbus_free (d);
00692 return TRUE;
00693 }
00694 }
00695 }
00696
00700 void
00701 _dbus_directory_close (DBusDirIter *iter)
00702 {
00703 closedir (iter->d);
00704 dbus_free (iter);
00705 }
00706
00707 static dbus_bool_t
00708 fill_user_info_from_group (struct group *g,
00709 DBusGroupInfo *info,
00710 DBusError *error)
00711 {
00712 _dbus_assert (g->gr_name != NULL);
00713
00714 info->gid = g->gr_gid;
00715 info->groupname = _dbus_strdup (g->gr_name);
00716
00717
00718
00719 if (info->groupname == NULL)
00720 {
00721 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00722 return FALSE;
00723 }
00724
00725 return TRUE;
00726 }
00727
00728 static dbus_bool_t
00729 fill_group_info (DBusGroupInfo *info,
00730 dbus_gid_t gid,
00731 const DBusString *groupname,
00732 DBusError *error)
00733 {
00734 const char *group_c_str;
00735
00736 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00737 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00738
00739 if (groupname)
00740 group_c_str = _dbus_string_get_const_data (groupname);
00741 else
00742 group_c_str = NULL;
00743
00744
00745
00746
00747
00748
00749 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00750 {
00751 struct group *g;
00752 int result;
00753 char buf[1024];
00754 struct group g_str;
00755
00756 g = NULL;
00757 #ifdef HAVE_POSIX_GETPWNAM_R
00758
00759 if (group_c_str)
00760 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00761 &g);
00762 else
00763 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00764 &g);
00765 #else
00766 g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00767 result = 0;
00768 #endif
00769 if (result == 0 && g == &g_str)
00770 {
00771 return fill_user_info_from_group (g, info, error);
00772 }
00773 else
00774 {
00775 dbus_set_error (error, _dbus_error_from_errno (errno),
00776 "Group %s unknown or failed to look it up\n",
00777 group_c_str ? group_c_str : "???");
00778 return FALSE;
00779 }
00780 }
00781 #else
00782 {
00783
00784 struct group *g;
00785
00786 g = getgrnam (group_c_str);
00787
00788 if (g != NULL)
00789 {
00790 return fill_user_info_from_group (g, info, error);
00791 }
00792 else
00793 {
00794 dbus_set_error (error, _dbus_error_from_errno (errno),
00795 "Group %s unknown or failed to look it up\n",
00796 group_c_str ? group_c_str : "???");
00797 return FALSE;
00798 }
00799 }
00800 #endif
00801 }
00802
00812 dbus_bool_t
00813 _dbus_group_info_fill (DBusGroupInfo *info,
00814 const DBusString *groupname,
00815 DBusError *error)
00816 {
00817 return fill_group_info (info, DBUS_GID_UNSET,
00818 groupname, error);
00819
00820 }
00821
00831 dbus_bool_t
00832 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00833 dbus_gid_t gid,
00834 DBusError *error)
00835 {
00836 return fill_group_info (info, gid, NULL, error);
00837 }
00838
00840
00852 dbus_bool_t
00853 _dbus_string_get_dirname (const DBusString *filename,
00854 DBusString *dirname)
00855 {
00856 int sep;
00857
00858 _dbus_assert (filename != dirname);
00859 _dbus_assert (filename != NULL);
00860 _dbus_assert (dirname != NULL);
00861
00862
00863 sep = _dbus_string_get_length (filename);
00864 if (sep == 0)
00865 return _dbus_string_append (dirname, ".");
00866
00867 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00868 --sep;
00869
00870 _dbus_assert (sep >= 0);
00871
00872 if (sep == 0)
00873 return _dbus_string_append (dirname, "/");
00874
00875
00876 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
00877 if (sep < 0)
00878 return _dbus_string_append (dirname, ".");
00879
00880
00881 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00882 --sep;
00883
00884 _dbus_assert (sep >= 0);
00885
00886 if (sep == 0 &&
00887 _dbus_string_get_byte (filename, 0) == '/')
00888 return _dbus_string_append (dirname, "/");
00889 else
00890 return _dbus_string_copy_len (filename, 0, sep - 0,
00891 dirname, _dbus_string_get_length (dirname));
00892 }
00894