void param_state_multipartite_mixed::initialize ( int n, int* subs, int d ) { nr_mixtures = d; nr_subspaces = n ; subspaces = new int[n] {}; dim = 1; nr_parameters=0; for ( int i = 0; i < n ; i++ ) { nr_parameters += subs[i]*subs[i]+abs ( subs[i] )-1; dim *= abs ( subs[i] ); subspaces[i] = abs ( subs[i] ); } nr_parameters *=nr_mixtures; nr_parameters += d-1; product_states = new param_state_multipartite[d] {}; for ( int i = 0; i < d ; i++ ) { product_states[i].initialize ( n , subs ); } parameters = new double [nr_parameters] {}; par_max = new double [nr_parameters] {}; par_min = new double [nr_parameters] {}; representation = new std::complex< double > [dim*dim] {}; temp1 = new std::complex< double > [dim*dim] {}; buffer = new std::complex< double > [dim*dim] {}; simplectic_prob = new double [d] {}; theta_simplex = new double [d-1] {}; set_limits(); }
void RelocIterator::initialize(intptr_t delta, CodeBlob* cb, address begin, address limit) { #ifndef CORE if (cb == NULL && delta == 0 && begin != NULL) { // allow CodeBlob to be deduced from beginning address cb = CodeCache::find_blob(begin); } assert(cb != NULL, "must be able to deduce nmethod from other arguments"); _code = cb; _current = cb->relocation_begin()-1; _end = cb->relocation_end(); _addr = (address) cb->instructions_begin(); assert(!has_current(), "just checking"); address code_end = cb->instructions_end(); assert(begin == NULL || begin >= delta + cb->instructions_begin(), "in bounds"); // FIX THIS assert(limit == NULL || limit <= delta + code_end, "in bounds"); if (begin != NULL) begin -= delta; if (limit != NULL) limit -= delta; set_limits(begin, limit); // after limits have been set and indexes consulted, then apply the delta if (delta == 0) { _is_copy = false; } else { _is_copy = true; _addr += delta; // we are operating on a copy of the code _limit += delta; } #endif // !CORE }
void param_state_multipartite::initialize ( int n, int* subs ) { nr_subspaces = n ; subspaces = new int[n] {}; dim = 1; for ( int i = 0; i < n ; i++ ) { nr_parameters += subs[i]*subs[i]+abs ( subs[i] )-1; dim *= abs ( subs[i] ); subspaces[i] = abs ( subs[i] ); } states = new param_state[n] {}; for ( int i = 0; i < n ; i++ ) { states[i].initialize ( abs ( subs[i] ) ); } parameters = new double [nr_parameters] {}; par_max = new double [nr_parameters] {}; par_min = new double [nr_parameters] {}; representation = new std::complex< double > [dim*dim] {}; temp1 = new std::complex< double > [dim*dim] {}; buffer = new std::complex< double > [dim*dim] {}; set_limits(); }
void initialize() { set_limits(); initialize_velocities(); randomize_particles(); initialize_pbest(); intialize_gbest(); }
Draw( double xmin, double xmax, double ymin, double ymax, unsigned dim_ = 2, const MPI_Comm comm = PETSC_COMM_WORLD ) : Draw( dim_, comm ) { set_limits( xmin, xmax, ymin, ymax ); }
RelocIterator::RelocIterator(CodeBuffer* cb, address begin, address limit) { #ifndef CORE _current = cb->locs_start()-1; _end = cb->locs_end(); _addr = (address) cb->code_begin(); _code = cb->get_blob(); assert(!has_current(), "just checking"); assert(begin == NULL || begin >= cb->code_begin(), "in bounds"); assert(limit == NULL || limit <= cb->code_end(), "in bounds"); set_limits(begin, limit); #endif // !CORE }
void param_state::initialize ( int n ) { dim = n ; nr_parameters = n*n+n-1; parameters = new double[nr_parameters] {}; representation = new std::complex< double >[n*n] {}; temp1 = new std::complex< double >[n*n] {}; simplex_angles = new double [n-1] {}; eigen = new std::complex< double >[n] {}; par_max = new double [nr_parameters] {}; par_min = new double [nr_parameters] {}; UN.initialize ( n ); set_limits(); }
int main(int argc, char **argv) { const char *config_file = "/etc/sniproxy.conf"; int background_flag = 1; int max_nofiles = 65536; int opt; while ((opt = getopt(argc, argv, "fc:n:V")) != -1) { switch (opt) { case 'c': config_file = optarg; break; case 'f': /* foreground */ background_flag = 0; break; case 'n': max_nofiles = atoi(optarg); break; case 'V': printf("sniproxy %s\n", sniproxy_version); #ifdef HAVE_LIBUDNS printf("compiled with udns support\n"); #endif return EXIT_SUCCESS; default: usage(); return EXIT_FAILURE; } } config = init_config(config_file, EV_DEFAULT); if (config == NULL) { fprintf(stderr, "Unable to load %s\n", config_file); usage(); return EXIT_FAILURE; } /* ignore SIGPIPE, or it will kill us */ signal(SIGPIPE, SIG_IGN); if (background_flag) { if (config->pidfile != NULL) remove(config->pidfile); daemonize(); if (config->pidfile != NULL) write_pidfile(config->pidfile, getpid()); } start_binder(); set_limits(max_nofiles); init_listeners(&config->listeners, &config->tables, EV_DEFAULT); /* Drop permissions only when we can */ drop_perms(config->user ? config->user : default_username); ev_signal_init(&sighup_watcher, signal_cb, SIGHUP); ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1); ev_signal_init(&sigusr2_watcher, signal_cb, SIGUSR2); ev_signal_init(&sigint_watcher, signal_cb, SIGINT); ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM); ev_signal_start(EV_DEFAULT, &sighup_watcher); ev_signal_start(EV_DEFAULT, &sigusr1_watcher); ev_signal_start(EV_DEFAULT, &sigusr2_watcher); ev_signal_start(EV_DEFAULT, &sigint_watcher); ev_signal_start(EV_DEFAULT, &sigterm_watcher); resolv_init(EV_DEFAULT, config->resolver.nameservers, config->resolver.search, config->resolver.mode); init_connections(); ev_run(EV_DEFAULT, 0); free_connections(EV_DEFAULT); resolv_shutdown(EV_DEFAULT); free_config(config, EV_DEFAULT); stop_binder(); return 0; }
// this function must be invoked by forked process void execute_command_in_jail( fs::path const& host_container_dir, container_options_t const& opts, linux::user const& user ) { // create virtual root for container construct_virtual_root( host_container_dir, opts.mount_points, opts.copy_points, user ); // into jail if ( ::chroot( host_container_dir.c_str() ) == -1 ) { std::stringstream ss; ss << "Failed to chroot: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } // move to home fs::current_path( opts.in_container_start_path ); // set limits set_limits( opts.limits ); set_limit( RLIMIT_STACK, opts.stack_size ); // overwrite host $PATH environment, to search an executable by execpve overwrite_path( opts.envs ); auto const& path = ::getenv( "PATH" ); if ( path != nullptr ) { std::cout << " = env PATH is " << path << std::endl; } // log std::cout << "[+] chrooted and resource limited!" << std::endl; // TODO: set umask // std::system("ls -la /proc/self/fd"); // redirect: pipes[debug] for( auto const& pr : opts.pipe_redirects ) { std::cout << "==> host fd: " << pr.host_fd << " will recieve data of child fd: " << pr.guest_fd << std::endl; } // redirect: pipes for( auto const& pr : opts.pipe_redirects ) { if ( ::dup2( pr.host_fd, pr.guest_fd ) == -1 ) { std::stringstream ss; ss << "Failed to dup2: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } if ( ::close( pr.host_fd ) == -1 ) { std::stringstream ss; ss << "Failed to close the host pipe: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } } // === discard privilege // remove supplementary groups const gid_t s_groups[] = {}; if ( ::setgroups( 0, s_groups ) == -1 ) { std::stringstream ss; ss << "Failed to setgroups: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } // change group if ( ::setresgid( user.group_id(), user.group_id(), user.group_id() ) == -1 ) { std::stringstream ss; ss << "Failed to setresgid: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } // change user if ( ::setresuid( user.user_id(), user.user_id(), user.user_id() ) == -1 ) { std::stringstream ss; ss << "Failed to setresuid: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } // === // == // now I am in the sandbox! // == if ( opts.commands.size() < 1 ) { std::stringstream ss; ss << "Failed to prepare environment: commands must have >= 1 elements (" << opts.commands.size() << ")"; throw std::runtime_error( ss.str() ); } auto const& filename = opts.commands[0]; auto argv_pack = make_buffer_for_execve( opts.commands ); auto& argv = std::get<0>( argv_pack ); auto envp_pack = make_buffer_for_execve( opts.envs ); auto& envp = std::get<0>( envp_pack ); // replace self process if ( ::execvpe( filename.c_str(), argv.data(), envp.data() ) == -1 ) { std::stringstream ss; ss << "Failed to execvpe: " << " errno=" << errno << " : " << std::strerror( errno ); throw std::runtime_error( ss.str() ); } }
int main(int argc, char **argv) #endif /* WIN32 */ { #ifdef WIN32 struct arg_param *p = (struct arg_param *)pv; int argc; char **argv; SERVICE_STATUS ss; #endif /* WIN32 */ char *name = NULL; struct tpp_config conf; int rpp_fd; char *pc; int numthreads; char lockfile[MAXPATHLEN + 1]; char path_log[MAXPATHLEN + 1]; char svr_home[MAXPATHLEN + 1]; char *log_file = 0; char *host; int port; char *routers = NULL; int c, i, rc; extern char *optarg; int are_primary; int num_var_env; #ifndef WIN32 struct sigaction act; struct sigaction oact; #endif #ifndef WIN32 /*the real deal or just pbs_version and exit*/ execution_mode(argc, argv); #endif /* As a security measure and to make sure all file descriptors */ /* are available to us, close all above stderr */ #ifdef WIN32 _fcloseall(); #else i = sysconf(_SC_OPEN_MAX); while (--i > 2) (void)close(i); /* close any file desc left open by parent */ #endif /* If we are not run with real and effective uid of 0, forget it */ #ifdef WIN32 argc = p->argc; argv = p->argv; ZeroMemory(&ss, sizeof(ss)); ss.dwCheckPoint = 0; ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwCurrentState = g_dwCurrentState; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; ss.dwWaitHint = 6000; if (g_ssHandle != 0) SetServiceStatus(g_ssHandle, &ss); if (!isAdminPrivilege(getlogin())) { fprintf(stderr, "%s: Must be run by root\n", argv[0]); return (2); } #else if ((getuid() != 0) || (geteuid() != 0)) { fprintf(stderr, "%s: Must be run by root\n", argv[0]); return (2); } #endif /* WIN32 */ /* set standard umask */ #ifndef WIN32 umask(022); #endif /* load the pbs conf file */ if (pbs_loadconf(0) == 0) { fprintf(stderr, "%s: Configuration error\n", argv[0]); return (1); } umask(022); #ifdef WIN32 save_env(); #endif /* The following is code to reduce security risks */ /* start out with standard umask, system resource limit infinite */ if ((num_var_env = setup_env(pbs_conf.pbs_environment)) == -1) { #ifdef WIN32 g_dwCurrentState = SERVICE_STOPPED; ss.dwCurrentState = g_dwCurrentState; ss.dwWin32ExitCode = ERROR_INVALID_ENVIRONMENT; if (g_ssHandle != 0) SetServiceStatus(g_ssHandle, &ss); return (1); #else exit(1); #endif /* WIN32 */ } #ifndef WIN32 i = getgid(); (void)setgroups(1, (gid_t *)&i); /* secure suppl. groups */ #endif log_event_mask = &pbs_conf.pbs_comm_log_events; tpp_set_logmask(*log_event_mask); #ifdef WIN32 winsock_init(); #endif routers = pbs_conf.pbs_comm_routers; numthreads = pbs_conf.pbs_comm_threads; server_host[0] = '\0'; if (pbs_conf.pbs_comm_name) { name = pbs_conf.pbs_comm_name; host = tpp_parse_hostname(name, &port); if (host) snprintf(server_host, sizeof(server_host), "%s", host); free(host); host = NULL; } else if (pbs_conf.pbs_leaf_name) { char *endp; snprintf(server_host, sizeof(server_host), "%s", pbs_conf.pbs_leaf_name); endp = strchr(server_host, ','); /* find the first name */ if (endp) *endp = '\0'; endp = strchr(server_host, ':'); /* cut out the port */ if (endp) *endp = '\0'; name = server_host; } else { if (gethostname(server_host, (sizeof(server_host) - 1)) == -1) { #ifndef WIN32 sprintf(log_buffer, "Could not determine my hostname, errno=%d", errno); #else sprintf(log_buffer, "Could not determine my hostname, errno=%d", WSAGetLastError()); #endif fprintf(stderr, "%s\n", log_buffer); return (1); } if ((get_fullhostname(server_host, server_host, (sizeof(server_host) - 1)) == -1)) { sprintf(log_buffer, "Could not determine my hostname"); fprintf(stderr, "%s\n", log_buffer); return (1); } name = server_host; } if (server_host[0] == '\0') { sprintf(log_buffer, "Could not determine server host"); fprintf(stderr, "%s\n", log_buffer); return (1); } while ((c = getopt(argc, argv, "r:t:e:N")) != -1) { switch (c) { case 'e': *log_event_mask = strtol(optarg, NULL, 0); break; case 'r': routers = optarg; break; case 't': numthreads = atol(optarg); if (numthreads == -1) { usage(argv[0]); return (1); } break; case 'N': stalone = 1; break; default: usage(argv[0]); return (1); } } (void)strcpy(daemonname, "Comm@"); (void)strcat(daemonname, name); if ((pc = strchr(daemonname, (int)'.')) != NULL) *pc = '\0'; if(set_msgdaemonname(daemonname)) { fprintf(stderr, "Out of memory\n"); return 1; } (void) snprintf(path_log, sizeof(path_log), "%s/%s", pbs_conf.pbs_home_path, PBS_COMM_LOGDIR); #ifdef WIN32 /* * let SCM wait 10 seconds for log_open() to complete * as it does network interface query which can take time */ ss.dwCheckPoint++; ss.dwWaitHint = 60000; if (g_ssHandle != 0) SetServiceStatus(g_ssHandle, &ss); #endif (void) log_open(log_file, path_log); /* set pbs_comm's process limits */ set_limits(); /* set_limits can call log_record, so call only after opening log file */ /* set tcp function pointers */ set_tpp_funcs(log_tppmsg); (void) snprintf(svr_home, sizeof(svr_home), "%s/%s", pbs_conf.pbs_home_path, PBS_SVR_PRIVATE); if (chdir(svr_home) != 0) { (void) sprintf(log_buffer, msg_init_chdir, svr_home); log_err(-1, __func__, log_buffer); return (1); } (void) sprintf(lockfile, "%s/%s/comm.lock", pbs_conf.pbs_home_path, PBS_SVR_PRIVATE); if ((are_primary = are_we_primary()) == FAILOVER_SECONDARY) { strcat(lockfile, ".secondary"); } else if (are_primary == FAILOVER_CONFIG_ERROR) { sprintf(log_buffer, "Failover configuration error"); log_err(-1, __func__, log_buffer); #ifdef WIN32 g_dwCurrentState = SERVICE_STOPPED; ss.dwCurrentState = g_dwCurrentState; ss.dwWin32ExitCode = ERROR_SERVICE_NOT_ACTIVE; if (g_ssHandle != 0) SetServiceStatus(g_ssHandle, &ss); #endif return (3); } if ((lockfds = open(lockfile, O_CREAT | O_WRONLY, 0600)) < 0) { (void) sprintf(log_buffer, "pbs_comm: unable to open lock file"); log_err(errno, __func__, log_buffer); return (1); } if ((host = tpp_parse_hostname(name, &port)) == NULL) { sprintf(log_buffer, "Out of memory parsing leaf name"); log_err(errno, __func__, log_buffer); return (1); } rc = 0; if (pbs_conf.auth_method == AUTH_RESV_PORT) { rc = set_tpp_config(&pbs_conf, &conf, host, port, routers, pbs_conf.pbs_use_compression, TPP_AUTH_RESV_PORT, NULL, NULL); } else { /* for all non-resv-port based authentication use a callback from TPP */ rc = set_tpp_config(&pbs_conf, &conf, host, port, routers, pbs_conf.pbs_use_compression, TPP_AUTH_EXTERNAL, get_ext_auth_data, validate_ext_auth_data); } if (rc == -1) { (void) sprintf(log_buffer, "Error setting TPP config"); log_err(-1, __func__, log_buffer); return (1); } free(host); i = 0; if (conf.routers) { while (conf.routers[i]) { sprintf(log_buffer, "Router[%d]:%s", i, conf.routers[i]); fprintf(stdout, "%s\n", log_buffer); log_event(PBSEVENT_SYSTEM | PBSEVENT_FORCE, PBS_EVENTCLASS_SERVER, LOG_INFO, msg_daemonname, log_buffer); i++; } } #ifndef DEBUG #ifndef WIN32 if (stalone != 1) go_to_background(); #endif #endif #ifdef WIN32 ss.dwCheckPoint = 0; g_dwCurrentState = SERVICE_RUNNING; ss.dwCurrentState = g_dwCurrentState; if (g_ssHandle != 0) SetServiceStatus(g_ssHandle, &ss); #endif if (already_forked == 0) lock_out(lockfds, F_WRLCK); /* go_to_backgroud call creates a forked process, * thus print/log pid only after go_to_background() * has been called */ sprintf(log_buffer, "%s ready (pid=%d), Proxy Name:%s, Threads:%d", argv[0], getpid(), conf.node_name, numthreads); fprintf(stdout, "%s\n", log_buffer); log_event(PBSEVENT_SYSTEM | PBSEVENT_FORCE, PBS_EVENTCLASS_SERVER, LOG_INFO, msg_daemonname, log_buffer); #ifndef DEBUG pbs_close_stdfiles(); #endif #ifdef WIN32 signal(SIGINT, stop_me); signal(SIGTERM, stop_me); #else sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = hup_me; if (sigaction(SIGHUP, &act, &oact) != 0) { log_err(errno, __func__, "sigaction for HUP"); return (2); } act.sa_handler = stop_me; if (sigaction(SIGINT, &act, &oact) != 0) { log_err(errno, __func__, "sigaction for INT"); return (2); } if (sigaction(SIGTERM, &act, &oact) != 0) { log_err(errno, __func__, "sigactin for TERM"); return (2); } if (sigaction(SIGQUIT, &act, &oact) != 0) { log_err(errno, __func__, "sigactin for QUIT"); return (2); } #ifdef SIGSHUTDN if (sigaction(SIGSHUTDN, &act, &oact) != 0) { log_err(errno, __func__, "sigactin for SHUTDN"); return (2); } #endif /* SIGSHUTDN */ act.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &act, &oact) != 0) { log_err(errno, __func__, "sigaction for PIPE"); return (2); } if (sigaction(SIGUSR1, &act, &oact) != 0) { log_err(errno, __func__, "sigaction for USR1"); return (2); } if (sigaction(SIGUSR2, &act, &oact) != 0) { log_err(errno, __func__, "sigaction for USR2"); return (2); } #endif /* WIN32 */ conf.node_type = TPP_ROUTER_NODE; conf.numthreads = numthreads; if ((rpp_fd = tpp_init_router(&conf)) == -1) { log_err(-1, __func__, "tpp init failed\n"); return 1; } /* Protect from being killed by kernel */ daemon_protect(0, PBS_DAEMON_PROTECT_ON); /* go in a while loop */ while (get_out == 0) { if (hupped == 1) { struct pbs_config pbs_conf_bak; int new_logevent; hupped = 0; /* reset back */ memcpy(&pbs_conf_bak, &pbs_conf, sizeof(struct pbs_config)); if (pbs_loadconf(1) == 0) { log_tppmsg(LOG_CRIT, NULL, "Configuration error, ignoring"); memcpy(&pbs_conf, &pbs_conf_bak, sizeof(struct pbs_config)); } else { /* restore old pbs.conf */ new_logevent = pbs_conf.pbs_comm_log_events; memcpy(&pbs_conf, &pbs_conf_bak, sizeof(struct pbs_config)); pbs_conf.pbs_comm_log_events = new_logevent; log_tppmsg(LOG_INFO, NULL, "Processed SIGHUP"); log_event_mask = &pbs_conf.pbs_comm_log_events; tpp_set_logmask(*log_event_mask); } } sleep(3); } tpp_router_shutdown(); log_event(PBSEVENT_SYSTEM | PBSEVENT_FORCE, PBS_EVENTCLASS_SERVER, LOG_NOTICE, msg_daemonname, "Exiting"); log_close(1); lock_out(lockfds, F_UNLCK); /* unlock */ (void)close(lockfds); (void)unlink(lockfile); return 0; }
int main(const int argc, char * const argv[]) /*@globals environ, errno@*/ /*@modifies environ, errno@*/ { struct passwd *pw; char **target_env = environ; static char *empty_env[] = { NULL }; environ = empty_env; (void) umask(~(mode_t)0); /* (no file perms, if signalled to dump core)*/ /* check that calling UID exists, is not root, and shell matches */ if (NULL != (pw = getpwuid(getuid())) && 0 != pw->pw_uid && 0 == memcmp(pw->pw_shell,CHROOTING_SHELL,sizeof(CHROOTING_SHELL)) ) { /* require commands of the form: "sh" "-c" "command args args args" */ if (3 == argc && 0 == memcmp(argv[1], "-c", 3)) { const char *chroot_dir = (const char *)pw->pw_dir; const char *home = "/"; struct stat st; if (0 == memcmp(pw->pw_dir, GROUP_CHROOT_DIR, sizeof(GROUP_CHROOT_DIR)-1) && getgroups(0, (gid_t *)NULL) > 1) { chroot_dir = GROUP_CHROOT_DIR; home = (const char *)pw->pw_dir+(sizeof(GROUP_CHROOT_DIR)-2); if (*home != '/' && *++home != '/') { home = "/"; } } if (!( 0 == stat(chroot_dir, &st) && pw->pw_uid != st.st_uid /* (not caller; typically root) */ && 0 == (st.st_mode & (S_IWGRP|S_IWOTH)))) { fatal(argc, pw, chroot_dir); } openlog("chressh", LOG_NDELAY|LOG_PID, LOG_AUTHPRIV); if (/*@-superuser@*/ 0 == chroot(chroot_dir) /*@=superuser@*/ && 0 == setuid(getuid()) && 0 != setuid(0) && 0 == chdir(home)) { char **target_argv; size_t len; errno = 0; /* (reset errno after expected setuid(0) failure) */ environ = target_env = env_clean(target_env, pw, home); target_argv = shell_parse(argv[2]); if (NULL == target_argv || NULL == target_argv[0]) { fatal(argc, pw, NULL); } (void) umask((mode_t)UMASK); if (0 == strcmp(target_argv[0], "scp")) { if (0 == set_limits(NPROC_SCP)) { (void) execve(CHROOTED_CMD_DIR "scp", target_argv, target_env); } } else if (0 == strcmp(target_argv[0], "rsync")) { if (0 == filter_args_rsync(target_argv) && 0 == set_limits(NPROC_RSYNC)) { (void) execve(CHROOTED_CMD_DIR "rsync", target_argv, target_env); } } else if (0 == strcmp(target_argv[0], "unison")) { if (0 == filter_args_unison(target_argv) && 0 == set_limits(NPROC_UNISON)) { (void) execve(CHROOTED_CMD_DIR "unison", target_argv, target_env); } } else { if ( 11 <= (len = strlen(target_argv[0])) && 0 == memcmp(target_argv[0]+len-11, "sftp-server", 11) && 0 == set_limits(NPROC_SFTP_SERVER)) { /*('chressh -c /usr/local/libexec/sftp-server')*/ /*(only tests for "sftp-server" suffix, which is fine)*/ /*(discard additional args to sftp-server, if present)*/ char sftp_server[] = "sftp-server"; char *target_argv_static[] = { sftp_server, NULL }; (void) execve(CHROOTED_CMD_DIR "sftp-server", target_argv_static, target_env); } } #if 0 /* which code do you think is clearer? above or below? */ switch ((len = strlen(target_argv[0]))) { case 3: if (0 == memcmp(target_argv[0], "scp", 3) && 0 == set_limits(NPROC_SCP)) { (void) execve(CHROOTED_CMD_DIR "scp", target_argv, target_env); } break; case 5: if (0 == memcmp(target_argv[0], "rsync", 5) && 0 == filter_args_rsync(target_argv) && 0 == set_limits(NPROC_RSYNC)) { (void) execve(CHROOTED_CMD_DIR "rsync", target_argv, target_env); } break; case 6: if (0 == memcmp(target_argv[0], "unison", 6) && 0 == filter_args_unison(target_argv) && 0 == set_limits(NPROC_UNISON)) { (void) execve(CHROOTED_CMD_DIR "unison", target_argv, target_env); } break; default: if ( 11 <= len && 0 == memcmp(target_argv[0]+len-11, "sftp-server", 11) && 0 == set_limits(NPROC_SFTP_SERVER)) { /*('chressh -c /usr/local/libexec/sftp-server')*/ /*(only tests for "sftp-server" suffix, which is fine)*/ /*(discard additional args to sftp-server, if present)*/ char sftp_server[] = "sftp-server"; char *target_argv_static[] = { sftp_server, NULL }; (void) execve(CHROOTED_CMD_DIR "sftp-server", target_argv_static, target_env); } break; } #endif } } #ifdef PASSWD_PROGRAM /* If login attempt (argc == 1), use PASSWD_PROGRAM as 'shell' * (*argv[0] == '-', too, for login shells on most (all?) systems) * (privileges intentionally dropped even if passwd_program setuid) */ else if (1 == argc && 0 == setuid(getuid()) && 0 != setuid(0)) { char passwd_program[] = PASSWD_PROGRAM; char *target_argv[] = { passwd_program, NULL }; errno = 0; /* (reset errno after expected setuid(0) failure) */ target_env = env_clean(target_env, pw, NULL); (void) execve(PASSWD_PROGRAM, target_argv, target_env); } #endif } fatal(argc, pw, NULL); return 0; /*(UNREACHED)*/ }