Example #1
0
int main(int argc, char *argv[])
{
	/* We need to keep these env variables since systemd uses them for socket
	 * activation
	 */
	static const char *keep_env[] = {
		"LISTEN_FDS",
		"LISTEN_PID",
		NULL
	};

	const char	*root, *cwd, *env, *uid_str, *gid_str, *exe;
	char		**args;
	uid_t		uid;
	gid_t		*gids;
	size_t		n_gids;

	exit_if(argc < 7,
		"Usage: %s /path/to/root /work/directory /env/file uid gid[,gid...] /to/exec [args ...]", argv[0]);

	root = argv[1];
	cwd = argv[2];
	env = argv[3];
	uid_str = argv[4];
	uid = atoi(uid_str);
	gid_str = argv[5];
	args = &argv[6];
	exe = args[0];

	parse_gids(gid_str, &n_gids, &gids);
	load_env(env, keep_env);

	pexit_if(chroot(root) == -1, "Chroot \"%s\" failed", root);
	pexit_if(chdir(cwd) == -1, "Chdir \"%s\" failed", cwd);
	pexit_if(gids[0] > 0 && setresgid(gids[0], gids[0], gids[0]) == -1,
		"Setresgid \"%s\" failed", gid_str);
	pexit_if(n_gids > 1 && setgroups(n_gids - 1, &gids[1]) == -1,
		"Setgroups \"%s\" failed", gid_str);
	pexit_if(uid > 0 && setresuid(uid, uid, uid) == -1,
		"Setresuid \"%s\" failed", uid_str);

	/* XXX(vc): note that since execvp() is happening post-chroot, the
	 * app's environment settings correctly affect the PATH search.
	 * This is why execvpe() isn't being used, we manipulate the environment
	 * manually then let it potentially affect execvp().  execvpe() simply
	 * passes the environment to execve() _after_ performing the search, not
	 * what we want here. */
	pexit_if(execvp(exe, args) == -1 &&
		 errno != ENOENT && errno != EACCES,
		 "Exec of \"%s\" failed", exe);
	diag(exe);

	return EXIT_FAILURE;
}
Example #2
0
int startup(int argc, char* argv[])
{
  const char* tmp;
  const char* end;
  const char* cwdstr;
  char* ptr;
  unsigned long session_timeout;
  unsigned startup_code;

  if ((tmp = getenv("TCPLOCALIP")) == 0) FAIL("Missing $TCPLOCALIP.");
  if (!parse_localip(tmp)) FAIL("Could not parse $TCPLOCALIP.");
  if ((tmp = getenv("TCPREMOTEIP")) == 0) FAIL("Missing $TCPREMOTEIP.");
  if (!parse_remoteip(tmp)) FAIL("Could not parse $TCPREMOTEIP.");
  if ((tmp = getenv("UID")) == 0) FAIL("Missing $UID.");
  if (!(uid = strtou(tmp, &end)) || *end) FAIL("Invalid $UID.");
  if ((tmp = getenv("GID")) == 0) FAIL("Missing $GID.");
  if (!(gid = strtou(tmp, &end)) || *end) FAIL("Invalid $GID.");
  if ((home = getenv("HOME")) == 0) FAIL("Missing $HOME.");
  if ((tmp = getenv("GIDS")) != 0 && !parse_gids(tmp))
    FAIL("Could not parse or set supplementary group IDs.");

  /* Strip off trailing slashes in $HOME */
  ptr = (char*)home + strlen(home)-1;
  while (ptr > home && *ptr == '/') *ptr-- = 0;

  if ((user = getenv("USER")) == 0) FAIL("Missing $USER.");
  if ((group = getenv("GROUP")) == 0) group = "mygroup";
  if (chdir(home)) FAIL("Could not chdir to $HOME.");
  if (!load_tables()) FAIL("Loading startup tables failed.");
  if (getenv("CHROOT") != 0) {
    cwdstr = "/";
    if (chroot(".")) FAIL("Could not chroot.");
  }
  else if (getenv("SOFTCHROOT") != 0) {
    cwdstr = "/";
  }
  else {
    cwdstr = home;
    if (chdir("/")) FAIL("Could not chdir to '/'.");
  }
  if (!str_copys(&cwd, cwdstr)) FAIL("Could not set CWD string");
  if (setgid(gid)) FAIL("Could not set GID.");
  if (setuid(uid)) FAIL("Could not set UID.");
  if ((user_len = strlen(user)) > MAX_NAME_LEN) {
    user_len = MAX_NAME_LEN;
    ((char*)user)[MAX_NAME_LEN] = 0;
  }
  if ((group_len = strlen(group)) > MAX_NAME_LEN) {
    group_len = MAX_NAME_LEN;
    ((char*)group)[MAX_NAME_LEN] = 0;
  }

  lockhome = (getenv("LOCKHOME") != 0);
  nodotfiles = (getenv("NODOTFILES") != 0);
  list_options = (nodotfiles ? 0 : PATH_MATCH_DOTFILES);

  session_timeout = 0;
  if ((tmp = getenv("SESSION_TIMEOUT")) != 0)
    session_timeout = strtou(tmp, &tmp);
  alarm(session_timeout);
  connect_timeout = timeout;
  if ((tmp = getenv("CONNECT_TIMEOUT")) != 0)
    connect_timeout = strtou(tmp, &tmp);

  if ((tmp = getenv("TWOFTPD_BIND_PORT_FD")) != 0) {
    if ((bind_port_fd = strtou(tmp, &end)) == 0 || *end != 0)
      FAIL("Invalid $TWOFTPD_BIND_PORT_FD");
  }
  else
    bind_port_fd = -1;

  startup_code = (getenv("AUTHENTICATED") != 0) ? 230 : 220;
  if ((tmp = getenv("BANNER")) != 0) show_banner(startup_code, tmp);
  message_file = getenv("MESSAGEFILE");
  show_message_file(startup_code);
  return respond(startup_code, 1, "Ready to transfer files.");
  (void)argc;
  (void)argv;
}