예제 #1
0
파일: xssd.c 프로젝트: hjp/xssd
int main(int argc, char **argv) {
    FILE *fp;
    char cfgfile[128];
    char line[1024];
    int linenr = 0;
    int grant = 0;
    char **env = NULL;
    size_t env_a = 0;
    size_t env_i = 0;
    char *command = NULL;
    char *user;
    struct passwd *pw;
    int log_opts = LOG_PID | LOG_PERROR;
    int c;
    
    clean_fds();

    cmnd = argv[0];

    while ((c = getopt(argc, argv, "q")) != EOF) {
	switch(c) {
	    case 'q':
		log_opts &= !LOG_PERROR;
		break;
	    case '?':
		usage();
	    default:
		assert(0);
	}
    }

    if (argc - optind < 2) usage();

    user = argv[optind++];

    openlog("xssd", log_opts, LOG_AUTH);

    /* a / in either the username or the command name could be used to 
     * break out of /etc/xssd. Of course the user would actually have to 
     * exist to do harm, but better safe than sorry.
     */
    if (strchr(user, '/')) {
	syslog(LOG_ERR, "invalid username %s. [Ruid: %d]",
	       user, getuid());
	exit(1);
    }
    if (strchr(argv[optind], '/')) {
	syslog(LOG_ERR, "invalid command name %s. [Ruid: %d]",
	       argv[optind], getuid());
	exit(1);
    }

    snprintf(cfgfile, sizeof(cfgfile), "/etc/xssd/%s/%s",
	     user, argv[optind]);				/* check for return value unnecessary, because
	     							   fopen below will fail if no config file 
								   exists
								 */
    if ((fp = fopen(cfgfile, "r")) == NULL) {
	syslog(LOG_ERR, "%s: fopen failed: %s. [Ruid: %d]",
	       cfgfile, strerror(errno), getuid());
	exit(1);
    }
    while (fgets(line, sizeof(line), fp)) {
	int lp;

	linenr++;

	/* remove trailing white space */
	lp = strlen(line)-1;
	if (line[lp] != '\n') {
	    syslog(LOG_ERR, "config file %s[%d]: Line unterminated or too long. [Ruid: %d]",
		   cfgfile, linenr, getuid());
	    exit(1);
	}
	while (lp >= 0 && isspace((unsigned char)line[lp])) {
	    line[lp--] = '\0';
	}
	 

	/* Check for keywords. 
	 */
	if (*line == '#') {
	    continue;
	}
	if (strncmp(line, "Command:", strlen("Command:") ) == 0) {
	    int lp;

	    skip_ws(line, lp, strlen("Command:"));
	    command = strdup(line + lp);
	    continue;
	}
	if (strncmp(line, "User:"******"User:"******"User:"******"Group:", strlen("Group:") ) == 0) {
	    int lp;
	    struct group *gr;
	    skip_ws(line, lp, strlen("Group:"));

	    gr = getgrnam(line + lp);
	    if (gr) {
		if (gr->gr_gid == getgid()) {
		    grant = 1;
		} else {
		    gid_t groups[NGROUPS_MAX] = {0};
		    int ngroups = getgroups(NGROUPS_MAX, groups);
		    int i;
		    for (i = 0; i < ngroups; i++) {
			if (gr->gr_gid == groups[i]) {
			    grant = 1;
			}
		    }
		}
	    }
	    continue;
	}
	if (strncmp(line, "Env:", strlen("Env:") ) == 0) {
	    char *s;
	    int lp;
	    skip_ws(line, lp, strlen("Env:"));

	    fprintf(stderr, "Env: %s\n", line + lp);
	    s = getenv(line + lp);
	    if (s) {
		if (env_i >= env_a) {
		    env_a = env_a * 3 / 2 + 10;
		    if ((env = realloc(env, env_a * sizeof(*env))) == NULL) {
			syslog(LOG_ERR, "config file %s[%d]: cannot realloc env to %ld strings: %s. [Ruid: %d]",
			       cfgfile, linenr, (long)env_a, strerror(errno), getuid());
			exit(1);
		    }
		}
		if ((env[env_i] = malloc(strlen(line + lp) + 1 + strlen(s) + 1)) == NULL) {
		    syslog(LOG_ERR, "config file %s[%d]: cannot strdup env variable %s: %s. [Ruid: %d]",
			   cfgfile, linenr, line + lp, strerror(errno), getuid());
		}
		sprintf(env[env_i], "%s=%s", line + lp, s);
		env_i++;
	    }
	    continue;
	}
	/* if we get here, we have an unknown keyword or mistyped or ...
	 */
	fprintf(stderr, "Do not know what to do with \"%s\"\n", line);
	exit(1);
    }
    fclose(fp);
    if (env_i >= env_a) {
	env_a = env_a * 3 / 2 + 10;
	if ((env = realloc(env, env_a * sizeof(*env))) == NULL) {
	    syslog(LOG_ERR, "config file %s[%d]: cannot realloc env to %ld strings: %s. [Ruid: %d]",
		   cfgfile, linenr, (long)env_a, strerror(errno), getuid());
	    exit(1);
	}
    }
    env[env_i] = NULL;

    if (grant) {
	syslog(LOG_INFO, "%s: access granted. [Ruid: %d]", cfgfile, getuid());
    } else {
	syslog(LOG_NOTICE, "%s: access denied. [Ruid: %d]", cfgfile, getuid());
	exit(1);
    }

    pw = getpwnam (user); 
    if (pw == NULL) { 
	syslog(LOG_ERR, "%s: unknown target user %s. [Ruid: %d]",
	       cfgfile, user, getuid());
	exit(1);
    }
    if (initgroups(user, pw->pw_gid) == -1) {
	syslog(LOG_ERR, "%s: initgroups(%s, %d) failed: %s. [Ruid: %d]",
	       cfgfile, user, pw->pw_gid, strerror(errno), getuid());
	exit(1);
    }
    if (setgid(pw->pw_gid) == -1) {
	syslog(LOG_ERR, "%s: setgid(%d) failed: %s. [Ruid: %d]",
	       cfgfile, (int)pw->pw_gid, strerror(errno), getuid());
	exit(1);
    }
    if (setuid(pw->pw_uid) == -1) {
	syslog(LOG_ERR, "%s: setuid(%d) failed: %s. [Ruid: %d]",
	       cfgfile, (int)pw->pw_uid, strerror(errno), getuid());
	exit(1);
    }
    syslog(LOG_INFO, "%s: execing %s. [Ruid: %d]",
	   cfgfile, command, getuid());
    execve(command, argv + optind, env);
    syslog(LOG_ERR, "%s: execve(%s) failed: %s. [Ruid: %d]",
	   cfgfile, command, strerror(errno), getuid());

    return 1;
}
예제 #2
0
파일: cross.cpp 프로젝트: chenbk85/gserver
int main(int argc, char *argv[])
{ 
  if (argc == 1)
    print_usage();
  
  int in_guard_mode = 0;
  int dump_core = 0;
  int children_instance = 0;
  char *run_as_user = NULL;

  // parse args
  int c = -1;
  extern char *optarg;
  extern int optopt;

  const char *opt = ":gvu:Cs:ep:h";
  while((c = getopt(argc, argv, opt)) != -1)
  {
    switch (c)
    {
    case 'v':        // version
      fprintf(stderr, "\033[0;32m%s %s\033[0m\n", SVC_EDITION, BIN_V);
      return 0;
    case 'g':
      in_guard_mode = 1;
      break;
    case 'u':
      run_as_user = optarg;
      break;
    case 'C':
      dump_core = 1;
      break;
    case 'e':
      children_instance = 1;
      break;
    case 'p':
      break;
    case ':':
      fprintf(stderr, 
              "\n\033[0;35mOption -%c requires an operand\033[0m\n",
              optopt);
    case 'h':
    default:
      print_usage();
    }
  }

  const int max_clients = 1024*4;
  set_max_fds(max_clients);
  g_max_fds = get_max_fds();

  if (run_as_user && runas(run_as_user) != 0)
  {
    fprintf(stderr, "\033[0;35mSudo to %s error!\033[0m\n", 
            run_as_user);
    return -1;
  }

  if (dump_core && dump_corefile() != 0)
  {
    fprintf(stderr, "\033[0;35mSet dump corefile error!\033[0m\n");
    return -1;
  }

  if (in_guard_mode)
  {
    if (children_instance == 0)
      guard_process(g_svc_name, argc, argv);

    clean_fds();
  }else
    output_pid(g_svc_name);

  //= child process
  child_sig_handle();

  sys::r = new reactor();
  if (sys::r->open(max_clients, max_clients + 16) != 0)
  {
    fprintf(stderr, "Error: reactor - open failed!\n");
    return -1;
  }

  if (sys::init_svc() != 0)
  {
    fprintf(stderr, "Error: init_svc - init failed!\n");
    return -1;
  }

  s_log->rinfo("launch ok! max fds:%d", g_max_fds);
  e_log->rinfo("launch ok! max fds:%d", g_max_fds);

  // reactor event loop
  sys::r->run_reactor_event_loop();
  return 1;
}