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 #ifdef HAVE_SYS_RESOURCE_H
00043 #include <sys/resource.h>
00044 #endif
00045 #include <grp.h>
00046 #include <sys/socket.h>
00047 #include <dirent.h>
00048 #include <sys/un.h>
00049 #include <syslog.h>
00050 #ifdef HAVE_LIBAUDIT
00051 #include <sys/prctl.h>
00052 #include <sys/capability.h>
00053 #include <libaudit.h>
00054 #endif
00055
00056 #ifdef HAVE_SYS_SYSLIMITS_H
00057 #include <sys/syslimits.h>
00058 #endif
00059
00060 #ifndef O_BINARY
00061 #define O_BINARY 0
00062 #endif
00063
00078 dbus_bool_t
00079 _dbus_become_daemon (const DBusString *pidfile,
00080 DBusPipe *print_pid_pipe,
00081 DBusError *error)
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
00129 _dbus_verbose ("setting umask\n");
00130 umask (022);
00131
00132 _dbus_verbose ("calling setsid()\n");
00133 if (setsid () == -1)
00134 _dbus_assert_not_reached ("setsid() failed");
00135
00136 break;
00137
00138 default:
00139 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
00140 child_pid, error))
00141 {
00142 _dbus_verbose ("pid file or pipe write failed: %s\n",
00143 error->message);
00144 kill (child_pid, SIGTERM);
00145 return FALSE;
00146 }
00147
00148 _dbus_verbose ("parent exiting\n");
00149 _exit (0);
00150 break;
00151 }
00152
00153 return TRUE;
00154 }
00155
00156
00165 static dbus_bool_t
00166 _dbus_write_pid_file (const DBusString *filename,
00167 unsigned long pid,
00168 DBusError *error)
00169 {
00170 const char *cfilename;
00171 int fd;
00172 FILE *f;
00173
00174 cfilename = _dbus_string_get_const_data (filename);
00175
00176 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00177
00178 if (fd < 0)
00179 {
00180 dbus_set_error (error, _dbus_error_from_errno (errno),
00181 "Failed to open \"%s\": %s", cfilename,
00182 _dbus_strerror (errno));
00183 return FALSE;
00184 }
00185
00186 if ((f = fdopen (fd, "w")) == NULL)
00187 {
00188 dbus_set_error (error, _dbus_error_from_errno (errno),
00189 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00190 _dbus_close (fd, NULL);
00191 return FALSE;
00192 }
00193
00194 if (fprintf (f, "%lu\n", pid) < 0)
00195 {
00196 dbus_set_error (error, _dbus_error_from_errno (errno),
00197 "Failed to write to \"%s\": %s", cfilename,
00198 _dbus_strerror (errno));
00199
00200 fclose (f);
00201 return FALSE;
00202 }
00203
00204 if (fclose (f) == EOF)
00205 {
00206 dbus_set_error (error, _dbus_error_from_errno (errno),
00207 "Failed to close \"%s\": %s", cfilename,
00208 _dbus_strerror (errno));
00209 return FALSE;
00210 }
00211
00212 return TRUE;
00213 }
00214
00226 dbus_bool_t
00227 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
00228 DBusPipe *print_pid_pipe,
00229 dbus_pid_t pid_to_write,
00230 DBusError *error)
00231 {
00232 if (pidfile)
00233 {
00234 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
00235 if (!_dbus_write_pid_file (pidfile,
00236 pid_to_write,
00237 error))
00238 {
00239 _dbus_verbose ("pid file write failed\n");
00240 _DBUS_ASSERT_ERROR_IS_SET(error);
00241 return FALSE;
00242 }
00243 }
00244 else
00245 {
00246 _dbus_verbose ("No pid file requested\n");
00247 }
00248
00249 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00250 {
00251 DBusString pid;
00252 int bytes;
00253
00254 _dbus_verbose ("writing our pid to pipe %d\n", print_pid_pipe->fd_or_handle);
00255
00256 if (!_dbus_string_init (&pid))
00257 {
00258 _DBUS_SET_OOM (error);
00259 return FALSE;
00260 }
00261
00262 if (!_dbus_string_append_int (&pid, pid_to_write) ||
00263 !_dbus_string_append (&pid, "\n"))
00264 {
00265 _dbus_string_free (&pid);
00266 _DBUS_SET_OOM (error);
00267 return FALSE;
00268 }
00269
00270 bytes = _dbus_string_get_length (&pid);
00271 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00272 {
00273
00274 if (error != NULL && !dbus_error_is_set(error))
00275 {
00276 dbus_set_error (error, DBUS_ERROR_FAILED,
00277 "Printing message bus PID: did not write enough bytes\n");
00278 }
00279 _dbus_string_free (&pid);
00280 return FALSE;
00281 }
00282
00283 _dbus_string_free (&pid);
00284 }
00285 else
00286 {
00287 _dbus_verbose ("No pid pipe to write to\n");
00288 }
00289
00290 return TRUE;
00291 }
00292
00299 dbus_bool_t
00300 _dbus_verify_daemon_user (const char *user)
00301 {
00302 DBusString u;
00303
00304 _dbus_string_init_const (&u, user);
00305
00306 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00307 }
00308
00316 dbus_bool_t
00317 _dbus_change_to_daemon_user (const char *user,
00318 DBusError *error)
00319 {
00320 dbus_uid_t uid;
00321 dbus_gid_t gid;
00322 DBusString u;
00323 #ifdef HAVE_LIBAUDIT
00324 dbus_bool_t we_were_root;
00325 cap_t new_caps;
00326 #endif
00327
00328 _dbus_string_init_const (&u, user);
00329
00330 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00331 {
00332 dbus_set_error (error, DBUS_ERROR_FAILED,
00333 "User '%s' does not appear to exist?",
00334 user);
00335 return FALSE;
00336 }
00337
00338 #ifdef HAVE_LIBAUDIT
00339 we_were_root = _dbus_geteuid () == 0;
00340 new_caps = NULL;
00341
00342
00343
00344
00345 if (we_were_root)
00346 {
00347 cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
00348 cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
00349 cap_t tmp_caps = cap_init();
00350
00351 if (!tmp_caps || !(new_caps = cap_init ()))
00352 {
00353 dbus_set_error (error, DBUS_ERROR_FAILED,
00354 "Failed to initialize drop of capabilities: %s\n",
00355 _dbus_strerror (errno));
00356
00357 if (tmp_caps)
00358 cap_free (tmp_caps);
00359
00360 return FALSE;
00361 }
00362
00363
00364 cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
00365 cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
00366 cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
00367 cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
00368
00369 if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
00370 {
00371 dbus_set_error (error, _dbus_error_from_errno (errno),
00372 "Failed to set keep-capabilities: %s\n",
00373 _dbus_strerror (errno));
00374 cap_free (tmp_caps);
00375 goto fail;
00376 }
00377
00378 if (cap_set_proc (tmp_caps) == -1)
00379 {
00380 dbus_set_error (error, DBUS_ERROR_FAILED,
00381 "Failed to drop capabilities: %s\n",
00382 _dbus_strerror (errno));
00383 cap_free (tmp_caps);
00384 goto fail;
00385 }
00386 cap_free (tmp_caps);
00387 }
00388 #endif
00389
00390
00391
00392
00393
00394
00395
00396
00397 if (setgroups (0, NULL) < 0)
00398 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00399 _dbus_strerror (errno));
00400
00401
00402
00403
00404 if (setgid (gid) < 0)
00405 {
00406 dbus_set_error (error, _dbus_error_from_errno (errno),
00407 "Failed to set GID to %lu: %s", gid,
00408 _dbus_strerror (errno));
00409 goto fail;
00410 }
00411
00412 if (setuid (uid) < 0)
00413 {
00414 dbus_set_error (error, _dbus_error_from_errno (errno),
00415 "Failed to set UID to %lu: %s", uid,
00416 _dbus_strerror (errno));
00417 goto fail;
00418 }
00419
00420 #ifdef HAVE_LIBAUDIT
00421 if (we_were_root)
00422 {
00423 if (cap_set_proc (new_caps))
00424 {
00425 dbus_set_error (error, DBUS_ERROR_FAILED,
00426 "Failed to drop capabilities: %s\n",
00427 _dbus_strerror (errno));
00428 goto fail;
00429 }
00430 cap_free (new_caps);
00431
00432
00433 if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
00434 {
00435 dbus_set_error (error, _dbus_error_from_errno (errno),
00436 "Failed to unset keep-capabilities: %s\n",
00437 _dbus_strerror (errno));
00438 return FALSE;
00439 }
00440 }
00441 #endif
00442
00443 return TRUE;
00444
00445 fail:
00446 #ifdef HAVE_LIBAUDIT
00447 if (!we_were_root)
00448 {
00449
00450 prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0);
00451 cap_free (new_caps);
00452 }
00453 #endif
00454
00455 return FALSE;
00456 }
00457
00458
00469 void
00470 _dbus_request_file_descriptor_limit (unsigned int limit)
00471 {
00472 #ifdef HAVE_SETRLIMIT
00473 struct rlimit lim;
00474 struct rlimit target_lim;
00475 unsigned int current_limit;
00476
00477
00478
00479
00480
00481
00482
00483 if (getuid () != 0)
00484 return;
00485
00486 if (getrlimit (RLIMIT_NOFILE, &lim) < 0)
00487 return;
00488
00489 if (lim.rlim_cur >= limit)
00490 return;
00491
00492
00493
00494
00495 target_lim.rlim_cur = target_lim.rlim_max = limit;
00496
00497
00498
00499
00500
00501
00502
00503
00504 setrlimit (RLIMIT_NOFILE, &target_lim);
00505 #endif
00506 }
00507
00508 void
00509 _dbus_init_system_log (void)
00510 {
00511 openlog ("dbus", LOG_PID, LOG_DAEMON);
00512 }
00513
00521 void
00522 _dbus_log_info (const char *msg, va_list args)
00523 {
00524 vsyslog (LOG_DAEMON|LOG_NOTICE, msg, args);
00525 }
00526
00534 void
00535 _dbus_log_security (const char *msg, va_list args)
00536 {
00537 vsyslog (LOG_AUTH|LOG_NOTICE, msg, args);
00538 }
00539
00545 void
00546 _dbus_set_signal_handler (int sig,
00547 DBusSignalHandler handler)
00548 {
00549 struct sigaction act;
00550 sigset_t empty_mask;
00551
00552 sigemptyset (&empty_mask);
00553 act.sa_handler = handler;
00554 act.sa_mask = empty_mask;
00555 act.sa_flags = 0;
00556 sigaction (sig, &act, NULL);
00557 }
00558
00559
00567 dbus_bool_t
00568 _dbus_delete_directory (const DBusString *filename,
00569 DBusError *error)
00570 {
00571 const char *filename_c;
00572
00573 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00574
00575 filename_c = _dbus_string_get_const_data (filename);
00576
00577 if (rmdir (filename_c) != 0)
00578 {
00579 dbus_set_error (error, DBUS_ERROR_FAILED,
00580 "Failed to remove directory %s: %s\n",
00581 filename_c, _dbus_strerror (errno));
00582 return FALSE;
00583 }
00584
00585 return TRUE;
00586 }
00587
00593 dbus_bool_t
00594 _dbus_file_exists (const char *file)
00595 {
00596 return (access (file, F_OK) == 0);
00597 }
00598
00605 dbus_bool_t
00606 _dbus_user_at_console (const char *username,
00607 DBusError *error)
00608 {
00609
00610 DBusString f;
00611 dbus_bool_t result;
00612
00613 result = FALSE;
00614 if (!_dbus_string_init (&f))
00615 {
00616 _DBUS_SET_OOM (error);
00617 return FALSE;
00618 }
00619
00620 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00621 {
00622 _DBUS_SET_OOM (error);
00623 goto out;
00624 }
00625
00626
00627 if (!_dbus_string_append (&f, username))
00628 {
00629 _DBUS_SET_OOM (error);
00630 goto out;
00631 }
00632
00633 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00634
00635 out:
00636 _dbus_string_free (&f);
00637
00638 return result;
00639 }
00640
00641
00648 dbus_bool_t
00649 _dbus_path_is_absolute (const DBusString *filename)
00650 {
00651 if (_dbus_string_get_length (filename) > 0)
00652 return _dbus_string_get_byte (filename, 0) == '/';
00653 else
00654 return FALSE;
00655 }
00656
00665 dbus_bool_t
00666 _dbus_stat (const DBusString *filename,
00667 DBusStat *statbuf,
00668 DBusError *error)
00669 {
00670 const char *filename_c;
00671 struct stat sb;
00672
00673 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00674
00675 filename_c = _dbus_string_get_const_data (filename);
00676
00677 if (stat (filename_c, &sb) < 0)
00678 {
00679 dbus_set_error (error, _dbus_error_from_errno (errno),
00680 "%s", _dbus_strerror (errno));
00681 return FALSE;
00682 }
00683
00684 statbuf->mode = sb.st_mode;
00685 statbuf->nlink = sb.st_nlink;
00686 statbuf->uid = sb.st_uid;
00687 statbuf->gid = sb.st_gid;
00688 statbuf->size = sb.st_size;
00689 statbuf->atime = sb.st_atime;
00690 statbuf->mtime = sb.st_mtime;
00691 statbuf->ctime = sb.st_ctime;
00692
00693 return TRUE;
00694 }
00695
00696
00700 struct DBusDirIter
00701 {
00702 DIR *d;
00704 };
00705
00713 DBusDirIter*
00714 _dbus_directory_open (const DBusString *filename,
00715 DBusError *error)
00716 {
00717 DIR *d;
00718 DBusDirIter *iter;
00719 const char *filename_c;
00720
00721 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00722
00723 filename_c = _dbus_string_get_const_data (filename);
00724
00725 d = opendir (filename_c);
00726 if (d == NULL)
00727 {
00728 dbus_set_error (error, _dbus_error_from_errno (errno),
00729 "Failed to read directory \"%s\": %s",
00730 filename_c,
00731 _dbus_strerror (errno));
00732 return NULL;
00733 }
00734 iter = dbus_new0 (DBusDirIter, 1);
00735 if (iter == NULL)
00736 {
00737 closedir (d);
00738 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00739 "Could not allocate memory for directory iterator");
00740 return NULL;
00741 }
00742
00743 iter->d = d;
00744
00745 return iter;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 static dbus_bool_t
00757 dirent_buf_size(DIR * dirp, size_t *size)
00758 {
00759 long name_max;
00760 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00761 # if defined(HAVE_DIRFD)
00762 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00763 # elif defined(HAVE_DDFD)
00764 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00765 # else
00766 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00767 # endif
00768 if (name_max == -1)
00769 # if defined(NAME_MAX)
00770 name_max = NAME_MAX;
00771 # else
00772 return FALSE;
00773 # endif
00774 # elif defined(MAXNAMELEN)
00775 name_max = MAXNAMELEN;
00776 # else
00777 # if defined(NAME_MAX)
00778 name_max = NAME_MAX;
00779 # else
00780 # error "buffer size for readdir_r cannot be determined"
00781 # endif
00782 # endif
00783 if (size)
00784 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00785 else
00786 return FALSE;
00787
00788 return TRUE;
00789 }
00790
00801 dbus_bool_t
00802 _dbus_directory_get_next_file (DBusDirIter *iter,
00803 DBusString *filename,
00804 DBusError *error)
00805 {
00806 struct dirent *d, *ent;
00807 size_t buf_size;
00808 int err;
00809
00810 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00811
00812 if (!dirent_buf_size (iter->d, &buf_size))
00813 {
00814 dbus_set_error (error, DBUS_ERROR_FAILED,
00815 "Can't calculate buffer size when reading directory");
00816 return FALSE;
00817 }
00818
00819 d = (struct dirent *)dbus_malloc (buf_size);
00820 if (!d)
00821 {
00822 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00823 "No memory to read directory entry");
00824 return FALSE;
00825 }
00826
00827 again:
00828 err = readdir_r (iter->d, d, &ent);
00829 if (err || !ent)
00830 {
00831 if (err != 0)
00832 dbus_set_error (error,
00833 _dbus_error_from_errno (err),
00834 "%s", _dbus_strerror (err));
00835
00836 dbus_free (d);
00837 return FALSE;
00838 }
00839 else if (ent->d_name[0] == '.' &&
00840 (ent->d_name[1] == '\0' ||
00841 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00842 goto again;
00843 else
00844 {
00845 _dbus_string_set_length (filename, 0);
00846 if (!_dbus_string_append (filename, ent->d_name))
00847 {
00848 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00849 "No memory to read directory entry");
00850 dbus_free (d);
00851 return FALSE;
00852 }
00853 else
00854 {
00855 dbus_free (d);
00856 return TRUE;
00857 }
00858 }
00859 }
00860
00864 void
00865 _dbus_directory_close (DBusDirIter *iter)
00866 {
00867 closedir (iter->d);
00868 dbus_free (iter);
00869 }
00870
00871 static dbus_bool_t
00872 fill_user_info_from_group (struct group *g,
00873 DBusGroupInfo *info,
00874 DBusError *error)
00875 {
00876 _dbus_assert (g->gr_name != NULL);
00877
00878 info->gid = g->gr_gid;
00879 info->groupname = _dbus_strdup (g->gr_name);
00880
00881
00882
00883 if (info->groupname == NULL)
00884 {
00885 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00886 return FALSE;
00887 }
00888
00889 return TRUE;
00890 }
00891
00892 static dbus_bool_t
00893 fill_group_info (DBusGroupInfo *info,
00894 dbus_gid_t gid,
00895 const DBusString *groupname,
00896 DBusError *error)
00897 {
00898 const char *group_c_str;
00899
00900 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00901 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00902
00903 if (groupname)
00904 group_c_str = _dbus_string_get_const_data (groupname);
00905 else
00906 group_c_str = NULL;
00907
00908
00909
00910
00911
00912
00913 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00914 {
00915 struct group *g;
00916 int result;
00917 size_t buflen;
00918 char *buf;
00919 struct group g_str;
00920 dbus_bool_t b;
00921
00922
00923 buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
00924
00925
00926
00927
00928
00929 if ((long) buflen <= 0)
00930 buflen = 1024;
00931
00932 result = -1;
00933 while (1)
00934 {
00935 buf = dbus_malloc (buflen);
00936 if (buf == NULL)
00937 {
00938 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00939 return FALSE;
00940 }
00941
00942 g = NULL;
00943 #ifdef HAVE_POSIX_GETPWNAM_R
00944 if (group_c_str)
00945 result = getgrnam_r (group_c_str, &g_str, buf, buflen,
00946 &g);
00947 else
00948 result = getgrgid_r (gid, &g_str, buf, buflen,
00949 &g);
00950 #else
00951 g = getgrnam_r (group_c_str, &g_str, buf, buflen);
00952 result = 0;
00953 #endif
00954
00955
00956
00957 if (result == ERANGE && buflen < 512 * 1024)
00958 {
00959 dbus_free (buf);
00960 buflen *= 2;
00961 }
00962 else
00963 {
00964 break;
00965 }
00966 }
00967
00968 if (result == 0 && g == &g_str)
00969 {
00970 b = fill_user_info_from_group (g, info, error);
00971 dbus_free (buf);
00972 return b;
00973 }
00974 else
00975 {
00976 dbus_set_error (error, _dbus_error_from_errno (errno),
00977 "Group %s unknown or failed to look it up\n",
00978 group_c_str ? group_c_str : "???");
00979 dbus_free (buf);
00980 return FALSE;
00981 }
00982 }
00983 #else
00984 {
00985
00986 struct group *g;
00987
00988 g = getgrnam (group_c_str);
00989
00990 if (g != NULL)
00991 {
00992 return fill_user_info_from_group (g, info, error);
00993 }
00994 else
00995 {
00996 dbus_set_error (error, _dbus_error_from_errno (errno),
00997 "Group %s unknown or failed to look it up\n",
00998 group_c_str ? group_c_str : "???");
00999 return FALSE;
01000 }
01001 }
01002 #endif
01003 }
01004
01014 dbus_bool_t
01015 _dbus_group_info_fill (DBusGroupInfo *info,
01016 const DBusString *groupname,
01017 DBusError *error)
01018 {
01019 return fill_group_info (info, DBUS_GID_UNSET,
01020 groupname, error);
01021
01022 }
01023
01033 dbus_bool_t
01034 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01035 dbus_gid_t gid,
01036 DBusError *error)
01037 {
01038 return fill_group_info (info, gid, NULL, error);
01039 }
01040
01049 dbus_bool_t
01050 _dbus_parse_unix_user_from_config (const DBusString *username,
01051 dbus_uid_t *uid_p)
01052 {
01053 return _dbus_get_user_id (username, uid_p);
01054
01055 }
01056
01065 dbus_bool_t
01066 _dbus_parse_unix_group_from_config (const DBusString *groupname,
01067 dbus_gid_t *gid_p)
01068 {
01069 return _dbus_get_group_id (groupname, gid_p);
01070 }
01071
01082 dbus_bool_t
01083 _dbus_unix_groups_from_uid (dbus_uid_t uid,
01084 dbus_gid_t **group_ids,
01085 int *n_group_ids)
01086 {
01087 return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
01088 }
01089
01099 dbus_bool_t
01100 _dbus_unix_user_is_at_console (dbus_uid_t uid,
01101 DBusError *error)
01102 {
01103 return _dbus_is_console_user (uid, error);
01104
01105 }
01106
01114 dbus_bool_t
01115 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
01116 {
01117 return uid == _dbus_geteuid ();
01118 }
01119
01127 dbus_bool_t
01128 _dbus_windows_user_is_process_owner (const char *windows_sid)
01129 {
01130 return FALSE;
01131 }
01132
01134
01146 dbus_bool_t
01147 _dbus_string_get_dirname (const DBusString *filename,
01148 DBusString *dirname)
01149 {
01150 int sep;
01151
01152 _dbus_assert (filename != dirname);
01153 _dbus_assert (filename != NULL);
01154 _dbus_assert (dirname != NULL);
01155
01156
01157 sep = _dbus_string_get_length (filename);
01158 if (sep == 0)
01159 return _dbus_string_append (dirname, ".");
01160
01161 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01162 --sep;
01163
01164 _dbus_assert (sep >= 0);
01165
01166 if (sep == 0)
01167 return _dbus_string_append (dirname, "/");
01168
01169
01170 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01171 if (sep < 0)
01172 return _dbus_string_append (dirname, ".");
01173
01174
01175 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01176 --sep;
01177
01178 _dbus_assert (sep >= 0);
01179
01180 if (sep == 0 &&
01181 _dbus_string_get_byte (filename, 0) == '/')
01182 return _dbus_string_append (dirname, "/");
01183 else
01184 return _dbus_string_copy_len (filename, 0, sep - 0,
01185 dirname, _dbus_string_get_length (dirname));
01186 }
01188
01189 static void
01190 string_squash_nonprintable (DBusString *str)
01191 {
01192 char *buf;
01193 int i, len;
01194
01195 buf = _dbus_string_get_data (str);
01196 len = _dbus_string_get_length (str);
01197
01198 for (i = 0; i < len; i++)
01199 if (buf[i] == '\0')
01200 buf[i] = ' ';
01201 else if (buf[i] < 0x20 || buf[i] > 127)
01202 buf[i] = '?';
01203 }
01204
01219 dbus_bool_t
01220 _dbus_command_for_pid (unsigned long pid,
01221 DBusString *str,
01222 int max_len,
01223 DBusError *error)
01224 {
01225
01226 DBusString path;
01227 DBusString cmdline;
01228 int fd;
01229
01230 if (!_dbus_string_init (&path))
01231 {
01232 _DBUS_SET_OOM (error);
01233 return FALSE;
01234 }
01235
01236 if (!_dbus_string_init (&cmdline))
01237 {
01238 _DBUS_SET_OOM (error);
01239 _dbus_string_free (&path);
01240 return FALSE;
01241 }
01242
01243 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
01244 goto oom;
01245
01246 fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
01247 if (fd < 0)
01248 {
01249 dbus_set_error (error,
01250 _dbus_error_from_errno (errno),
01251 "Failed to open \"%s\": %s",
01252 _dbus_string_get_const_data (&path),
01253 _dbus_strerror (errno));
01254 goto fail;
01255 }
01256
01257 if (!_dbus_read (fd, &cmdline, max_len))
01258 {
01259 dbus_set_error (error,
01260 _dbus_error_from_errno (errno),
01261 "Failed to read from \"%s\": %s",
01262 _dbus_string_get_const_data (&path),
01263 _dbus_strerror (errno));
01264 goto fail;
01265 }
01266
01267 if (!_dbus_close (fd, error))
01268 goto fail;
01269
01270 string_squash_nonprintable (&cmdline);
01271
01272 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
01273 goto oom;
01274
01275 _dbus_string_free (&cmdline);
01276 _dbus_string_free (&path);
01277 return TRUE;
01278 oom:
01279 _DBUS_SET_OOM (error);
01280 fail:
01281 _dbus_string_free (&cmdline);
01282 _dbus_string_free (&path);
01283 return FALSE;
01284 }