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 <syslog.h>
00047 #ifdef HAVE_LIBAUDIT
00048 #include <sys/prctl.h>
00049 #include <sys/capability.h>
00050 #include <libaudit.h>
00051 #endif
00052
00053 #ifdef HAVE_SYS_SYSLIMITS_H
00054 #include <sys/syslimits.h>
00055 #endif
00056
00057 #ifndef O_BINARY
00058 #define O_BINARY 0
00059 #endif
00060
00076 dbus_bool_t
00077 _dbus_become_daemon (const DBusString *pidfile,
00078 DBusPipe *print_pid_pipe,
00079 DBusError *error,
00080 dbus_bool_t keep_umask)
00081 {
00082 const char *s;
00083 pid_t child_pid;
00084 int dev_null_fd;
00085
00086 _dbus_verbose ("Becoming a daemon...\n");
00087
00088 _dbus_verbose ("chdir to /\n");
00089 if (chdir ("/") < 0)
00090 {
00091 dbus_set_error (error, DBUS_ERROR_FAILED,
00092 "Could not chdir() to root directory");
00093 return FALSE;
00094 }
00095
00096 _dbus_verbose ("forking...\n");
00097 switch ((child_pid = fork ()))
00098 {
00099 case -1:
00100 _dbus_verbose ("fork failed\n");
00101 dbus_set_error (error, _dbus_error_from_errno (errno),
00102 "Failed to fork daemon: %s", _dbus_strerror (errno));
00103 return FALSE;
00104 break;
00105
00106 case 0:
00107 _dbus_verbose ("in child, closing std file descriptors\n");
00108
00109
00110
00111
00112
00113
00114 dev_null_fd = open ("/dev/null", O_RDWR);
00115 if (dev_null_fd >= 0)
00116 {
00117 dup2 (dev_null_fd, 0);
00118 dup2 (dev_null_fd, 1);
00119
00120 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00121 if (s == NULL || *s == '\0')
00122 dup2 (dev_null_fd, 2);
00123 else
00124 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00125 }
00126
00127 if (!keep_umask)
00128 {
00129
00130 _dbus_verbose ("setting umask\n");
00131 umask (022);
00132 }
00133
00134 _dbus_verbose ("calling setsid()\n");
00135 if (setsid () == -1)
00136 _dbus_assert_not_reached ("setsid() failed");
00137
00138 break;
00139
00140 default:
00141 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
00142 child_pid, error))
00143 {
00144 _dbus_verbose ("pid file or pipe write failed: %s\n",
00145 error->message);
00146 kill (child_pid, SIGTERM);
00147 return FALSE;
00148 }
00149
00150 _dbus_verbose ("parent exiting\n");
00151 _exit (0);
00152 break;
00153 }
00154
00155 return TRUE;
00156 }
00157
00158
00167 static dbus_bool_t
00168 _dbus_write_pid_file (const DBusString *filename,
00169 unsigned long pid,
00170 DBusError *error)
00171 {
00172 const char *cfilename;
00173 int fd;
00174 FILE *f;
00175
00176 cfilename = _dbus_string_get_const_data (filename);
00177
00178 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00179
00180 if (fd < 0)
00181 {
00182 dbus_set_error (error, _dbus_error_from_errno (errno),
00183 "Failed to open \"%s\": %s", cfilename,
00184 _dbus_strerror (errno));
00185 return FALSE;
00186 }
00187
00188 if ((f = fdopen (fd, "w")) == NULL)
00189 {
00190 dbus_set_error (error, _dbus_error_from_errno (errno),
00191 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00192 _dbus_close (fd, NULL);
00193 return FALSE;
00194 }
00195
00196 if (fprintf (f, "%lu\n", pid) < 0)
00197 {
00198 dbus_set_error (error, _dbus_error_from_errno (errno),
00199 "Failed to write to \"%s\": %s", cfilename,
00200 _dbus_strerror (errno));
00201
00202 fclose (f);
00203 return FALSE;
00204 }
00205
00206 if (fclose (f) == EOF)
00207 {
00208 dbus_set_error (error, _dbus_error_from_errno (errno),
00209 "Failed to close \"%s\": %s", cfilename,
00210 _dbus_strerror (errno));
00211 return FALSE;
00212 }
00213
00214 return TRUE;
00215 }
00216
00228 dbus_bool_t
00229 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
00230 DBusPipe *print_pid_pipe,
00231 dbus_pid_t pid_to_write,
00232 DBusError *error)
00233 {
00234 if (pidfile)
00235 {
00236 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
00237 if (!_dbus_write_pid_file (pidfile,
00238 pid_to_write,
00239 error))
00240 {
00241 _dbus_verbose ("pid file write failed\n");
00242 _DBUS_ASSERT_ERROR_IS_SET(error);
00243 return FALSE;
00244 }
00245 }
00246 else
00247 {
00248 _dbus_verbose ("No pid file requested\n");
00249 }
00250
00251 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00252 {
00253 DBusString pid;
00254 int bytes;
00255
00256 _dbus_verbose ("writing our pid to pipe %d\n", print_pid_pipe->fd_or_handle);
00257
00258 if (!_dbus_string_init (&pid))
00259 {
00260 _DBUS_SET_OOM (error);
00261 return FALSE;
00262 }
00263
00264 if (!_dbus_string_append_int (&pid, pid_to_write) ||
00265 !_dbus_string_append (&pid, "\n"))
00266 {
00267 _dbus_string_free (&pid);
00268 _DBUS_SET_OOM (error);
00269 return FALSE;
00270 }
00271
00272 bytes = _dbus_string_get_length (&pid);
00273 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00274 {
00275
00276 if (error != NULL && !dbus_error_is_set(error))
00277 {
00278 dbus_set_error (error, DBUS_ERROR_FAILED,
00279 "Printing message bus PID: did not write enough bytes\n");
00280 }
00281 _dbus_string_free (&pid);
00282 return FALSE;
00283 }
00284
00285 _dbus_string_free (&pid);
00286 }
00287 else
00288 {
00289 _dbus_verbose ("No pid pipe to write to\n");
00290 }
00291
00292 return TRUE;
00293 }
00294
00301 dbus_bool_t
00302 _dbus_verify_daemon_user (const char *user)
00303 {
00304 DBusString u;
00305
00306 _dbus_string_init_const (&u, user);
00307
00308 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00309 }
00310
00318 dbus_bool_t
00319 _dbus_change_to_daemon_user (const char *user,
00320 DBusError *error)
00321 {
00322 dbus_uid_t uid;
00323 dbus_gid_t gid;
00324 DBusString u;
00325 #ifdef HAVE_LIBAUDIT
00326 dbus_bool_t we_were_root;
00327 cap_t new_caps;
00328 #endif
00329
00330 _dbus_string_init_const (&u, user);
00331
00332 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00333 {
00334 dbus_set_error (error, DBUS_ERROR_FAILED,
00335 "User '%s' does not appear to exist?",
00336 user);
00337 return FALSE;
00338 }
00339
00340 #ifdef HAVE_LIBAUDIT
00341 we_were_root = _dbus_geteuid () == 0;
00342 new_caps = NULL;
00343
00344
00345
00346
00347 if (we_were_root)
00348 {
00349 cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
00350 cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
00351 cap_t tmp_caps = cap_init();
00352
00353 if (!tmp_caps || !(new_caps = cap_init ()))
00354 {
00355 dbus_set_error (error, DBUS_ERROR_FAILED,
00356 "Failed to initialize drop of capabilities: %s\n",
00357 _dbus_strerror (errno));
00358
00359 if (tmp_caps)
00360 cap_free (tmp_caps);
00361
00362 return FALSE;
00363 }
00364
00365
00366 cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
00367 cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
00368 cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
00369 cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
00370
00371 if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
00372 {
00373 dbus_set_error (error, _dbus_error_from_errno (errno),
00374 "Failed to set keep-capabilities: %s\n",
00375 _dbus_strerror (errno));
00376 cap_free (tmp_caps);
00377 goto fail;
00378 }
00379
00380 if (cap_set_proc (tmp_caps) == -1)
00381 {
00382 dbus_set_error (error, DBUS_ERROR_FAILED,
00383 "Failed to drop capabilities: %s\n",
00384 _dbus_strerror (errno));
00385 cap_free (tmp_caps);
00386 goto fail;
00387 }
00388 cap_free (tmp_caps);
00389 }
00390 #endif
00391
00392
00393
00394
00395
00396
00397
00398
00399 if (setgroups (0, NULL) < 0)
00400 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00401 _dbus_strerror (errno));
00402
00403
00404
00405
00406 if (setgid (gid) < 0)
00407 {
00408 dbus_set_error (error, _dbus_error_from_errno (errno),
00409 "Failed to set GID to %lu: %s", gid,
00410 _dbus_strerror (errno));
00411 goto fail;
00412 }
00413
00414 if (setuid (uid) < 0)
00415 {
00416 dbus_set_error (error, _dbus_error_from_errno (errno),
00417 "Failed to set UID to %lu: %s", uid,
00418 _dbus_strerror (errno));
00419 goto fail;
00420 }
00421
00422 #ifdef HAVE_LIBAUDIT
00423 if (we_were_root)
00424 {
00425 if (cap_set_proc (new_caps))
00426 {
00427 dbus_set_error (error, DBUS_ERROR_FAILED,
00428 "Failed to drop capabilities: %s\n",
00429 _dbus_strerror (errno));
00430 goto fail;
00431 }
00432 cap_free (new_caps);
00433
00434
00435 if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
00436 {
00437 dbus_set_error (error, _dbus_error_from_errno (errno),
00438 "Failed to unset keep-capabilities: %s\n",
00439 _dbus_strerror (errno));
00440 return FALSE;
00441 }
00442 }
00443 #endif
00444
00445 return TRUE;
00446
00447 fail:
00448 #ifdef HAVE_LIBAUDIT
00449 if (!we_were_root)
00450 {
00451
00452 prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0);
00453 cap_free (new_caps);
00454 }
00455 #endif
00456
00457 return FALSE;
00458 }
00459
00460 void
00461 _dbus_init_system_log (void)
00462 {
00463 openlog ("dbus", LOG_PID, LOG_DAEMON);
00464 }
00465
00473 void
00474 _dbus_log_info (const char *msg, va_list args)
00475 {
00476 vsyslog (LOG_DAEMON|LOG_NOTICE, msg, args);
00477 }
00478
00486 void
00487 _dbus_log_security (const char *msg, va_list args)
00488 {
00489 vsyslog (LOG_AUTH|LOG_NOTICE, msg, args);
00490 }
00491
00497 void
00498 _dbus_set_signal_handler (int sig,
00499 DBusSignalHandler handler)
00500 {
00501 struct sigaction act;
00502 sigset_t empty_mask;
00503
00504 sigemptyset (&empty_mask);
00505 act.sa_handler = handler;
00506 act.sa_mask = empty_mask;
00507 act.sa_flags = 0;
00508 sigaction (sig, &act, NULL);
00509 }
00510
00511
00519 dbus_bool_t
00520 _dbus_delete_directory (const DBusString *filename,
00521 DBusError *error)
00522 {
00523 const char *filename_c;
00524
00525 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00526
00527 filename_c = _dbus_string_get_const_data (filename);
00528
00529 if (rmdir (filename_c) != 0)
00530 {
00531 dbus_set_error (error, DBUS_ERROR_FAILED,
00532 "Failed to remove directory %s: %s\n",
00533 filename_c, _dbus_strerror (errno));
00534 return FALSE;
00535 }
00536
00537 return TRUE;
00538 }
00539
00545 dbus_bool_t
00546 _dbus_file_exists (const char *file)
00547 {
00548 return (access (file, F_OK) == 0);
00549 }
00550
00557 dbus_bool_t
00558 _dbus_user_at_console (const char *username,
00559 DBusError *error)
00560 {
00561
00562 DBusString f;
00563 dbus_bool_t result;
00564
00565 result = FALSE;
00566 if (!_dbus_string_init (&f))
00567 {
00568 _DBUS_SET_OOM (error);
00569 return FALSE;
00570 }
00571
00572 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00573 {
00574 _DBUS_SET_OOM (error);
00575 goto out;
00576 }
00577
00578
00579 if (!_dbus_string_append (&f, username))
00580 {
00581 _DBUS_SET_OOM (error);
00582 goto out;
00583 }
00584
00585 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00586
00587 out:
00588 _dbus_string_free (&f);
00589
00590 return result;
00591 }
00592
00593
00600 dbus_bool_t
00601 _dbus_path_is_absolute (const DBusString *filename)
00602 {
00603 if (_dbus_string_get_length (filename) > 0)
00604 return _dbus_string_get_byte (filename, 0) == '/';
00605 else
00606 return FALSE;
00607 }
00608
00617 dbus_bool_t
00618 _dbus_stat (const DBusString *filename,
00619 DBusStat *statbuf,
00620 DBusError *error)
00621 {
00622 const char *filename_c;
00623 struct stat sb;
00624
00625 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00626
00627 filename_c = _dbus_string_get_const_data (filename);
00628
00629 if (stat (filename_c, &sb) < 0)
00630 {
00631 dbus_set_error (error, _dbus_error_from_errno (errno),
00632 "%s", _dbus_strerror (errno));
00633 return FALSE;
00634 }
00635
00636 statbuf->mode = sb.st_mode;
00637 statbuf->nlink = sb.st_nlink;
00638 statbuf->uid = sb.st_uid;
00639 statbuf->gid = sb.st_gid;
00640 statbuf->size = sb.st_size;
00641 statbuf->atime = sb.st_atime;
00642 statbuf->mtime = sb.st_mtime;
00643 statbuf->ctime = sb.st_ctime;
00644
00645 return TRUE;
00646 }
00647
00648
00652 struct DBusDirIter
00653 {
00654 DIR *d;
00656 };
00657
00665 DBusDirIter*
00666 _dbus_directory_open (const DBusString *filename,
00667 DBusError *error)
00668 {
00669 DIR *d;
00670 DBusDirIter *iter;
00671 const char *filename_c;
00672
00673 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00674
00675 filename_c = _dbus_string_get_const_data (filename);
00676
00677 d = opendir (filename_c);
00678 if (d == NULL)
00679 {
00680 dbus_set_error (error, _dbus_error_from_errno (errno),
00681 "Failed to read directory \"%s\": %s",
00682 filename_c,
00683 _dbus_strerror (errno));
00684 return NULL;
00685 }
00686 iter = dbus_new0 (DBusDirIter, 1);
00687 if (iter == NULL)
00688 {
00689 closedir (d);
00690 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00691 "Could not allocate memory for directory iterator");
00692 return NULL;
00693 }
00694
00695 iter->d = d;
00696
00697 return iter;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 static dbus_bool_t
00709 dirent_buf_size(DIR * dirp, size_t *size)
00710 {
00711 long name_max;
00712 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00713 # if defined(HAVE_DIRFD)
00714 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00715 # elif defined(HAVE_DDFD)
00716 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00717 # else
00718 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00719 # endif
00720 if (name_max == -1)
00721 # if defined(NAME_MAX)
00722 name_max = NAME_MAX;
00723 # else
00724 return FALSE;
00725 # endif
00726 # elif defined(MAXNAMELEN)
00727 name_max = MAXNAMELEN;
00728 # else
00729 # if defined(NAME_MAX)
00730 name_max = NAME_MAX;
00731 # else
00732 # error "buffer size for readdir_r cannot be determined"
00733 # endif
00734 # endif
00735 if (size)
00736 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00737 else
00738 return FALSE;
00739
00740 return TRUE;
00741 }
00742
00753 dbus_bool_t
00754 _dbus_directory_get_next_file (DBusDirIter *iter,
00755 DBusString *filename,
00756 DBusError *error)
00757 {
00758 struct dirent *d, *ent;
00759 size_t buf_size;
00760 int err;
00761
00762 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00763
00764 if (!dirent_buf_size (iter->d, &buf_size))
00765 {
00766 dbus_set_error (error, DBUS_ERROR_FAILED,
00767 "Can't calculate buffer size when reading directory");
00768 return FALSE;
00769 }
00770
00771 d = (struct dirent *)dbus_malloc (buf_size);
00772 if (!d)
00773 {
00774 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00775 "No memory to read directory entry");
00776 return FALSE;
00777 }
00778
00779 again:
00780 err = readdir_r (iter->d, d, &ent);
00781 if (err || !ent)
00782 {
00783 if (err != 0)
00784 dbus_set_error (error,
00785 _dbus_error_from_errno (err),
00786 "%s", _dbus_strerror (err));
00787
00788 dbus_free (d);
00789 return FALSE;
00790 }
00791 else if (ent->d_name[0] == '.' &&
00792 (ent->d_name[1] == '\0' ||
00793 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00794 goto again;
00795 else
00796 {
00797 _dbus_string_set_length (filename, 0);
00798 if (!_dbus_string_append (filename, ent->d_name))
00799 {
00800 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00801 "No memory to read directory entry");
00802 dbus_free (d);
00803 return FALSE;
00804 }
00805 else
00806 {
00807 dbus_free (d);
00808 return TRUE;
00809 }
00810 }
00811 }
00812
00816 void
00817 _dbus_directory_close (DBusDirIter *iter)
00818 {
00819 closedir (iter->d);
00820 dbus_free (iter);
00821 }
00822
00823 static dbus_bool_t
00824 fill_user_info_from_group (struct group *g,
00825 DBusGroupInfo *info,
00826 DBusError *error)
00827 {
00828 _dbus_assert (g->gr_name != NULL);
00829
00830 info->gid = g->gr_gid;
00831 info->groupname = _dbus_strdup (g->gr_name);
00832
00833
00834
00835 if (info->groupname == NULL)
00836 {
00837 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00838 return FALSE;
00839 }
00840
00841 return TRUE;
00842 }
00843
00844 static dbus_bool_t
00845 fill_group_info (DBusGroupInfo *info,
00846 dbus_gid_t gid,
00847 const DBusString *groupname,
00848 DBusError *error)
00849 {
00850 const char *group_c_str;
00851
00852 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00853 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00854
00855 if (groupname)
00856 group_c_str = _dbus_string_get_const_data (groupname);
00857 else
00858 group_c_str = NULL;
00859
00860
00861
00862
00863
00864
00865 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00866 {
00867 struct group *g;
00868 int result;
00869 size_t buflen;
00870 char *buf;
00871 struct group g_str;
00872 dbus_bool_t b;
00873
00874
00875 buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
00876
00877
00878
00879
00880
00881 if ((long) buflen <= 0)
00882 buflen = 1024;
00883
00884 result = -1;
00885 while (1)
00886 {
00887 buf = dbus_malloc (buflen);
00888 if (buf == NULL)
00889 {
00890 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00891 return FALSE;
00892 }
00893
00894 g = NULL;
00895 #ifdef HAVE_POSIX_GETPWNAM_R
00896 if (group_c_str)
00897 result = getgrnam_r (group_c_str, &g_str, buf, buflen,
00898 &g);
00899 else
00900 result = getgrgid_r (gid, &g_str, buf, buflen,
00901 &g);
00902 #else
00903 g = getgrnam_r (group_c_str, &g_str, buf, buflen);
00904 result = 0;
00905 #endif
00906
00907
00908
00909 if (result == ERANGE && buflen < 512 * 1024)
00910 {
00911 dbus_free (buf);
00912 buflen *= 2;
00913 }
00914 else
00915 {
00916 break;
00917 }
00918 }
00919
00920 if (result == 0 && g == &g_str)
00921 {
00922 b = fill_user_info_from_group (g, info, error);
00923 dbus_free (buf);
00924 return b;
00925 }
00926 else
00927 {
00928 dbus_set_error (error, _dbus_error_from_errno (errno),
00929 "Group %s unknown or failed to look it up\n",
00930 group_c_str ? group_c_str : "???");
00931 dbus_free (buf);
00932 return FALSE;
00933 }
00934 }
00935 #else
00936 {
00937
00938 struct group *g;
00939
00940 g = getgrnam (group_c_str);
00941
00942 if (g != NULL)
00943 {
00944 return fill_user_info_from_group (g, info, error);
00945 }
00946 else
00947 {
00948 dbus_set_error (error, _dbus_error_from_errno (errno),
00949 "Group %s unknown or failed to look it up\n",
00950 group_c_str ? group_c_str : "???");
00951 return FALSE;
00952 }
00953 }
00954 #endif
00955 }
00956
00966 dbus_bool_t
00967 _dbus_group_info_fill (DBusGroupInfo *info,
00968 const DBusString *groupname,
00969 DBusError *error)
00970 {
00971 return fill_group_info (info, DBUS_GID_UNSET,
00972 groupname, error);
00973
00974 }
00975
00985 dbus_bool_t
00986 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00987 dbus_gid_t gid,
00988 DBusError *error)
00989 {
00990 return fill_group_info (info, gid, NULL, error);
00991 }
00992
01001 dbus_bool_t
01002 _dbus_parse_unix_user_from_config (const DBusString *username,
01003 dbus_uid_t *uid_p)
01004 {
01005 return _dbus_get_user_id (username, uid_p);
01006
01007 }
01008
01017 dbus_bool_t
01018 _dbus_parse_unix_group_from_config (const DBusString *groupname,
01019 dbus_gid_t *gid_p)
01020 {
01021 return _dbus_get_group_id (groupname, gid_p);
01022 }
01023
01034 dbus_bool_t
01035 _dbus_unix_groups_from_uid (dbus_uid_t uid,
01036 dbus_gid_t **group_ids,
01037 int *n_group_ids)
01038 {
01039 return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
01040 }
01041
01051 dbus_bool_t
01052 _dbus_unix_user_is_at_console (dbus_uid_t uid,
01053 DBusError *error)
01054 {
01055 return _dbus_is_console_user (uid, error);
01056
01057 }
01058
01066 dbus_bool_t
01067 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
01068 {
01069 return uid == _dbus_geteuid ();
01070 }
01071
01079 dbus_bool_t
01080 _dbus_windows_user_is_process_owner (const char *windows_sid)
01081 {
01082 return FALSE;
01083 }
01084
01086
01098 dbus_bool_t
01099 _dbus_string_get_dirname (const DBusString *filename,
01100 DBusString *dirname)
01101 {
01102 int sep;
01103
01104 _dbus_assert (filename != dirname);
01105 _dbus_assert (filename != NULL);
01106 _dbus_assert (dirname != NULL);
01107
01108
01109 sep = _dbus_string_get_length (filename);
01110 if (sep == 0)
01111 return _dbus_string_append (dirname, ".");
01112
01113 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01114 --sep;
01115
01116 _dbus_assert (sep >= 0);
01117
01118 if (sep == 0)
01119 return _dbus_string_append (dirname, "/");
01120
01121
01122 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01123 if (sep < 0)
01124 return _dbus_string_append (dirname, ".");
01125
01126
01127 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01128 --sep;
01129
01130 _dbus_assert (sep >= 0);
01131
01132 if (sep == 0 &&
01133 _dbus_string_get_byte (filename, 0) == '/')
01134 return _dbus_string_append (dirname, "/");
01135 else
01136 return _dbus_string_copy_len (filename, 0, sep - 0,
01137 dirname, _dbus_string_get_length (dirname));
01138 }
01140
01141 static void
01142 string_squash_nonprintable (DBusString *str)
01143 {
01144 char *buf;
01145 int i, len;
01146
01147 buf = _dbus_string_get_data (str);
01148 len = _dbus_string_get_length (str);
01149
01150 for (i = 0; i < len; i++)
01151 if (buf[i] == '\0')
01152 buf[i] = ' ';
01153 else if (buf[i] < 0x20 || buf[i] > 127)
01154 buf[i] = '?';
01155 }
01156
01171 dbus_bool_t
01172 _dbus_command_for_pid (unsigned long pid,
01173 DBusString *str,
01174 int max_len,
01175 DBusError *error)
01176 {
01177
01178 DBusString path;
01179 DBusString cmdline;
01180 int fd;
01181
01182 if (!_dbus_string_init (&path))
01183 {
01184 _DBUS_SET_OOM (error);
01185 return FALSE;
01186 }
01187
01188 if (!_dbus_string_init (&cmdline))
01189 {
01190 _DBUS_SET_OOM (error);
01191 _dbus_string_free (&path);
01192 return FALSE;
01193 }
01194
01195 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
01196 goto oom;
01197
01198 fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
01199 if (fd < 0)
01200 {
01201 dbus_set_error (error,
01202 _dbus_error_from_errno (errno),
01203 "Failed to open \"%s\": %s",
01204 _dbus_string_get_const_data (&path),
01205 _dbus_strerror (errno));
01206 goto fail;
01207 }
01208
01209 if (!_dbus_read (fd, &cmdline, max_len))
01210 {
01211 dbus_set_error (error,
01212 _dbus_error_from_errno (errno),
01213 "Failed to read from \"%s\": %s",
01214 _dbus_string_get_const_data (&path),
01215 _dbus_strerror (errno));
01216 goto fail;
01217 }
01218
01219 if (!_dbus_close (fd, error))
01220 goto fail;
01221
01222 string_squash_nonprintable (&cmdline);
01223
01224 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
01225 goto oom;
01226
01227 _dbus_string_free (&cmdline);
01228 _dbus_string_free (&path);
01229 return TRUE;
01230 oom:
01231 _DBUS_SET_OOM (error);
01232 fail:
01233 _dbus_string_free (&cmdline);
01234 _dbus_string_free (&path);
01235 return FALSE;
01236 }