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