Exemplo n.º 1
0
/**
 * \param[in] rPath path to file
 * \param[in] rUser user name
 * \return true = success, false = failure
 */
bool copy_from_file(const std::string& rPath, const std::string& rUser)
{
  fprintf(stderr, "copying table from file '%s'\n", rPath.c_str());

  IncronTab tab;
  std::string s(rPath);
  if (s == "-")
    s = "/dev/stdin";
  if (!tab.Load(s)) {
    fprintf(stderr, "cannot load table from file '%s'\n", rPath.c_str());
    return false;
  }

  std::string out(IncronTab::GetUserTablePath(rUser));
  if (!tab.Save(out)) {
    fprintf(stderr, "cannot create table for user '%s'\n", rUser.c_str());
    return false;
  }

  struct passwd* ppwd = getpwnam(rUser.c_str());
  if (ppwd == NULL) {
    fprintf(stderr, "cannot find user '%s': %s\n", rUser.c_str(), strerror(errno));
    return false;
  }
  if (chown(out.c_str(), ppwd->pw_uid, -1) != 0) {
    fprintf(stderr, "cannot set owner '%s' to table '%s': %s\n", rUser.c_str(), out.c_str(), strerror(errno));
    return false;
  }

  return true;
}
Exemplo n.º 2
0
/**
 * \param[in] rPath path to file
 * \param[in] rUser user name
 * \return true = success, false = failure
 */
bool copy_from_file(const std::string& rPath, const std::string& rUser)
{
  fprintf(stderr, "copying table from file '%s'\n", rPath.c_str());

  IncronTab tab;
  std::string s(rPath);
  if (s == "-")
    s = "/dev/stdin";
  if (!tab.Load(s)) {
    fprintf(stderr, "cannot load table from file '%s'\n", rPath.c_str());
    return false;
  }

  std::string out(IncronTab::GetUserTablePath(rUser));
  if (!tab.Save(out)) {
    fprintf(stderr, "cannot create table for user '%s'\n", rUser.c_str());
    return false;
  }

  return true;
}
Exemplo n.º 3
0
/**
 * \param[in] rUser user name
 * \return true = success, false = failure
 *
 * \attention This function is very complex and may contain
 *            various bugs including security ones. Please keep
 *            it in mind..
 */
bool edit_table(const std::string& rUser)
{
  std::string tp(IncronTab::GetUserTablePath(rUser));

  struct passwd* ppwd = getpwnam(rUser.c_str());
  if (ppwd == NULL) {
    fprintf(stderr, "cannot find user '%s': %s\n", rUser.c_str(), strerror(errno));
    return false;
  }

  uid_t uid = ppwd->pw_uid;
  uid_t gid = ppwd->pw_gid;

  char s[NAME_MAX];
  strcpy(s, "/tmp/incron.table-XXXXXX");

  uid_t iu = geteuid();
  uid_t ig = getegid();

  if (setegid(gid) != 0 || seteuid(uid) != 0) {
    fprintf(stderr, "cannot change effective UID/GID for user '%s': %s\n", rUser.c_str(), strerror(errno));
    return false;
  }

  int fd = mkstemp(s);
  if (fd == -1) {
    fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno));
    return false;
  }

  bool ok = false;
  FILE* out = NULL;
  FILE* in = NULL;
  time_t mt = (time_t) 0;
  const char* e = NULL;
  std::string ed;

  if (setegid(ig) != 0 || seteuid(iu) != 0) {
    fprintf(stderr, "cannot change effective UID/GID: %s\n", strerror(errno));
    close(fd);
    goto end;
  }

  out = fdopen(fd, "w");
  if (out == NULL) {
    fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno));
    close(fd);
    goto end;
  }

  in = fopen(tp.c_str(), "r");
  if (in == NULL) {
    if (errno == ENOENT) {
      in = fopen("/dev/null", "r");
      if (in == NULL) {
        fprintf(stderr, "cannot get empty table for '%s': %s\n", rUser.c_str(), strerror(errno));
        fclose(out);
        goto end;
      }
    }
    else {
      fprintf(stderr, "cannot read old table for '%s': %s\n", rUser.c_str(), strerror(errno));
      fclose(out);
      goto end;
    }
  }

  char buf[1024];
  while (fgets(buf, 1024, in) != NULL) {
    fputs(buf, out);
  }
  fclose(in);
  fclose(out);

  struct stat st;
  if (stat(s, &st) != 0) {
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
    goto end;
  }

  mt = st.st_mtime; // save modification time for detecting its change

  // Editor selecting algorithm:
  // 1. Check EDITOR environment variable
  // 2. Check VISUAL environment variable
  // 3. Try to get from configuration
  // 4. Check presence of /etc/alternatives/editor
  // 5. Use hard-wired editor

  e = getenv("EDITOR");
  if (e == NULL) {
    e = getenv("VISUAL");
    if (e == NULL) {

      if (!IncronCfg::GetValue("editor", ed))
        throw InotifyException("configuration is corrupted", EINVAL);

      if (!ed.empty()) {
        e = ed.c_str();
      }
      else {
        if (access(INCRON_ALT_EDITOR, X_OK) == 0)
          e = INCRON_ALT_EDITOR;
        else
          e = INCRON_DEFAULT_EDITOR;
      }
    }
  }

  // this block is explicite due to gotos' usage simplification
  {
    pid_t pid = fork();
    if (pid == 0) {
      if (setgid(gid) != 0 || setuid(uid) != 0) {
        fprintf(stderr, "cannot set user '%s': %s\n", rUser.c_str(), strerror(errno));
        goto end;
      }

      execlp(e, e, s, (const char*) NULL);
      _exit(1);
    }
    else if (pid > 0) {
      int status;
      if (wait(&status) != pid) {
        perror("error while waiting for editor");
        goto end;
      }
      if (!(WIFEXITED(status)) || WEXITSTATUS(status) != 0) {
        perror("editor finished with error");
        goto end;
      }
    }
    else {
      perror("cannot start editor");
      goto end;
    }
  }

  if (stat(s, &st) != 0) {
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
    goto end;
  }

  if (st.st_mtime == mt) {
    fprintf(stderr, "table unchanged\n");
    ok = true;
    goto end;
  }

  {
    IncronTab ict;
    if (ict.Load(s) && ict.Save(tp)) {
      if (chmod(tp.c_str(), S_IRUSR | S_IWUSR) != 0) {
        fprintf(stderr, "cannot change mode of temporary file: %s\n", strerror(errno));
      }
    }
    else {
      fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno));
      goto end;
    }

  }

  ok = true;
  fprintf(stderr, "table updated\n");

end:

  unlink(s);
  return ok;
}