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-internals.h"
00026 #include "dbus-protocol.h"
00027 #include "dbus-string.h"
00028 #define DBUS_USERDB_INCLUDES_PRIVATE 1
00029 #include "dbus-userdb.h"
00030 #include "dbus-test.h"
00031
00032 #include <sys/types.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <signal.h>
00036 #include <unistd.h>
00037 #include <stdio.h>
00038 #include <errno.h>
00039 #include <fcntl.h>
00040 #include <sys/stat.h>
00041 #include <grp.h>
00042 #include <sys/socket.h>
00043 #include <dirent.h>
00044 #include <sys/un.h>
00045 #include <sys/wait.h>
00046
00047 #ifndef O_BINARY
00048 #define O_BINARY 0
00049 #endif
00050
00064 dbus_bool_t
00065 _dbus_become_daemon (const DBusString *pidfile,
00066 int print_pid_fd,
00067 DBusError *error)
00068 {
00069 const char *s;
00070 pid_t child_pid;
00071 int dev_null_fd;
00072
00073 _dbus_verbose ("Becoming a daemon...\n");
00074
00075 _dbus_verbose ("chdir to /\n");
00076 if (chdir ("/") < 0)
00077 {
00078 dbus_set_error (error, DBUS_ERROR_FAILED,
00079 "Could not chdir() to root directory");
00080 return FALSE;
00081 }
00082
00083 _dbus_verbose ("forking...\n");
00084 switch ((child_pid = fork ()))
00085 {
00086 case -1:
00087 _dbus_verbose ("fork failed\n");
00088 dbus_set_error (error, _dbus_error_from_errno (errno),
00089 "Failed to fork daemon: %s", _dbus_strerror (errno));
00090 return FALSE;
00091 break;
00092
00093 case 0:
00094 _dbus_verbose ("in child, closing std file descriptors\n");
00095
00096
00097
00098
00099
00100
00101 dev_null_fd = open ("/dev/null", O_RDWR);
00102 if (dev_null_fd >= 0)
00103 {
00104 dup2 (dev_null_fd, 0);
00105 dup2 (dev_null_fd, 1);
00106
00107 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00108 if (s == NULL || *s == '\0')
00109 dup2 (dev_null_fd, 2);
00110 else
00111 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00112 }
00113
00114
00115 _dbus_verbose ("setting umask\n");
00116 umask (022);
00117 break;
00118
00119 default:
00120 if (pidfile)
00121 {
00122 _dbus_verbose ("parent writing pid file\n");
00123 if (!_dbus_write_pid_file (pidfile,
00124 child_pid,
00125 error))
00126 {
00127 _dbus_verbose ("pid file write failed, killing child\n");
00128 kill (child_pid, SIGTERM);
00129 return FALSE;
00130 }
00131 }
00132
00133
00134 if (print_pid_fd >= 0)
00135 {
00136 DBusString pid;
00137 int bytes;
00138
00139 if (!_dbus_string_init (&pid))
00140 {
00141 _DBUS_SET_OOM (error);
00142 kill (child_pid, SIGTERM);
00143 return FALSE;
00144 }
00145
00146 if (!_dbus_string_append_int (&pid, child_pid) ||
00147 !_dbus_string_append (&pid, "\n"))
00148 {
00149 _dbus_string_free (&pid);
00150 _DBUS_SET_OOM (error);
00151 kill (child_pid, SIGTERM);
00152 return FALSE;
00153 }
00154
00155 bytes = _dbus_string_get_length (&pid);
00156 if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
00157 {
00158 dbus_set_error (error, DBUS_ERROR_FAILED,
00159 "Printing message bus PID: %s\n",
00160 _dbus_strerror (errno));
00161 _dbus_string_free (&pid);
00162 kill (child_pid, SIGTERM);
00163 return FALSE;
00164 }
00165
00166 _dbus_string_free (&pid);
00167 }
00168 _dbus_verbose ("parent exiting\n");
00169 _exit (0);
00170 break;
00171 }
00172
00173 _dbus_verbose ("calling setsid()\n");
00174 if (setsid () == -1)
00175 _dbus_assert_not_reached ("setsid() failed");
00176
00177 return TRUE;
00178 }
00179
00180
00189 dbus_bool_t
00190 _dbus_write_pid_file (const DBusString *filename,
00191 unsigned long pid,
00192 DBusError *error)
00193 {
00194 const char *cfilename;
00195 int fd;
00196 FILE *f;
00197
00198 cfilename = _dbus_string_get_const_data (filename);
00199
00200 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00201
00202 if (fd < 0)
00203 {
00204 dbus_set_error (error, _dbus_error_from_errno (errno),
00205 "Failed to open \"%s\": %s", cfilename,
00206 _dbus_strerror (errno));
00207 return FALSE;
00208 }
00209
00210 if ((f = fdopen (fd, "w")) == NULL)
00211 {
00212 dbus_set_error (error, _dbus_error_from_errno (errno),
00213 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00214 _dbus_close (fd, NULL);
00215 return FALSE;
00216 }
00217
00218 if (fprintf (f, "%lu\n", pid) < 0)
00219 {
00220 dbus_set_error (error, _dbus_error_from_errno (errno),
00221 "Failed to write to \"%s\": %s", cfilename,
00222 _dbus_strerror (errno));
00223
00224 fclose (f);
00225 return FALSE;
00226 }
00227
00228 if (fclose (f) == EOF)
00229 {
00230 dbus_set_error (error, _dbus_error_from_errno (errno),
00231 "Failed to close \"%s\": %s", cfilename,
00232 _dbus_strerror (errno));
00233 return FALSE;
00234 }
00235
00236 return TRUE;
00237 }
00238
00239
00248 dbus_bool_t
00249 _dbus_change_identity (dbus_uid_t uid,
00250 dbus_gid_t gid,
00251 DBusError *error)
00252 {
00253
00254
00255
00256
00257
00258
00259
00260 if (setgroups (0, NULL) < 0)
00261 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00262 _dbus_strerror (errno));
00263
00264
00265
00266
00267 if (setgid (gid) < 0)
00268 {
00269 dbus_set_error (error, _dbus_error_from_errno (errno),
00270 "Failed to set GID to %lu: %s", gid,
00271 _dbus_strerror (errno));
00272 return FALSE;
00273 }
00274
00275 if (setuid (uid) < 0)
00276 {
00277 dbus_set_error (error, _dbus_error_from_errno (errno),
00278 "Failed to set UID to %lu: %s", uid,
00279 _dbus_strerror (errno));
00280 return FALSE;
00281 }
00282
00283 return TRUE;
00284 }
00285
00291 void
00292 _dbus_set_signal_handler (int sig,
00293 DBusSignalHandler handler)
00294 {
00295 struct sigaction act;
00296 sigset_t empty_mask;
00297
00298 sigemptyset (&empty_mask);
00299 act.sa_handler = handler;
00300 act.sa_mask = empty_mask;
00301 act.sa_flags = 0;
00302 sigaction (sig, &act, NULL);
00303 }
00304
00305
00313 dbus_bool_t
00314 _dbus_delete_directory (const DBusString *filename,
00315 DBusError *error)
00316 {
00317 const char *filename_c;
00318
00319 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00320
00321 filename_c = _dbus_string_get_const_data (filename);
00322
00323 if (rmdir (filename_c) != 0)
00324 {
00325 dbus_set_error (error, DBUS_ERROR_FAILED,
00326 "Failed to remove directory %s: %s\n",
00327 filename_c, _dbus_strerror (errno));
00328 return FALSE;
00329 }
00330
00331 return TRUE;
00332 }
00333
00339 dbus_bool_t
00340 _dbus_file_exists (const char *file)
00341 {
00342 return (access (file, F_OK) == 0);
00343 }
00344
00351 dbus_bool_t
00352 _dbus_user_at_console (const char *username,
00353 DBusError *error)
00354 {
00355
00356 DBusString f;
00357 dbus_bool_t result;
00358 int console;
00359 pid_t fgconsole;
00360
00361 result = FALSE;
00362
00363 fgconsole = fork();
00364 if (fgconsole == 0)
00365 {
00366 execl (DBUS_FOREGROUND_CONSOLE_COMMAND, DBUS_FOREGROUND_CONSOLE_COMMAND, NULL);
00367 exit (0);
00368 } else if (fgconsole < 0)
00369 {
00370 dbus_set_error (error, DBUS_ERROR_FAILED,
00371 "Failed to fork(): %s\n", _dbus_strerror (errno));
00372 return FALSE;
00373 }
00374
00375 if (wait (&console) < 0 || !WIFEXITED (console))
00376 {
00377 dbus_set_error (error, DBUS_ERROR_FAILED,
00378 "Failed to execute %s: %s\n",
00379 DBUS_FOREGROUND_CONSOLE_COMMAND, _dbus_strerror (errno));
00380 return FALSE;
00381 }
00382
00383 console = WEXITSTATUS(console);
00384
00385
00386 if (console == 0)
00387 {
00388 return FALSE;
00389 }
00390
00391
00392 if (!_dbus_string_init (&f))
00393 {
00394 _DBUS_SET_OOM (error);
00395 return FALSE;
00396 }
00397
00398 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00399 {
00400 _DBUS_SET_OOM (error);
00401 goto out;
00402 }
00403
00404
00405 if (!_dbus_string_append (&f, username))
00406 {
00407 _DBUS_SET_OOM (error);
00408 goto out;
00409 }
00410
00411
00412 if (!_dbus_string_append (&f, ":"))
00413 {
00414 _DBUS_SET_OOM (error);
00415 goto out;
00416 }
00417
00418 if (!_dbus_string_append_int (&f, console))
00419 {
00420 _DBUS_SET_OOM (error);
00421 goto out;
00422 }
00423
00424 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00425
00426 out:
00427 _dbus_string_free (&f);
00428
00429 return result;
00430 }
00431
00432
00439 dbus_bool_t
00440 _dbus_path_is_absolute (const DBusString *filename)
00441 {
00442 if (_dbus_string_get_length (filename) > 0)
00443 return _dbus_string_get_byte (filename, 0) == '/';
00444 else
00445 return FALSE;
00446 }
00447
00456 dbus_bool_t
00457 _dbus_stat (const DBusString *filename,
00458 DBusStat *statbuf,
00459 DBusError *error)
00460 {
00461 const char *filename_c;
00462 struct stat sb;
00463
00464 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00465
00466 filename_c = _dbus_string_get_const_data (filename);
00467
00468 if (stat (filename_c, &sb) < 0)
00469 {
00470 dbus_set_error (error, _dbus_error_from_errno (errno),
00471 "%s", _dbus_strerror (errno));
00472 return FALSE;
00473 }
00474
00475 statbuf->mode = sb.st_mode;
00476 statbuf->nlink = sb.st_nlink;
00477 statbuf->uid = sb.st_uid;
00478 statbuf->gid = sb.st_gid;
00479 statbuf->size = sb.st_size;
00480 statbuf->atime = sb.st_atime;
00481 statbuf->mtime = sb.st_mtime;
00482 statbuf->ctime = sb.st_ctime;
00483
00484 return TRUE;
00485 }
00486
00487
00491 struct DBusDirIter
00492 {
00493 DIR *d;
00495 };
00496
00504 DBusDirIter*
00505 _dbus_directory_open (const DBusString *filename,
00506 DBusError *error)
00507 {
00508 DIR *d;
00509 DBusDirIter *iter;
00510 const char *filename_c;
00511
00512 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00513
00514 filename_c = _dbus_string_get_const_data (filename);
00515
00516 d = opendir (filename_c);
00517 if (d == NULL)
00518 {
00519 dbus_set_error (error, _dbus_error_from_errno (errno),
00520 "Failed to read directory \"%s\": %s",
00521 filename_c,
00522 _dbus_strerror (errno));
00523 return NULL;
00524 }
00525 iter = dbus_new0 (DBusDirIter, 1);
00526 if (iter == NULL)
00527 {
00528 closedir (d);
00529 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00530 "Could not allocate memory for directory iterator");
00531 return NULL;
00532 }
00533
00534 iter->d = d;
00535
00536 return iter;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 static dbus_bool_t
00548 dirent_buf_size(DIR * dirp, size_t *size)
00549 {
00550 long name_max;
00551 # if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) \
00552 && defined(_PC_NAME_MAX)
00553 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00554 if (name_max == -1)
00555 # if defined(NAME_MAX)
00556 name_max = NAME_MAX;
00557 # else
00558 return FALSE;
00559 # endif
00560 # else
00561 # if defined(NAME_MAX)
00562 name_max = NAME_MAX;
00563 # else
00564 # error "buffer size for readdir_r cannot be determined"
00565 # endif
00566 # endif
00567 if (size)
00568 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00569 else
00570 return FALSE;
00571
00572 return TRUE;
00573 }
00574
00585 dbus_bool_t
00586 _dbus_directory_get_next_file (DBusDirIter *iter,
00587 DBusString *filename,
00588 DBusError *error)
00589 {
00590 struct dirent *d, *ent;
00591 size_t buf_size;
00592 int err;
00593
00594 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00595
00596 if (!dirent_buf_size (iter->d, &buf_size))
00597 {
00598 dbus_set_error (error, DBUS_ERROR_FAILED,
00599 "Can't calculate buffer size when reading directory");
00600 return FALSE;
00601 }
00602
00603 d = (struct dirent *)dbus_malloc (buf_size);
00604 if (!d)
00605 {
00606 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00607 "No memory to read directory entry");
00608 return FALSE;
00609 }
00610
00611 again:
00612 err = readdir_r (iter->d, d, &ent);
00613 if (err || !ent)
00614 {
00615 if (err != 0)
00616 dbus_set_error (error,
00617 _dbus_error_from_errno (err),
00618 "%s", _dbus_strerror (err));
00619
00620 dbus_free (d);
00621 return FALSE;
00622 }
00623 else if (ent->d_name[0] == '.' &&
00624 (ent->d_name[1] == '\0' ||
00625 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00626 goto again;
00627 else
00628 {
00629 _dbus_string_set_length (filename, 0);
00630 if (!_dbus_string_append (filename, ent->d_name))
00631 {
00632 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00633 "No memory to read directory entry");
00634 dbus_free (d);
00635 return FALSE;
00636 }
00637 else
00638 {
00639 dbus_free (d);
00640 return TRUE;
00641 }
00642 }
00643 }
00644
00648 void
00649 _dbus_directory_close (DBusDirIter *iter)
00650 {
00651 closedir (iter->d);
00652 dbus_free (iter);
00653 }
00654
00655 static dbus_bool_t
00656 fill_user_info_from_group (struct group *g,
00657 DBusGroupInfo *info,
00658 DBusError *error)
00659 {
00660 _dbus_assert (g->gr_name != NULL);
00661
00662 info->gid = g->gr_gid;
00663 info->groupname = _dbus_strdup (g->gr_name);
00664
00665
00666
00667 if (info->groupname == NULL)
00668 {
00669 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00670 return FALSE;
00671 }
00672
00673 return TRUE;
00674 }
00675
00676 static dbus_bool_t
00677 fill_group_info (DBusGroupInfo *info,
00678 dbus_gid_t gid,
00679 const DBusString *groupname,
00680 DBusError *error)
00681 {
00682 const char *group_c_str;
00683
00684 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00685 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00686
00687 if (groupname)
00688 group_c_str = _dbus_string_get_const_data (groupname);
00689 else
00690 group_c_str = NULL;
00691
00692
00693
00694
00695
00696
00697 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00698 {
00699 struct group *g;
00700 int result;
00701 char buf[1024];
00702 struct group g_str;
00703
00704 g = NULL;
00705 #ifdef HAVE_POSIX_GETPWNAM_R
00706
00707 if (group_c_str)
00708 result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00709 &g);
00710 else
00711 result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00712 &g);
00713 #else
00714 g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00715 result = 0;
00716 #endif
00717 if (result == 0 && g == &g_str)
00718 {
00719 return fill_user_info_from_group (g, info, error);
00720 }
00721 else
00722 {
00723 dbus_set_error (error, _dbus_error_from_errno (errno),
00724 "Group %s unknown or failed to look it up\n",
00725 group_c_str ? group_c_str : "???");
00726 return FALSE;
00727 }
00728 }
00729 #else
00730 {
00731
00732 struct group *g;
00733
00734 g = getgrnam (group_c_str);
00735
00736 if (g != NULL)
00737 {
00738 return fill_user_info_from_group (g, info, error);
00739 }
00740 else
00741 {
00742 dbus_set_error (error, _dbus_error_from_errno (errno),
00743 "Group %s unknown or failed to look it up\n",
00744 group_c_str ? group_c_str : "???");
00745 return FALSE;
00746 }
00747 }
00748 #endif
00749 }
00750
00760 dbus_bool_t
00761 _dbus_group_info_fill (DBusGroupInfo *info,
00762 const DBusString *groupname,
00763 DBusError *error)
00764 {
00765 return fill_group_info (info, DBUS_GID_UNSET,
00766 groupname, error);
00767
00768 }
00769
00779 dbus_bool_t
00780 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00781 dbus_gid_t gid,
00782 DBusError *error)
00783 {
00784 return fill_group_info (info, gid, NULL, error);
00785 }
00786
00788
00800 dbus_bool_t
00801 _dbus_string_get_dirname (const DBusString *filename,
00802 DBusString *dirname)
00803 {
00804 int sep;
00805
00806 _dbus_assert (filename != dirname);
00807 _dbus_assert (filename != NULL);
00808 _dbus_assert (dirname != NULL);
00809
00810
00811 sep = _dbus_string_get_length (filename);
00812 if (sep == 0)
00813 return _dbus_string_append (dirname, ".");
00814
00815 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00816 --sep;
00817
00818 _dbus_assert (sep >= 0);
00819
00820 if (sep == 0)
00821 return _dbus_string_append (dirname, "/");
00822
00823
00824 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
00825 if (sep < 0)
00826 return _dbus_string_append (dirname, ".");
00827
00828
00829 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00830 --sep;
00831
00832 _dbus_assert (sep >= 0);
00833
00834 if (sep == 0 &&
00835 _dbus_string_get_byte (filename, 0) == '/')
00836 return _dbus_string_append (dirname, "/");
00837 else
00838 return _dbus_string_copy_len (filename, 0, sep - 0,
00839 dirname, _dbus_string_get_length (dirname));
00840 }
00842