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 #include <pwd.h>
00047
00048 #ifdef HAVE_SYS_SYSLIMITS_H
00049 #include <sys/syslimits.h>
00050 #endif
00051
00052 #ifndef O_BINARY
00053 #define O_BINARY 0
00054 #endif
00055
00069 dbus_bool_t
00070 _dbus_become_daemon (const DBusString *pidfile,
00071 int print_pid_fd,
00072 DBusError *error)
00073 {
00074 const char *s;
00075 pid_t child_pid;
00076 int dev_null_fd;
00077
00078 _dbus_verbose ("Becoming a daemon...\n");
00079
00080 _dbus_verbose ("chdir to /\n");
00081 if (chdir ("/") < 0)
00082 {
00083 dbus_set_error (error, DBUS_ERROR_FAILED,
00084 "Could not chdir() to root directory");
00085 return FALSE;
00086 }
00087
00088 _dbus_verbose ("forking...\n");
00089 switch ((child_pid = fork ()))
00090 {
00091 case -1:
00092 _dbus_verbose ("fork failed\n");
00093 dbus_set_error (error, _dbus_error_from_errno (errno),
00094 "Failed to fork daemon: %s", _dbus_strerror (errno));
00095 return FALSE;
00096 break;
00097
00098 case 0:
00099 _dbus_verbose ("in child, closing std file descriptors\n");
00100
00101
00102
00103
00104
00105
00106 dev_null_fd = open ("/dev/null", O_RDWR);
00107 if (dev_null_fd >= 0)
00108 {
00109 dup2 (dev_null_fd, 0);
00110 dup2 (dev_null_fd, 1);
00111
00112 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00113 if (s == NULL || *s == '\0')
00114 dup2 (dev_null_fd, 2);
00115 else
00116 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00117 }
00118
00119
00120 _dbus_verbose ("setting umask\n");
00121 umask (022);
00122 break;
00123
00124 default:
00125 if (pidfile)
00126 {
00127 _dbus_verbose ("parent writing pid file\n");
00128 if (!_dbus_write_pid_file (pidfile,
00129 child_pid,
00130 error))
00131 {
00132 _dbus_verbose ("pid file write failed, killing child\n");
00133 kill (child_pid, SIGTERM);
00134 return FALSE;
00135 }
00136 }
00137
00138
00139 if (print_pid_fd >= 0)
00140 {
00141 DBusString pid;
00142 int bytes;
00143
00144 if (!_dbus_string_init (&pid))
00145 {
00146 _DBUS_SET_OOM (error);
00147 kill (child_pid, SIGTERM);
00148 return FALSE;
00149 }
00150
00151 if (!_dbus_string_append_int (&pid, child_pid) ||
00152 !_dbus_string_append (&pid, "\n"))
00153 {
00154 _dbus_string_free (&pid);
00155 _DBUS_SET_OOM (error);
00156 kill (child_pid, SIGTERM);
00157 return FALSE;
00158 }
00159
00160 bytes = _dbus_string_get_length (&pid);
00161 if (_dbus_write_socket (print_pid_fd, &pid, 0, bytes) != bytes)
00162 {
00163 dbus_set_error (error, DBUS_ERROR_FAILED,
00164 "Printing message bus PID: %s\n",
00165 _dbus_strerror (errno));
00166 _dbus_string_free (&pid);
00167 kill (child_pid, SIGTERM);
00168 return FALSE;
00169 }
00170
00171 _dbus_string_free (&pid);
00172 }
00173 _dbus_verbose ("parent exiting\n");
00174 _exit (0);
00175 break;
00176 }
00177
00178 _dbus_verbose ("calling setsid()\n");
00179 if (setsid () == -1)
00180 _dbus_assert_not_reached ("setsid() failed");
00181
00182 return TRUE;
00183 }
00184
00185
00194 dbus_bool_t
00195 _dbus_write_pid_file (const DBusString *filename,
00196 unsigned long pid,
00197 DBusError *error)
00198 {
00199 const char *cfilename;
00200 int fd;
00201 FILE *f;
00202
00203 cfilename = _dbus_string_get_const_data (filename);
00204
00205 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00206
00207 if (fd < 0)
00208 {
00209 dbus_set_error (error, _dbus_error_from_errno (errno),
00210 "Failed to open \"%s\": %s", cfilename,
00211 _dbus_strerror (errno));
00212 return FALSE;
00213 }
00214
00215 if ((f = fdopen (fd, "w")) == NULL)
00216 {
00217 dbus_set_error (error, _dbus_error_from_errno (errno),
00218 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00219 _dbus_close (fd, NULL);
00220 return FALSE;
00221 }
00222
00223 if (fprintf (f, "%lu\n", pid) < 0)
00224 {
00225 dbus_set_error (error, _dbus_error_from_errno (errno),
00226 "Failed to write to \"%s\": %s", cfilename,
00227 _dbus_strerror (errno));
00228
00229 fclose (f);
00230 return FALSE;
00231 }
00232
00233 if (fclose (f) == EOF)
00234 {
00235 dbus_set_error (error, _dbus_error_from_errno (errno),
00236 "Failed to close \"%s\": %s", cfilename,
00237 _dbus_strerror (errno));
00238 return FALSE;
00239 }
00240
00241 return TRUE;
00242 }
00243
00244
00253 dbus_bool_t
00254 _dbus_change_identity (dbus_uid_t uid,
00255 dbus_gid_t gid,
00256 DBusError *error)
00257 {
00258 struct passwd *pw = getpwuid(uid);
00259 if (pw == NULL)
00260 {
00261 dbus_set_error (error, _dbus_error_from_errno (errno),
00262 "getpwuid() for UID '%d' failed: %s", uid,
00263 _dbus_strerror (errno));
00264 return FALSE;
00265 }
00266
00267 if (initgroups (pw->pw_name, pw->pw_gid) < 0)
00268 {
00269 dbus_set_error (error, _dbus_error_from_errno (errno),
00270 "initgroups() failed: %s",
00271 _dbus_strerror (errno));
00272 return FALSE;
00273 }
00274
00275
00276
00277
00278 if (setgid (gid) < 0)
00279 {
00280 dbus_set_error (error, _dbus_error_from_errno (errno),
00281 "Failed to set GID to %lu: %s", gid,
00282 _dbus_strerror (errno));
00283 return FALSE;
00284 }
00285
00286 if (setuid (uid) < 0)
00287 {
00288 dbus_set_error (error, _dbus_error_from_errno (errno),
00289 "Failed to set UID to %lu: %s", uid,
00290 _dbus_strerror (errno));
00291 return FALSE;
00292 }
00293
00294 return TRUE;
00295 }
00296
00302 void
00303 _dbus_set_signal_handler (int sig,
00304 DBusSignalHandler handler)
00305 {
00306 struct sigaction act;
00307 sigset_t empty_mask;
00308
00309 sigemptyset (&empty_mask);
00310 act.sa_handler = handler;
00311 act.sa_mask = empty_mask;
00312 act.sa_flags = 0;
00313 sigaction (sig, &act, NULL);
00314 }
00315
00316
00324 dbus_bool_t
00325 _dbus_delete_directory (const DBusString *filename,
00326 DBusError *error)
00327 {
00328 const char *filename_c;
00329
00330 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00331
00332 filename_c = _dbus_string_get_const_data (filename);
00333
00334 if (rmdir (filename_c) != 0)
00335 {
00336 dbus_set_error (error, DBUS_ERROR_FAILED,
00337 "Failed to remove directory %s: %s\n",
00338 filename_c, _dbus_strerror (errno));
00339 return FALSE;
00340 }
00341
00342 return TRUE;
00343 }
00344
00350 dbus_bool_t
00351 _dbus_file_exists (const char *file)
00352 {
00353 return (access (file, F_OK) == 0);
00354 }
00355
00362 dbus_bool_t
00363 _dbus_user_at_console (const char *username,
00364 DBusError *error)
00365 {
00366
00367 DBusString f;
00368 dbus_bool_t result;
00369
00370 result = FALSE;
00371 if (!_dbus_string_init (&f))
00372 {
00373 _DBUS_SET_OOM (error);
00374 return FALSE;
00375 }
00376
00377 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00378 {
00379 _DBUS_SET_OOM (error);
00380 goto out;
00381 }
00382
00383
00384 if (!_dbus_string_append (&f, username))
00385 {
00386 _DBUS_SET_OOM (error);
00387 goto out;
00388 }
00389
00390 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00391
00392 out:
00393 _dbus_string_free (&f);
00394
00395 return result;
00396 }
00397
00398
00405 dbus_bool_t
00406 _dbus_path_is_absolute (const DBusString *filename)
00407 {
00408 if (_dbus_string_get_length (filename) > 0)
00409 return _dbus_string_get_byte (filename, 0) == '/';
00410 else
00411 return FALSE;
00412 }
00413
00422 dbus_bool_t
00423 _dbus_stat (const DBusString *filename,
00424 DBusStat *statbuf,
00425 DBusError *error)
00426 {
00427 const char *filename_c;
00428 struct stat sb;
00429
00430 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00431
00432 filename_c = _dbus_string_get_const_data (filename);
00433
00434 if (stat (filename_c, &sb) < 0)
00435 {
00436 dbus_set_error (error, _dbus_error_from_errno (errno),
00437 "%s", _dbus_strerror (errno));
00438 return FALSE;
00439 }
00440
00441 statbuf->mode = sb.st_mode;
00442 statbuf->nlink = sb.st_nlink;
00443 statbuf->uid = sb.st_uid;
00444 statbuf->gid = sb.st_gid;
00445 statbuf->size = sb.st_size;
00446 statbuf->atime = sb.st_atime;
00447 statbuf->mtime = sb.st_mtime;
00448 statbuf->ctime = sb.st_ctime;
00449
00450 return TRUE;
00451 }
00452
00453
00457 struct DBusDirIter
00458 {
00459 DIR *d;
00461 };
00462
00470 DBusDirIter*
00471 _dbus_directory_open (const DBusString *filename,
00472 DBusError *error)
00473 {
00474 DIR *d;
00475 DBusDirIter *iter;
00476 const char *filename_c;
00477
00478 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00479
00480 filename_c = _dbus_string_get_const_data (filename);
00481
00482 d = opendir (filename_c);
00483 if (d == NULL)
00484 {
00485 dbus_set_error (error, _dbus_error_from_errno (errno),
00486 "Failed to read directory \"%s\": %s",
00487 filename_c,
00488 _dbus_strerror (errno));
00489 return NULL;
00490 }
00491 iter = dbus_new0 (DBusDirIter, 1);
00492 if (iter == NULL)
00493 {
00494 closedir (d);
00495 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00496 "Could not allocate memory for directory iterator");
00497 return NULL;
00498 }
00499
00500 iter->d = d;
00501
00502 return iter;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 static dbus_bool_t
00514 dirent_buf_size(DIR * dirp, size_t *size)
00515 {
00516 long name_max;
00517 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00518 # if defined(HAVE_DIRFD)
00519 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00520 # elif defined(HAVE_DDFD)
00521 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00522 # else
00523 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00524 # endif
00525 if (name_max == -1)
00526 # if defined(NAME_MAX)
00527 name_max = NAME_MAX;
00528 # else
00529 return FALSE;
00530 # endif
00531 # elif defined(MAXNAMELEN)
00532 name_max = MAXNAMELEN;
00533 # else
00534 # if defined(NAME_MAX)
00535 name_max = NAME_MAX;
00536 # else
00537 # error "buffer size for readdir_r cannot be determined"
00538 # endif
00539 # endif
00540 if (size)
00541 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00542 else
00543 return FALSE;
00544
00545 return TRUE;
00546 }
00547
00558 dbus_bool_t
00559 _dbus_directory_get_next_file (DBusDirIter *iter,
00560 DBusString *filename,
00561 DBusError *error)
00562 {
00563 struct dirent *d, *ent;
00564 size_t buf_size;
00565 int err;
00566
00567 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00568
00569 if (!dirent_buf_size (iter->d, &buf_size))
00570 {
00571 dbus_set_error (error, DBUS_ERROR_FAILED,
00572 "Can't calculate buffer size when reading directory");
00573 return FALSE;
00574 }
00575
00576 d = (struct dirent *)dbus_malloc (buf_size);
00577 if (!d)
00578 {
00579 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00580 "No memory to read directory entry");
00581 return FALSE;
00582 }
00583
00584 again:
00585 err = readdir_r (iter->d, d, &ent);
00586 if (err || !ent)
00587 {
00588 if (err != 0)
00589 dbus_set_error (error,
00590 _dbus_error_from_errno (err),
00591 "%s", _dbus_strerror (err));
00592
00593 dbus_free (d);
00594 return FALSE;
00595 }
00596 else if (ent->d_name[0] == '.' &&
00597 (ent->d_name[1] == '\0' ||
00598 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00599 goto again;
00600 else
00601 {
00602 _dbus_string_set_length (filename, 0);
00603 if (!_dbus_string_append (filename, ent->d_name))
00604 {
00605 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00606 "No memory to read directory entry");
00607 dbus_free (d);
00608 return FALSE;
00609 }
00610 else
00611 {
00612 dbus_free (d);
00613 return TRUE;
00614 }
00615 }
00616 }
00617
00621 void
00622 _dbus_directory_close (DBusDirIter *iter)
00623 {
00624 closedir (iter->d);
00625 dbus_free (iter);
00626 }
00627
00628 static dbus_bool_t
00629 fill_user_info_from_group (struct group *g,
00630 DBusGroupInfo *info,
00631 DBusError *error)
00632 {
00633 _dbus_assert (g->gr_name != NULL);
00634
00635 info->gid = g->gr_gid;
00636 info->groupname = _dbus_strdup (g->gr_name);
00637
00638
00639
00640 if (info->groupname == NULL)
00641 {
00642 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00643 return FALSE;
00644 }
00645
00646 return TRUE;
00647 }
00648
00649 static dbus_bool_t
00650 fill_group_info (DBusGroupInfo *info,
00651 dbus_gid_t gid,
00652 const DBusString *groupname,
00653 DBusError *error)
00654 {
00655 const char *group_c_str;
00656
00657 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00658 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00659
00660 if (groupname)
00661 group_c_str = _dbus_string_get_const_data (groupname);
00662 else
00663 group_c_str = NULL;
00664
00665
00666
00667
00668
00669
00670 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00671 {
00672 struct group *g;
00673 int result;
00674 char buf[1024];
00675 struct group g_str;
00676
00677 g = NULL;
00678 #ifdef HAVE_POSIX_GETPWNAM_R
00679
00680 if (group_c_str)
00681 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00682 &g);
00683 else
00684 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00685 &g);
00686 #else
00687 g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00688 result = 0;
00689 #endif
00690 if (result == 0 && g == &g_str)
00691 {
00692 return fill_user_info_from_group (g, info, error);
00693 }
00694 else
00695 {
00696 dbus_set_error (error, _dbus_error_from_errno (errno),
00697 "Group %s unknown or failed to look it up\n",
00698 group_c_str ? group_c_str : "???");
00699 return FALSE;
00700 }
00701 }
00702 #else
00703 {
00704
00705 struct group *g;
00706
00707 g = getgrnam (group_c_str);
00708
00709 if (g != NULL)
00710 {
00711 return fill_user_info_from_group (g, info, error);
00712 }
00713 else
00714 {
00715 dbus_set_error (error, _dbus_error_from_errno (errno),
00716 "Group %s unknown or failed to look it up\n",
00717 group_c_str ? group_c_str : "???");
00718 return FALSE;
00719 }
00720 }
00721 #endif
00722 }
00723
00733 dbus_bool_t
00734 _dbus_group_info_fill (DBusGroupInfo *info,
00735 const DBusString *groupname,
00736 DBusError *error)
00737 {
00738 return fill_group_info (info, DBUS_GID_UNSET,
00739 groupname, error);
00740
00741 }
00742
00752 dbus_bool_t
00753 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00754 dbus_gid_t gid,
00755 DBusError *error)
00756 {
00757 return fill_group_info (info, gid, NULL, error);
00758 }
00759
00761
00773 dbus_bool_t
00774 _dbus_string_get_dirname (const DBusString *filename,
00775 DBusString *dirname)
00776 {
00777 int sep;
00778
00779 _dbus_assert (filename != dirname);
00780 _dbus_assert (filename != NULL);
00781 _dbus_assert (dirname != NULL);
00782
00783
00784 sep = _dbus_string_get_length (filename);
00785 if (sep == 0)
00786 return _dbus_string_append (dirname, ".");
00787
00788 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00789 --sep;
00790
00791 _dbus_assert (sep >= 0);
00792
00793 if (sep == 0)
00794 return _dbus_string_append (dirname, "/");
00795
00796
00797 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
00798 if (sep < 0)
00799 return _dbus_string_append (dirname, ".");
00800
00801
00802 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00803 --sep;
00804
00805 _dbus_assert (sep >= 0);
00806
00807 if (sep == 0 &&
00808 _dbus_string_get_byte (filename, 0) == '/')
00809 return _dbus_string_append (dirname, "/");
00810 else
00811 return _dbus_string_copy_len (filename, 0, sep - 0,
00812 dirname, _dbus_string_get_length (dirname));
00813 }
00815