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 = NAME_MAX;
00517 #if 0
00518 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00519 # if defined(HAVE_DIRFD)
00520 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00521 # elif defined(HAVE_DDFD)
00522 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00523 # else
00524 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00525 # endif
00526 if (name_max == -1)
00527 # if defined(NAME_MAX)
00528 name_max = NAME_MAX;
00529 # else
00530 return FALSE;
00531 # endif
00532 # elif defined(MAXNAMELEN)
00533 name_max = MAXNAMELEN;
00534 # else
00535 # if defined(NAME_MAX)
00536 name_max = NAME_MAX;
00537 # else
00538 # error "buffer size for readdir_r cannot be determined"
00539 # endif
00540 # endif
00541 #endif
00542 if (size)
00543 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00544 else
00545 return FALSE;
00546
00547 return TRUE;
00548 }
00549
00560 dbus_bool_t
00561 _dbus_directory_get_next_file (DBusDirIter *iter,
00562 DBusString *filename,
00563 DBusError *error)
00564 {
00565 struct dirent *d, *ent;
00566 size_t buf_size;
00567 int err;
00568
00569 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00570
00571 if (!dirent_buf_size (iter->d, &buf_size))
00572 {
00573 dbus_set_error (error, DBUS_ERROR_FAILED,
00574 "Can't calculate buffer size when reading directory");
00575 return FALSE;
00576 }
00577
00578 d = (struct dirent *)dbus_malloc (buf_size);
00579 if (!d)
00580 {
00581 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00582 "No memory to read directory entry");
00583 return FALSE;
00584 }
00585
00586 again:
00587 err = readdir_r (iter->d, d, &ent);
00588 if (err || !ent)
00589 {
00590 if (err != 0)
00591 dbus_set_error (error,
00592 _dbus_error_from_errno (err),
00593 "%s", _dbus_strerror (err));
00594
00595 dbus_free (d);
00596 return FALSE;
00597 }
00598 else if (ent->d_name[0] == '.' &&
00599 (ent->d_name[1] == '\0' ||
00600 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00601 goto again;
00602 else
00603 {
00604 _dbus_string_set_length (filename, 0);
00605 if (!_dbus_string_append (filename, ent->d_name))
00606 {
00607 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00608 "No memory to read directory entry");
00609 dbus_free (d);
00610 return FALSE;
00611 }
00612 else
00613 {
00614 dbus_free (d);
00615 return TRUE;
00616 }
00617 }
00618 }
00619
00623 void
00624 _dbus_directory_close (DBusDirIter *iter)
00625 {
00626 closedir (iter->d);
00627 dbus_free (iter);
00628 }
00629
00630 static dbus_bool_t
00631 fill_user_info_from_group (struct group *g,
00632 DBusGroupInfo *info,
00633 DBusError *error)
00634 {
00635 _dbus_assert (g->gr_name != NULL);
00636
00637 info->gid = g->gr_gid;
00638 info->groupname = _dbus_strdup (g->gr_name);
00639
00640
00641
00642 if (info->groupname == NULL)
00643 {
00644 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00645 return FALSE;
00646 }
00647
00648 return TRUE;
00649 }
00650
00651 static dbus_bool_t
00652 fill_group_info (DBusGroupInfo *info,
00653 dbus_gid_t gid,
00654 const DBusString *groupname,
00655 DBusError *error)
00656 {
00657 const char *group_c_str;
00658
00659 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00660 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00661
00662 if (groupname)
00663 group_c_str = _dbus_string_get_const_data (groupname);
00664 else
00665 group_c_str = NULL;
00666
00667
00668
00669
00670
00671
00672 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00673 {
00674 struct group *g;
00675 int result;
00676 char buf[1024];
00677 struct group g_str;
00678
00679 g = NULL;
00680 #ifdef HAVE_POSIX_GETPWNAM_R
00681
00682 if (group_c_str)
00683 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00684 &g);
00685 else
00686 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00687 &g);
00688 #else
00689 g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00690 result = 0;
00691 #endif
00692 if (result == 0 && g == &g_str)
00693 {
00694 return fill_user_info_from_group (g, info, error);
00695 }
00696 else
00697 {
00698 dbus_set_error (error, _dbus_error_from_errno (errno),
00699 "Group %s unknown or failed to look it up\n",
00700 group_c_str ? group_c_str : "???");
00701 return FALSE;
00702 }
00703 }
00704 #else
00705 {
00706
00707 struct group *g;
00708
00709 g = getgrnam (group_c_str);
00710
00711 if (g != NULL)
00712 {
00713 return fill_user_info_from_group (g, info, error);
00714 }
00715 else
00716 {
00717 dbus_set_error (error, _dbus_error_from_errno (errno),
00718 "Group %s unknown or failed to look it up\n",
00719 group_c_str ? group_c_str : "???");
00720 return FALSE;
00721 }
00722 }
00723 #endif
00724 }
00725
00735 dbus_bool_t
00736 _dbus_group_info_fill (DBusGroupInfo *info,
00737 const DBusString *groupname,
00738 DBusError *error)
00739 {
00740 return fill_group_info (info, DBUS_GID_UNSET,
00741 groupname, error);
00742
00743 }
00744
00754 dbus_bool_t
00755 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00756 dbus_gid_t gid,
00757 DBusError *error)
00758 {
00759 return fill_group_info (info, gid, NULL, error);
00760 }
00761
00763
00775 dbus_bool_t
00776 _dbus_string_get_dirname (const DBusString *filename,
00777 DBusString *dirname)
00778 {
00779 int sep;
00780
00781 _dbus_assert (filename != dirname);
00782 _dbus_assert (filename != NULL);
00783 _dbus_assert (dirname != NULL);
00784
00785
00786 sep = _dbus_string_get_length (filename);
00787 if (sep == 0)
00788 return _dbus_string_append (dirname, ".");
00789
00790 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00791 --sep;
00792
00793 _dbus_assert (sep >= 0);
00794
00795 if (sep == 0)
00796 return _dbus_string_append (dirname, "/");
00797
00798
00799 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
00800 if (sep < 0)
00801 return _dbus_string_append (dirname, ".");
00802
00803
00804 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00805 --sep;
00806
00807 _dbus_assert (sep >= 0);
00808
00809 if (sep == 0 &&
00810 _dbus_string_get_byte (filename, 0) == '/')
00811 return _dbus_string_append (dirname, "/");
00812 else
00813 return _dbus_string_copy_len (filename, 0, sep - 0,
00814 dirname, _dbus_string_get_length (dirname));
00815 }
00817