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 <pwd.h>
00043 #include <grp.h>
00044 #include <sys/socket.h>
00045 #include <dirent.h>
00046 #include <sys/un.h>
00047 #include <syslog.h>
00048 #ifdef HAVE_LIBAUDIT
00049 #include <sys/prctl.h>
00050 #include <sys/capability.h>
00051 #include <libaudit.h>
00052 #endif
00053
00054 #ifdef HAVE_SYS_SYSLIMITS_H
00055 #include <sys/syslimits.h>
00056 #endif
00057
00058 #ifndef O_BINARY
00059 #define O_BINARY 0
00060 #endif
00061
00077 dbus_bool_t
00078 _dbus_become_daemon (const DBusString *pidfile,
00079 DBusPipe *print_pid_pipe,
00080 DBusError *error,
00081 dbus_bool_t keep_umask)
00082 {
00083 const char *s;
00084 pid_t child_pid;
00085 int dev_null_fd;
00086
00087 _dbus_verbose ("Becoming a daemon...\n");
00088
00089 _dbus_verbose ("chdir to /\n");
00090 if (chdir ("/") < 0)
00091 {
00092 dbus_set_error (error, DBUS_ERROR_FAILED,
00093 "Could not chdir() to root directory");
00094 return FALSE;
00095 }
00096
00097 _dbus_verbose ("forking...\n");
00098 switch ((child_pid = fork ()))
00099 {
00100 case -1:
00101 _dbus_verbose ("fork failed\n");
00102 dbus_set_error (error, _dbus_error_from_errno (errno),
00103 "Failed to fork daemon: %s", _dbus_strerror (errno));
00104 return FALSE;
00105 break;
00106
00107 case 0:
00108 _dbus_verbose ("in child, closing std file descriptors\n");
00109
00110
00111
00112
00113
00114
00115 dev_null_fd = open ("/dev/null", O_RDWR);
00116 if (dev_null_fd >= 0)
00117 {
00118 dup2 (dev_null_fd, 0);
00119 dup2 (dev_null_fd, 1);
00120
00121 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00122 if (s == NULL || *s == '\0')
00123 dup2 (dev_null_fd, 2);
00124 else
00125 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00126 }
00127
00128 if (!keep_umask)
00129 {
00130
00131 _dbus_verbose ("setting umask\n");
00132 umask (022);
00133 }
00134
00135 _dbus_verbose ("calling setsid()\n");
00136 if (setsid () == -1)
00137 _dbus_assert_not_reached ("setsid() failed");
00138
00139 break;
00140
00141 default:
00142 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
00143 child_pid, error))
00144 {
00145 _dbus_verbose ("pid file or pipe write failed: %s\n",
00146 error->message);
00147 kill (child_pid, SIGTERM);
00148 return FALSE;
00149 }
00150
00151 _dbus_verbose ("parent exiting\n");
00152 _exit (0);
00153 break;
00154 }
00155
00156 return TRUE;
00157 }
00158
00159
00168 static dbus_bool_t
00169 _dbus_write_pid_file (const DBusString *filename,
00170 unsigned long pid,
00171 DBusError *error)
00172 {
00173 const char *cfilename;
00174 int fd;
00175 FILE *f;
00176
00177 cfilename = _dbus_string_get_const_data (filename);
00178
00179 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00180
00181 if (fd < 0)
00182 {
00183 dbus_set_error (error, _dbus_error_from_errno (errno),
00184 "Failed to open \"%s\": %s", cfilename,
00185 _dbus_strerror (errno));
00186 return FALSE;
00187 }
00188
00189 if ((f = fdopen (fd, "w")) == NULL)
00190 {
00191 dbus_set_error (error, _dbus_error_from_errno (errno),
00192 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00193 _dbus_close (fd, NULL);
00194 return FALSE;
00195 }
00196
00197 if (fprintf (f, "%lu\n", pid) < 0)
00198 {
00199 dbus_set_error (error, _dbus_error_from_errno (errno),
00200 "Failed to write to \"%s\": %s", cfilename,
00201 _dbus_strerror (errno));
00202
00203 fclose (f);
00204 return FALSE;
00205 }
00206
00207 if (fclose (f) == EOF)
00208 {
00209 dbus_set_error (error, _dbus_error_from_errno (errno),
00210 "Failed to close \"%s\": %s", cfilename,
00211 _dbus_strerror (errno));
00212 return FALSE;
00213 }
00214
00215 return TRUE;
00216 }
00217
00229 dbus_bool_t
00230 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
00231 DBusPipe *print_pid_pipe,
00232 dbus_pid_t pid_to_write,
00233 DBusError *error)
00234 {
00235 if (pidfile)
00236 {
00237 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
00238 if (!_dbus_write_pid_file (pidfile,
00239 pid_to_write,
00240 error))
00241 {
00242 _dbus_verbose ("pid file write failed\n");
00243 _DBUS_ASSERT_ERROR_IS_SET(error);
00244 return FALSE;
00245 }
00246 }
00247 else
00248 {
00249 _dbus_verbose ("No pid file requested\n");
00250 }
00251
00252 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00253 {
00254 DBusString pid;
00255 int bytes;
00256
00257 _dbus_verbose ("writing our pid to pipe %d\n", print_pid_pipe->fd_or_handle);
00258
00259 if (!_dbus_string_init (&pid))
00260 {
00261 _DBUS_SET_OOM (error);
00262 return FALSE;
00263 }
00264
00265 if (!_dbus_string_append_int (&pid, pid_to_write) ||
00266 !_dbus_string_append (&pid, "\n"))
00267 {
00268 _dbus_string_free (&pid);
00269 _DBUS_SET_OOM (error);
00270 return FALSE;
00271 }
00272
00273 bytes = _dbus_string_get_length (&pid);
00274 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00275 {
00276
00277 if (error != NULL && !dbus_error_is_set(error))
00278 {
00279 dbus_set_error (error, DBUS_ERROR_FAILED,
00280 "Printing message bus PID: did not write enough bytes\n");
00281 }
00282 _dbus_string_free (&pid);
00283 return FALSE;
00284 }
00285
00286 _dbus_string_free (&pid);
00287 }
00288 else
00289 {
00290 _dbus_verbose ("No pid pipe to write to\n");
00291 }
00292
00293 return TRUE;
00294 }
00295
00302 dbus_bool_t
00303 _dbus_verify_daemon_user (const char *user)
00304 {
00305 DBusString u;
00306
00307 _dbus_string_init_const (&u, user);
00308
00309 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00310 }
00311
00319 dbus_bool_t
00320 _dbus_change_to_daemon_user (const char *user,
00321 DBusError *error)
00322 {
00323 dbus_uid_t uid;
00324 dbus_gid_t gid;
00325 DBusString u;
00326 #ifdef HAVE_LIBAUDIT
00327 dbus_bool_t we_were_root;
00328 cap_t new_caps;
00329 #endif
00330
00331 _dbus_string_init_const (&u, user);
00332
00333 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00334 {
00335 dbus_set_error (error, DBUS_ERROR_FAILED,
00336 "User '%s' does not appear to exist?",
00337 user);
00338 return FALSE;
00339 }
00340
00341 #ifdef HAVE_LIBAUDIT
00342 we_were_root = _dbus_geteuid () == 0;
00343 new_caps = NULL;
00344
00345
00346
00347
00348 if (we_were_root)
00349 {
00350 cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
00351 cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
00352 cap_t tmp_caps = cap_init();
00353
00354 if (!tmp_caps || !(new_caps = cap_init ()))
00355 {
00356 dbus_set_error (error, DBUS_ERROR_FAILED,
00357 "Failed to initialize drop of capabilities: %s\n",
00358 _dbus_strerror (errno));
00359
00360 if (tmp_caps)
00361 cap_free (tmp_caps);
00362
00363 return FALSE;
00364 }
00365
00366
00367 cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
00368 cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
00369 cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
00370 cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
00371
00372 if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
00373 {
00374 dbus_set_error (error, _dbus_error_from_errno (errno),
00375 "Failed to set keep-capabilities: %s\n",
00376 _dbus_strerror (errno));
00377 cap_free (tmp_caps);
00378 goto fail;
00379 }
00380
00381 if (cap_set_proc (tmp_caps) == -1)
00382 {
00383 dbus_set_error (error, DBUS_ERROR_FAILED,
00384 "Failed to drop capabilities: %s\n",
00385 _dbus_strerror (errno));
00386 cap_free (tmp_caps);
00387 goto fail;
00388 }
00389 cap_free (tmp_caps);
00390 }
00391 #endif
00392
00393
00394 #if 0
00395
00396
00397
00398
00399
00400
00401
00402 if (setgroups (0, NULL) < 0)
00403 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00404 _dbus_strerror (errno));
00405
00406 #endif
00407
00408 struct passwd *pw = getpwuid (uid);
00409 if (pw == NULL)
00410 {
00411 dbus_set_error (error, _dbus_error_from_errno (errno),
00412 "getpwuid () for UID '%d' failed: %s", uid,
00413 _dbus_strerror (errno));
00414 return FALSE;
00415 }
00416
00417 if (initgroups (pw->pw_name, pw->pw_gid) < 0)
00418 {
00419 dbus_set_error (error, _dbus_error_from_errno (errno),
00420 "initgroups () failed: %s",
00421 _dbus_strerror (errno));
00422 return FALSE;
00423 }
00424
00425
00426
00427
00428 if (setgid (gid) < 0)
00429 {
00430 dbus_set_error (error, _dbus_error_from_errno (errno),
00431 "Failed to set GID to %lu: %s", gid,
00432 _dbus_strerror (errno));
00433 goto fail;
00434 }
00435
00436 if (setuid (uid) < 0)
00437 {
00438 dbus_set_error (error, _dbus_error_from_errno (errno),
00439 "Failed to set UID to %lu: %s", uid,
00440 _dbus_strerror (errno));
00441 goto fail;
00442 }
00443
00444 #ifdef HAVE_LIBAUDIT
00445 if (we_were_root)
00446 {
00447 if (cap_set_proc (new_caps))
00448 {
00449 dbus_set_error (error, DBUS_ERROR_FAILED,
00450 "Failed to drop capabilities: %s\n",
00451 _dbus_strerror (errno));
00452 goto fail;
00453 }
00454 cap_free (new_caps);
00455
00456
00457 if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
00458 {
00459 dbus_set_error (error, _dbus_error_from_errno (errno),
00460 "Failed to unset keep-capabilities: %s\n",
00461 _dbus_strerror (errno));
00462 return FALSE;
00463 }
00464 }
00465 #endif
00466
00467 return TRUE;
00468
00469 fail:
00470 #ifdef HAVE_LIBAUDIT
00471 if (!we_were_root)
00472 {
00473
00474 prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0);
00475 cap_free (new_caps);
00476 }
00477 #endif
00478
00479 return FALSE;
00480 }
00481
00482 void
00483 _dbus_init_system_log (void)
00484 {
00485 openlog ("dbus", LOG_PID, LOG_DAEMON);
00486 }
00487
00495 void
00496 _dbus_log_info (const char *msg, va_list args)
00497 {
00498 vsyslog (LOG_DAEMON|LOG_NOTICE, msg, args);
00499 }
00500
00508 void
00509 _dbus_log_security (const char *msg, va_list args)
00510 {
00511 vsyslog (LOG_AUTH|LOG_NOTICE, msg, args);
00512 }
00513
00519 void
00520 _dbus_set_signal_handler (int sig,
00521 DBusSignalHandler handler)
00522 {
00523 struct sigaction act;
00524 sigset_t empty_mask;
00525
00526 sigemptyset (&empty_mask);
00527 act.sa_handler = handler;
00528 act.sa_mask = empty_mask;
00529 act.sa_flags = 0;
00530 sigaction (sig, &act, NULL);
00531 }
00532
00533
00541 dbus_bool_t
00542 _dbus_delete_directory (const DBusString *filename,
00543 DBusError *error)
00544 {
00545 const char *filename_c;
00546
00547 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00548
00549 filename_c = _dbus_string_get_const_data (filename);
00550
00551 if (rmdir (filename_c) != 0)
00552 {
00553 dbus_set_error (error, DBUS_ERROR_FAILED,
00554 "Failed to remove directory %s: %s\n",
00555 filename_c, _dbus_strerror (errno));
00556 return FALSE;
00557 }
00558
00559 return TRUE;
00560 }
00561
00567 dbus_bool_t
00568 _dbus_file_exists (const char *file)
00569 {
00570 return (access (file, F_OK) == 0);
00571 }
00572
00579 dbus_bool_t
00580 _dbus_user_at_console (const char *username,
00581 DBusError *error)
00582 {
00583
00584 DBusString f;
00585 dbus_bool_t result;
00586
00587 result = FALSE;
00588 if (!_dbus_string_init (&f))
00589 {
00590 _DBUS_SET_OOM (error);
00591 return FALSE;
00592 }
00593
00594 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00595 {
00596 _DBUS_SET_OOM (error);
00597 goto out;
00598 }
00599
00600
00601 if (!_dbus_string_append (&f, username))
00602 {
00603 _DBUS_SET_OOM (error);
00604 goto out;
00605 }
00606
00607 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00608
00609 out:
00610 _dbus_string_free (&f);
00611
00612 return result;
00613 }
00614
00615
00622 dbus_bool_t
00623 _dbus_path_is_absolute (const DBusString *filename)
00624 {
00625 if (_dbus_string_get_length (filename) > 0)
00626 return _dbus_string_get_byte (filename, 0) == '/';
00627 else
00628 return FALSE;
00629 }
00630
00639 dbus_bool_t
00640 _dbus_stat (const DBusString *filename,
00641 DBusStat *statbuf,
00642 DBusError *error)
00643 {
00644 const char *filename_c;
00645 struct stat sb;
00646
00647 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00648
00649 filename_c = _dbus_string_get_const_data (filename);
00650
00651 if (stat (filename_c, &sb) < 0)
00652 {
00653 dbus_set_error (error, _dbus_error_from_errno (errno),
00654 "%s", _dbus_strerror (errno));
00655 return FALSE;
00656 }
00657
00658 statbuf->mode = sb.st_mode;
00659 statbuf->nlink = sb.st_nlink;
00660 statbuf->uid = sb.st_uid;
00661 statbuf->gid = sb.st_gid;
00662 statbuf->size = sb.st_size;
00663 statbuf->atime = sb.st_atime;
00664 statbuf->mtime = sb.st_mtime;
00665 statbuf->ctime = sb.st_ctime;
00666
00667 return TRUE;
00668 }
00669
00670
00674 struct DBusDirIter
00675 {
00676 DIR *d;
00678 };
00679
00687 DBusDirIter*
00688 _dbus_directory_open (const DBusString *filename,
00689 DBusError *error)
00690 {
00691 DIR *d;
00692 DBusDirIter *iter;
00693 const char *filename_c;
00694
00695 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00696
00697 filename_c = _dbus_string_get_const_data (filename);
00698
00699 d = opendir (filename_c);
00700 if (d == NULL)
00701 {
00702 dbus_set_error (error, _dbus_error_from_errno (errno),
00703 "Failed to read directory \"%s\": %s",
00704 filename_c,
00705 _dbus_strerror (errno));
00706 return NULL;
00707 }
00708 iter = dbus_new0 (DBusDirIter, 1);
00709 if (iter == NULL)
00710 {
00711 closedir (d);
00712 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00713 "Could not allocate memory for directory iterator");
00714 return NULL;
00715 }
00716
00717 iter->d = d;
00718
00719 return iter;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 static dbus_bool_t
00731 dirent_buf_size(DIR * dirp, size_t *size)
00732 {
00733 long name_max = NAME_MAX;
00734 #if 0
00735 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00736 # if defined(HAVE_DIRFD)
00737 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00738 # elif defined(HAVE_DDFD)
00739 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00740 # else
00741 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00742 # endif
00743 if (name_max == -1)
00744 # if defined(NAME_MAX)
00745 name_max = NAME_MAX;
00746 # else
00747 return FALSE;
00748 # endif
00749 # elif defined(MAXNAMELEN)
00750 name_max = MAXNAMELEN;
00751 # else
00752 # if defined(NAME_MAX)
00753 name_max = NAME_MAX;
00754 # else
00755 # error "buffer size for readdir_r cannot be determined"
00756 # endif
00757 # endif
00758 #endif
00759 if (size)
00760 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00761 else
00762 return FALSE;
00763
00764 return TRUE;
00765 }
00766
00777 dbus_bool_t
00778 _dbus_directory_get_next_file (DBusDirIter *iter,
00779 DBusString *filename,
00780 DBusError *error)
00781 {
00782 struct dirent *d, *ent;
00783 size_t buf_size;
00784 int err;
00785
00786 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00787
00788 if (!dirent_buf_size (iter->d, &buf_size))
00789 {
00790 dbus_set_error (error, DBUS_ERROR_FAILED,
00791 "Can't calculate buffer size when reading directory");
00792 return FALSE;
00793 }
00794
00795 d = (struct dirent *)dbus_malloc (buf_size);
00796 if (!d)
00797 {
00798 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00799 "No memory to read directory entry");
00800 return FALSE;
00801 }
00802
00803 again:
00804 err = readdir_r (iter->d, d, &ent);
00805 if (err || !ent)
00806 {
00807 if (err != 0)
00808 dbus_set_error (error,
00809 _dbus_error_from_errno (err),
00810 "%s", _dbus_strerror (err));
00811
00812 dbus_free (d);
00813 return FALSE;
00814 }
00815 else if (ent->d_name[0] == '.' &&
00816 (ent->d_name[1] == '\0' ||
00817 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00818 goto again;
00819 else
00820 {
00821 _dbus_string_set_length (filename, 0);
00822 if (!_dbus_string_append (filename, ent->d_name))
00823 {
00824 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00825 "No memory to read directory entry");
00826 dbus_free (d);
00827 return FALSE;
00828 }
00829 else
00830 {
00831 dbus_free (d);
00832 return TRUE;
00833 }
00834 }
00835 }
00836
00840 void
00841 _dbus_directory_close (DBusDirIter *iter)
00842 {
00843 closedir (iter->d);
00844 dbus_free (iter);
00845 }
00846
00847 static dbus_bool_t
00848 fill_user_info_from_group (struct group *g,
00849 DBusGroupInfo *info,
00850 DBusError *error)
00851 {
00852 _dbus_assert (g->gr_name != NULL);
00853
00854 info->gid = g->gr_gid;
00855 info->groupname = _dbus_strdup (g->gr_name);
00856
00857
00858
00859 if (info->groupname == NULL)
00860 {
00861 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00862 return FALSE;
00863 }
00864
00865 return TRUE;
00866 }
00867
00868 static dbus_bool_t
00869 fill_group_info (DBusGroupInfo *info,
00870 dbus_gid_t gid,
00871 const DBusString *groupname,
00872 DBusError *error)
00873 {
00874 const char *group_c_str;
00875
00876 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00877 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00878
00879 if (groupname)
00880 group_c_str = _dbus_string_get_const_data (groupname);
00881 else
00882 group_c_str = NULL;
00883
00884
00885
00886
00887
00888
00889 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00890 {
00891 struct group *g;
00892 int result;
00893 size_t buflen;
00894 char *buf;
00895 struct group g_str;
00896 dbus_bool_t b;
00897
00898
00899 buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
00900
00901
00902
00903
00904
00905 if ((long) buflen <= 0)
00906 buflen = 1024;
00907
00908 result = -1;
00909 while (1)
00910 {
00911 buf = dbus_malloc (buflen);
00912 if (buf == NULL)
00913 {
00914 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00915 return FALSE;
00916 }
00917
00918 g = NULL;
00919 #ifdef HAVE_POSIX_GETPWNAM_R
00920 if (group_c_str)
00921 result = getgrnam_r (group_c_str, &g_str, buf, buflen,
00922 &g);
00923 else
00924 result = getgrgid_r (gid, &g_str, buf, buflen,
00925 &g);
00926 #else
00927 g = getgrnam_r (group_c_str, &g_str, buf, buflen);
00928 result = 0;
00929 #endif
00930
00931
00932
00933 if (result == ERANGE && buflen < 512 * 1024)
00934 {
00935 dbus_free (buf);
00936 buflen *= 2;
00937 }
00938 else
00939 {
00940 break;
00941 }
00942 }
00943
00944 if (result == 0 && g == &g_str)
00945 {
00946 b = fill_user_info_from_group (g, info, error);
00947 dbus_free (buf);
00948 return b;
00949 }
00950 else
00951 {
00952 dbus_set_error (error, _dbus_error_from_errno (errno),
00953 "Group %s unknown or failed to look it up\n",
00954 group_c_str ? group_c_str : "???");
00955 dbus_free (buf);
00956 return FALSE;
00957 }
00958 }
00959 #else
00960 {
00961
00962 struct group *g;
00963
00964 g = getgrnam (group_c_str);
00965
00966 if (g != NULL)
00967 {
00968 return fill_user_info_from_group (g, info, error);
00969 }
00970 else
00971 {
00972 dbus_set_error (error, _dbus_error_from_errno (errno),
00973 "Group %s unknown or failed to look it up\n",
00974 group_c_str ? group_c_str : "???");
00975 return FALSE;
00976 }
00977 }
00978 #endif
00979 }
00980
00990 dbus_bool_t
00991 _dbus_group_info_fill (DBusGroupInfo *info,
00992 const DBusString *groupname,
00993 DBusError *error)
00994 {
00995 return fill_group_info (info, DBUS_GID_UNSET,
00996 groupname, error);
00997
00998 }
00999
01009 dbus_bool_t
01010 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01011 dbus_gid_t gid,
01012 DBusError *error)
01013 {
01014 return fill_group_info (info, gid, NULL, error);
01015 }
01016
01025 dbus_bool_t
01026 _dbus_parse_unix_user_from_config (const DBusString *username,
01027 dbus_uid_t *uid_p)
01028 {
01029 return _dbus_get_user_id (username, uid_p);
01030
01031 }
01032
01041 dbus_bool_t
01042 _dbus_parse_unix_group_from_config (const DBusString *groupname,
01043 dbus_gid_t *gid_p)
01044 {
01045 return _dbus_get_group_id (groupname, gid_p);
01046 }
01047
01058 dbus_bool_t
01059 _dbus_unix_groups_from_uid (dbus_uid_t uid,
01060 dbus_gid_t **group_ids,
01061 int *n_group_ids)
01062 {
01063 return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
01064 }
01065
01075 dbus_bool_t
01076 _dbus_unix_user_is_at_console (dbus_uid_t uid,
01077 DBusError *error)
01078 {
01079 return _dbus_is_console_user (uid, error);
01080
01081 }
01082
01090 dbus_bool_t
01091 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
01092 {
01093 return uid == _dbus_geteuid ();
01094 }
01095
01103 dbus_bool_t
01104 _dbus_windows_user_is_process_owner (const char *windows_sid)
01105 {
01106 return FALSE;
01107 }
01108
01110
01122 dbus_bool_t
01123 _dbus_string_get_dirname (const DBusString *filename,
01124 DBusString *dirname)
01125 {
01126 int sep;
01127
01128 _dbus_assert (filename != dirname);
01129 _dbus_assert (filename != NULL);
01130 _dbus_assert (dirname != NULL);
01131
01132
01133 sep = _dbus_string_get_length (filename);
01134 if (sep == 0)
01135 return _dbus_string_append (dirname, ".");
01136
01137 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01138 --sep;
01139
01140 _dbus_assert (sep >= 0);
01141
01142 if (sep == 0)
01143 return _dbus_string_append (dirname, "/");
01144
01145
01146 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01147 if (sep < 0)
01148 return _dbus_string_append (dirname, ".");
01149
01150
01151 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01152 --sep;
01153
01154 _dbus_assert (sep >= 0);
01155
01156 if (sep == 0 &&
01157 _dbus_string_get_byte (filename, 0) == '/')
01158 return _dbus_string_append (dirname, "/");
01159 else
01160 return _dbus_string_copy_len (filename, 0, sep - 0,
01161 dirname, _dbus_string_get_length (dirname));
01162 }
01164
01165 static void
01166 string_squash_nonprintable (DBusString *str)
01167 {
01168 char *buf;
01169 int i, len;
01170
01171 buf = _dbus_string_get_data (str);
01172 len = _dbus_string_get_length (str);
01173
01174 for (i = 0; i < len; i++)
01175 if (buf[i] == '\0')
01176 buf[i] = ' ';
01177 else if (buf[i] < 0x20 || buf[i] > 127)
01178 buf[i] = '?';
01179 }
01180
01195 dbus_bool_t
01196 _dbus_command_for_pid (unsigned long pid,
01197 DBusString *str,
01198 int max_len,
01199 DBusError *error)
01200 {
01201
01202 DBusString path;
01203 DBusString cmdline;
01204 int fd;
01205
01206 if (!_dbus_string_init (&path))
01207 {
01208 _DBUS_SET_OOM (error);
01209 return FALSE;
01210 }
01211
01212 if (!_dbus_string_init (&cmdline))
01213 {
01214 _DBUS_SET_OOM (error);
01215 _dbus_string_free (&path);
01216 return FALSE;
01217 }
01218
01219 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
01220 goto oom;
01221
01222 fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
01223 if (fd < 0)
01224 {
01225 dbus_set_error (error,
01226 _dbus_error_from_errno (errno),
01227 "Failed to open \"%s\": %s",
01228 _dbus_string_get_const_data (&path),
01229 _dbus_strerror (errno));
01230 goto fail;
01231 }
01232
01233 if (!_dbus_read (fd, &cmdline, max_len))
01234 {
01235 dbus_set_error (error,
01236 _dbus_error_from_errno (errno),
01237 "Failed to read from \"%s\": %s",
01238 _dbus_string_get_const_data (&path),
01239 _dbus_strerror (errno));
01240 goto fail;
01241 }
01242
01243 if (!_dbus_close (fd, error))
01244 goto fail;
01245
01246 string_squash_nonprintable (&cmdline);
01247
01248 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
01249 goto oom;
01250
01251 _dbus_string_free (&cmdline);
01252 _dbus_string_free (&path);
01253 return TRUE;
01254 oom:
01255 _DBUS_SET_OOM (error);
01256 fail:
01257 _dbus_string_free (&cmdline);
01258 _dbus_string_free (&path);
01259 return FALSE;
01260 }
01261