/* * Main program. Initialize us, disconnect us from the tty if necessary, * and loop waiting for I/O and/or timer expiries. */ int ntpdmain( int argc, char *argv[] ) { l_fp now; struct recvbuf *rbuf; #ifdef _AIX /* HMS: ifdef SIGDANGER? */ struct sigaction sa; #endif progname = argv[0]; initializing = 1; /* mark that we are initializing */ process_commandline_opts(&argc, &argv); init_logging(progname, 1); /* Open the log file */ #ifdef HAVE_UMASK { mode_t uv; uv = umask(0); if(uv) (void) umask(uv); else (void) umask(022); } #endif #if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ { uid_t uid; uid = getuid(); if (uid && !HAVE_OPT( SAVECONFIGQUIT )) { msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid); printf("must be run as root, not uid %ld\n", (long)uid); exit(1); } } #endif /* getstartup(argc, argv); / * startup configuration, may set debug */ #ifdef DEBUG debug = DESC(DEBUG_LEVEL).optOccCt; DPRINTF(1, ("%s\n", Version)); #endif /* honor -l/--logfile option to log to a file */ setup_logfile(); /* * Enable the Multi-Media Timer for Windows? */ #ifdef SYS_WINNT if (HAVE_OPT( MODIFYMMTIMER )) set_mm_timer(MM_TIMER_HIRES); #endif if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ) #ifdef DEBUG || debug #endif || HAVE_OPT( SAVECONFIGQUIT )) nofork = 1; if (HAVE_OPT( NOVIRTUALIPS )) listen_to_virtual_ips = 0; /* * --interface, listen on specified interfaces */ if (HAVE_OPT( INTERFACE )) { int ifacect = STACKCT_OPT( INTERFACE ); const char** ifaces = STACKLST_OPT( INTERFACE ); sockaddr_u addr; while (ifacect-- > 0) { add_nic_rule( is_ip_address(*ifaces, &addr) ? MATCH_IFADDR : MATCH_IFNAME, *ifaces, -1, ACTION_LISTEN); ifaces++; } } if (HAVE_OPT( NICE )) priority_done = 0; #if defined(HAVE_SCHED_SETSCHEDULER) if (HAVE_OPT( PRIORITY )) { config_priority = OPT_VALUE_PRIORITY; config_priority_override = 1; priority_done = 0; } #endif #ifdef SYS_WINNT /* * Start interpolation thread, must occur before first * get_systime() */ init_winnt_time(); #endif /* * Initialize random generator and public key pair */ get_systime(&now); ntp_srandom((int)(now.l_i * now.l_uf)); #if !defined(VMS) # ifndef NODETACH /* * Detach us from the terminal. May need an #ifndef GIZMO. */ if (!nofork) { /* * Install trap handlers to log errors and assertion * failures. Default handlers print to stderr which * doesn't work if detached. */ isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); # ifndef SYS_WINNT # ifdef HAVE_DAEMON daemon(0, 0); # else /* not HAVE_DAEMON */ if (fork()) /* HMS: What about a -1? */ exit(0); { #if !defined(F_CLOSEM) u_long s; int max_fd; #endif /* !FCLOSEM */ if (syslog_file != NULL) { fclose(syslog_file); syslog_file = NULL; } #if defined(F_CLOSEM) /* * From 'Writing Reliable AIX Daemons,' SG24-4946-00, * by Eric Agar (saves us from doing 32767 system * calls) */ if (fcntl(0, F_CLOSEM, 0) == -1) msyslog(LOG_ERR, "ntpd: failed to close open files(): %m"); #else /* not F_CLOSEM */ # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) max_fd = sysconf(_SC_OPEN_MAX); # else /* HAVE_SYSCONF && _SC_OPEN_MAX */ max_fd = getdtablesize(); # endif /* HAVE_SYSCONF && _SC_OPEN_MAX */ for (s = 0; s < max_fd; s++) (void) close((int)s); #endif /* not F_CLOSEM */ (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); init_logging(progname, 0); /* we lost our logfile (if any) daemonizing */ setup_logfile(); #ifdef SYS_DOMAINOS { uid_$t puid; status_$t st; proc2_$who_am_i(&puid); proc2_$make_server(&puid, &st); } #endif /* SYS_DOMAINOS */ #if defined(HAVE_SETPGID) || defined(HAVE_SETSID) # ifdef HAVE_SETSID if (setsid() == (pid_t)-1) msyslog(LOG_ERR, "ntpd: setsid(): %m"); # else if (setpgid(0, 0) == -1) msyslog(LOG_ERR, "ntpd: setpgid(): %m"); # endif #else /* HAVE_SETPGID || HAVE_SETSID */ { # if defined(TIOCNOTTY) int fid; fid = open("/dev/tty", 2); if (fid >= 0) { (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0); (void) close(fid); } # endif /* defined(TIOCNOTTY) */ # ifdef HAVE_SETPGRP_0 (void) setpgrp(); # else /* HAVE_SETPGRP_0 */ (void) setpgrp(0, getpid()); # endif /* HAVE_SETPGRP_0 */ } #endif /* HAVE_SETPGID || HAVE_SETSID */ #ifdef _AIX /* Don't get killed by low-on-memory signal. */ sa.sa_handler = catch_danger; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; (void) sigaction(SIGDANGER, &sa, NULL); #endif /* _AIX */ } # endif /* not HAVE_DAEMON */ # endif /* SYS_WINNT */ } # endif /* NODETACH */ #endif /* VMS */ #ifdef SCO5_CLOCK /* * SCO OpenServer's system clock offers much more precise timekeeping * on the base CPU than the other CPUs (for multiprocessor systems), * so we must lock to the base CPU. */ { int fd = open("/dev/at1", O_RDONLY); if (fd >= 0) { int zero = 0; if (ioctl(fd, ACPU_LOCK, &zero) < 0) msyslog(LOG_ERR, "cannot lock to base CPU: %m"); close( fd ); } /* else ... * If we can't open the device, this probably just isn't * a multiprocessor system, so we're A-OK. */ } #endif #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE) # ifdef HAVE_SETRLIMIT /* * Set the stack limit to something smaller, so that we don't lock a lot * of unused stack memory. */ { struct rlimit rl; /* HMS: must make the rlim_cur amount configurable */ if (getrlimit(RLIMIT_STACK, &rl) != -1 && (rl.rlim_cur = 50 * 4096) < rl.rlim_max) { if (setrlimit(RLIMIT_STACK, &rl) == -1) { msyslog(LOG_ERR, "Cannot adjust stack limit for mlockall: %m"); } } # ifdef RLIMIT_MEMLOCK /* * The default RLIMIT_MEMLOCK is very low on Linux systems. * Unless we increase this limit malloc calls are likely to * fail if we drop root privlege. To be useful the value * has to be larger than the largest ntpd resident set size. */ rl.rlim_cur = rl.rlim_max = 32*1024*1024; if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) { msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); } # endif /* RLIMIT_MEMLOCK */ } # endif /* HAVE_SETRLIMIT */ /* * lock the process into memory */ if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) msyslog(LOG_ERR, "mlockall(): %m"); #else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ # ifdef HAVE_PLOCK # ifdef PROCLOCK # ifdef _AIX /* * set the stack limit for AIX for plock(). * see get_aix_stack() for more info. */ if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0) { msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m"); } # endif /* _AIX */ /* * lock the process into memory */ if (plock(PROCLOCK) < 0) msyslog(LOG_ERR, "plock(PROCLOCK): %m"); # else /* not PROCLOCK */ # ifdef TXTLOCK /* * Lock text into ram */ if (plock(TXTLOCK) < 0) msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); # else /* not TXTLOCK */ msyslog(LOG_ERR, "plock() - don't know what to lock!"); # endif /* not TXTLOCK */ # endif /* not PROCLOCK */ # endif /* HAVE_PLOCK */ #endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ /* * Set up signals we pay attention to locally. */ #ifdef SIGDIE1 (void) signal_no_reset(SIGDIE1, finish); #endif /* SIGDIE1 */ #ifdef SIGDIE2 (void) signal_no_reset(SIGDIE2, finish); #endif /* SIGDIE2 */ #ifdef SIGDIE3 (void) signal_no_reset(SIGDIE3, finish); #endif /* SIGDIE3 */ #ifdef SIGDIE4 (void) signal_no_reset(SIGDIE4, finish); #endif /* SIGDIE4 */ #ifdef SIGBUS (void) signal_no_reset(SIGBUS, finish); #endif /* SIGBUS */ #if !defined(SYS_WINNT) && !defined(VMS) # ifdef DEBUG (void) signal_no_reset(MOREDEBUGSIG, moredebug); (void) signal_no_reset(LESSDEBUGSIG, lessdebug); # else (void) signal_no_reset(MOREDEBUGSIG, no_debug); (void) signal_no_reset(LESSDEBUGSIG, no_debug); # endif /* DEBUG */ #endif /* !SYS_WINNT && !VMS */ /* * Set up signals we should never pay attention to. */ #if defined SIGPIPE (void) signal_no_reset(SIGPIPE, SIG_IGN); #endif /* SIGPIPE */ /* * Call the init_ routines to initialize the data structures. * * Exactly what command-line options are we expecting here? */ init_auth(); init_util(); init_restrict(); init_mon(); init_timer(); init_lib(); init_request(); init_control(); init_peer(); #ifdef REFCLOCK init_refclock(); #endif set_process_priority(); init_proto(); /* Call at high priority */ init_io(); init_loopfilter(); mon_start(MON_ON); /* monitor on by default now */ /* turn off in config if unwanted */ /* * Get the configuration. This is done in a separate module * since this will definitely be different for the gizmo board. */ getconfig(argc, argv); report_event(EVNT_SYSRESTART, NULL, NULL); loop_config(LOOP_DRIFTCOMP, old_drift); initializing = 0; #ifdef HAVE_DROPROOT if( droproot ) { /* Drop super-user privileges and chroot now if the OS supports this */ #ifdef HAVE_LINUX_CAPABILITIES /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) { msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); exit(-1); } #else /* we need a user to switch to */ if (user == NULL) { msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); exit(-1); } #endif /* HAVE_LINUX_CAPABILITIES */ if (user != NULL) { if (isdigit((unsigned char)*user)) { sw_uid = (uid_t)strtoul(user, &endp, 0); if (*endp != '\0') goto getuser; if ((pw = getpwuid(sw_uid)) != NULL) { user = strdup(pw->pw_name); if (NULL == user) { msyslog(LOG_ERR, "strdup() failed: %m"); exit (-1); } sw_gid = pw->pw_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find user ID %s", user); exit (-1); } } else { getuser: errno = 0; if ((pw = getpwnam(user)) != NULL) { sw_uid = pw->pw_uid; sw_gid = pw->pw_gid; } else { if (errno) msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user); else msyslog(LOG_ERR, "Cannot find user `%s'", user); exit (-1); } } } if (group != NULL) { if (isdigit((unsigned char)*group)) { sw_gid = (gid_t)strtoul(group, &endp, 0); if (*endp != '\0') goto getgroup; } else { getgroup: if ((gr = getgrnam(group)) != NULL) { sw_gid = gr->gr_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find group `%s'", group); exit (-1); } } } if (chrootdir ) { /* make sure cwd is inside the jail: */ if (chdir(chrootdir)) { msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); exit (-1); } if (chroot(chrootdir)) { msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); exit (-1); } if (chdir("/")) { msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m"); exit (-1); } } if (user && initgroups(user, sw_gid)) { msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user); exit (-1); } if (group && setgid(sw_gid)) { msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); exit (-1); } if (group && setegid(sw_gid)) { msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); exit (-1); } if (group) setgroups(1, &sw_gid); else initgroups(pw->pw_name, pw->pw_gid); if (user && setuid(sw_uid)) { msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); exit (-1); } if (user && seteuid(sw_uid)) { msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); exit (-1); } #ifndef HAVE_LINUX_CAPABILITIES /* * for now assume that the privilege to bind to privileged ports * is associated with running with uid 0 - should be refined on * ports that allow binding to NTP_PORT with uid != 0 */ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ #endif if (disable_dynamic_updates && interface_interval) { interface_interval = 0; msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking"); } #ifdef HAVE_LINUX_CAPABILITIES do { /* * We may be running under non-root uid now, but we still hold full root privileges! * We drop all of them, except for the crucial one or two: cap_sys_time and * cap_net_bind_service if doing dynamic interface tracking. */ cap_t caps; char *captext = (interface_interval) ? "cap_sys_time,cap_net_bind_service=ipe" : "cap_sys_time=ipe"; if( ! ( caps = cap_from_text( captext ) ) ) { msyslog( LOG_ERR, "cap_from_text() failed: %m" ); exit(-1); } if( cap_set_proc( caps ) == -1 ) { msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" ); exit(-1); } cap_free( caps ); } while(0); #endif /* HAVE_LINUX_CAPABILITIES */ } /* if( droproot ) */ #endif /* HAVE_DROPROOT */ /* * Use select() on all on all input fd's for unlimited * time. select() will terminate on SIGALARM or on the * reception of input. Using select() means we can't do * robust signal handling and we get a potential race * between checking for alarms and doing the select(). * Mostly harmless, I think. */ /* On VMS, I suspect that select() can't be interrupted * by a "signal" either, so I take the easy way out and * have select() time out after one second. * System clock updates really aren't time-critical, * and - lacking a hardware reference clock - I have * yet to learn about anything else that is. */ #if defined(HAVE_IO_COMPLETION_PORT) for (;;) { GetReceivedBuffers(); #else /* normal I/O */ BLOCK_IO_AND_ALARM(); was_alarmed = 0; for (;;) { # if !defined(HAVE_SIGNALED_IO) extern fd_set activefds; extern int maxactivefd; fd_set rdfdes; int nfound; # endif if (alarm_flag) /* alarmed? */ { was_alarmed = 1; alarm_flag = 0; } if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE) { /* * Nothing to do. Wait for something. */ # ifndef HAVE_SIGNALED_IO rdfdes = activefds; # if defined(VMS) || defined(SYS_VXWORKS) /* make select() wake up after one second */ { struct timeval t1; t1.tv_sec = 1; t1.tv_usec = 0; nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, (fd_set *)0, &t1); } # else nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, (fd_set *)0, (struct timeval *)0); # endif /* VMS */ if (nfound > 0) { l_fp ts; get_systime(&ts); (void)input_handler(&ts); } else if (nfound == -1 && errno != EINTR) msyslog(LOG_ERR, "select() error: %m"); # ifdef DEBUG else if (debug > 5) msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); # endif /* DEBUG */ # else /* HAVE_SIGNALED_IO */ wait_for_signal(); # endif /* HAVE_SIGNALED_IO */ if (alarm_flag) /* alarmed? */ { was_alarmed = 1; alarm_flag = 0; } } if (was_alarmed) { UNBLOCK_IO_AND_ALARM(); /* * Out here, signals are unblocked. Call timer routine * to process expiry. */ timer(); was_alarmed = 0; BLOCK_IO_AND_ALARM(); } #endif /* ! HAVE_IO_COMPLETION_PORT */ #ifdef DEBUG_TIMING { l_fp pts; l_fp tsa, tsb; int bufcount = 0; get_systime(&pts); tsa = pts; #endif rbuf = get_full_recv_buffer(); while (rbuf != NULL) { if (alarm_flag) { was_alarmed = 1; alarm_flag = 0; } UNBLOCK_IO_AND_ALARM(); if (was_alarmed) { /* avoid timer starvation during lengthy I/O handling */ timer(); was_alarmed = 0; } /* * Call the data procedure to handle each received * packet. */ if (rbuf->receiver != NULL) /* This should always be true */ { #ifdef DEBUG_TIMING l_fp dts = pts; L_SUB(&dts, &rbuf->recv_time); DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); collect_timing(rbuf, "buffer processing delay", 1, &dts); bufcount++; #endif (rbuf->receiver)(rbuf); } else { msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING"); abort(); } BLOCK_IO_AND_ALARM(); freerecvbuf(rbuf); rbuf = get_full_recv_buffer(); } #ifdef DEBUG_TIMING get_systime(&tsb); L_SUB(&tsb, &tsa); if (bufcount) { collect_timing(NULL, "processing", bufcount, &tsb); DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); } } #endif /* * Go around again */ #ifdef HAVE_DNSREGISTRATION if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) { mdnsreg = current_time; msyslog(LOG_INFO, "Attempting to register mDNS"); if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { if (!--mdnstries) { msyslog(LOG_ERR, "Unable to register mDNS, giving up."); } else { msyslog(LOG_INFO, "Unable to register mDNS, will try later."); } } else { msyslog(LOG_INFO, "mDNS service registered."); mdnsreg = 0; } } #endif /* HAVE_DNSREGISTRATION */ } UNBLOCK_IO_AND_ALARM(); return 1; } #ifdef SIGDIE2 /* * finish - exit gracefully */ static RETSIGTYPE finish( int sig ) { msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig); #ifdef HAVE_DNSREGISTRATION if (mdns != NULL) DNSServiceRefDeallocate(mdns); #endif switch (sig) { # ifdef SIGBUS case SIGBUS: printf("\nfinish(SIGBUS)\n"); exit(0); # endif case 0: /* Should never happen... */ return; default: exit(0); } }
int main(int argc, char **argv) { int ch; const char *caldir; (void)setprogname(argv[0]); /* for portability */ while ((ch = getopt(argc, argv, "-ad:f:l:vw:x")) != -1) { switch (ch) { case '-': /* backward contemptible */ case 'a': if (getuid()) { errno = EPERM; err(EXIT_FAILURE, NULL); } doall = true; break; case 'd': datestr = optarg; break; case 'f': fname = optarg; break; case 'l': atodays(ch, optarg, &lookahead); break; case 'v': printf("%s\n", CALENDAR_VERSION); return 0; case 'w': atodays(ch, optarg, &weekend); break; case 'x': cpp_restricted = true; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc) usage(); settime(); if (doall) { /* * XXX - This ignores the user's CALENDAR_DIR variable. * Run under user's login shell? */ if (setgroups(0, NULL) == -1) { err(EXIT_FAILURE, "setgroups"); } while ((pw = getpwent()) != NULL) { if (setegid(pw->pw_gid) == -1) { warn("%s: setegid", pw->pw_name); continue; } if (seteuid(pw->pw_uid) == -1) { warn("%s: seteuid", pw->pw_name); continue; } if (chdir(pw->pw_dir) != -1) { cal(); } if (seteuid(0) == -1) { warn("%s: seteuid back to 0", pw->pw_name); } } } else if ((caldir = getenv("CALENDAR_DIR")) != NULL) { if (chdir(caldir) != -1) cal(); } else if ((pw = getpwuid(geteuid())) != NULL) { if (chdir(pw->pw_dir) != -1) cal(); } return 0; }
void create() { seteuid(getuid()); }
void test_init_app() { printf("\nTesting init app\n"); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } FILE* creds = fopen(TEST_ROOT "/creds.txt", "w"); if (creds == NULL) { printf("FAIL: failed to create credentials file - %s\n", strerror(errno)); exit(1); } if (fprintf(creds, "secret key\n") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(creds) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } FILE* job_xml = fopen(TEST_ROOT "/job.xml", "w"); if (job_xml == NULL) { printf("FAIL: failed to create job file - %s\n", strerror(errno)); exit(1); } if (fprintf(job_xml, "<jobconf/>\n") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(job_xml) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } if (seteuid(user_detail->pw_uid) != 0) { printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno)); exit(1); } fflush(stdout); fflush(stderr); pid_t child = fork(); if (child == -1) { printf("FAIL: failed to fork process for init_app - %s\n", strerror(errno)); exit(1); } else if (child == 0) { char *final_pgm[] = {"touch", "my-touch-file", 0}; if (initialize_app(username, "app_4", TEST_ROOT "/creds.txt", final_pgm, extract_values(local_dirs), extract_values(log_dirs)) != 0) { printf("FAIL: failed in child\n"); exit(42); } // should never return exit(1); } int status = 0; if (waitpid(child, &status, 0) <= 0) { printf("FAIL: failed waiting for process %d - %s\n", child, strerror(errno)); exit(1); } if (access(TEST_ROOT "/logs/userlogs/app_4", R_OK) != 0) { printf("FAIL: failed to create app log directory\n"); exit(1); } char* app_dir = get_app_directory(TEST_ROOT "/local-1", username, "app_4"); if (access(app_dir, R_OK) != 0) { printf("FAIL: failed to create app directory %s\n", app_dir); exit(1); } char buffer[100000]; sprintf(buffer, "%s/jobToken", app_dir); if (access(buffer, R_OK) != 0) { printf("FAIL: failed to create credentials %s\n", buffer); exit(1); } sprintf(buffer, "%s/my-touch-file", app_dir); if (access(buffer, R_OK) != 0) { printf("FAIL: failed to create touch file %s\n", buffer); exit(1); } free(app_dir); app_dir = get_app_log_directory("logs","app_4"); if (access(app_dir, R_OK) != 0) { printf("FAIL: failed to create app log directory %s\n", app_dir); exit(1); } free(app_dir); }
int main(int argc, char **argv) { LOGFILE = stdout; ERRORFILE = stderr; int my_username = 0; // clean up any junk from previous run system("chmod -R u=rwx " TEST_ROOT "; rm -fr " TEST_ROOT); if (mkdirs(TEST_ROOT "/logs/userlogs", 0755) != 0) { exit(1); } if (write_config_file(TEST_ROOT "/test.cfg") != 0) { exit(1); } read_config(TEST_ROOT "/test.cfg"); local_dirs = (char *) malloc (sizeof(char) * ARRAY_SIZE); strcpy(local_dirs, NM_LOCAL_DIRS); log_dirs = (char *) malloc (sizeof(char) * ARRAY_SIZE); strcpy(log_dirs, NM_LOG_DIRS); create_nm_roots(extract_values(local_dirs)); if (getuid() == 0 && argc == 2) { username = argv[1]; } else { username = strdup(getpwuid(getuid())->pw_name); my_username = 1; } set_nm_uid(geteuid(), getegid()); if (set_user(username)) { exit(1); } printf("\nStarting tests\n"); printf("\nTesting get_user_directory()\n"); test_get_user_directory(); printf("\nTesting get_app_directory()\n"); test_get_app_directory(); printf("\nTesting get_container_directory()\n"); test_get_container_directory(); printf("\nTesting get_container_launcher_file()\n"); test_get_container_launcher_file(); printf("\nTesting get_app_log_dir()\n"); test_get_app_log_dir(); test_check_configuration_permissions(); printf("\nTesting delete_container()\n"); test_delete_container(); printf("\nTesting delete_app()\n"); test_delete_app(); test_delete_user(); test_check_user(); // the tests that change user need to be run in a subshell, so that // when they change user they don't give up our privs run_test_in_child("test_signal_container", test_signal_container); run_test_in_child("test_signal_container_group", test_signal_container_group); // init app and run container can't be run if you aren't testing as root if (getuid() == 0) { // these tests do internal forks so that the change_owner and execs // don't mess up our process. test_init_app(); test_run_container(); } seteuid(0); run("rm -fr " TEST_ROOT); printf("\nFinished tests\n"); if (my_username) { free(username); } free_configurations(); return 0; }
int main(int argc, char *argv[]) { struct passwd *pw; struct group *gptr; const char *arg, *cp, *printer; char *p; char buf[BUFSIZ]; int c, i, f, errs; int ret, didlink; struct stat stb; struct stat statb1, statb2; struct printer myprinter, *pp = &myprinter; printer = NULL; euid = geteuid(); uid = getuid(); seteuid(uid); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, cleanup); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanup); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, cleanup); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, cleanup); progname = argv[0]; gethostname(local_host, sizeof(local_host)); openlog("lpd", 0, LOG_LPR); errs = 0; while ((c = getopt(argc, argv, ":#:1:2:3:4:C:J:L:P:T:U:Z:cdfghi:lnmprstvw:")) != -1) switch (c) { case '#': /* n copies */ i = strtol(optarg, &p, 10); if (*p) errx(1, "Bad argument to -#, number expected"); if (i > 0) ncopies = i; break; case '1': /* troff fonts */ case '2': case '3': case '4': fonts[optopt - '1'] = optarg; break; case 'C': /* classification spec */ hdr++; class = optarg; break; case 'J': /* job name */ hdr++; jobname = optarg; break; case 'P': /* specifiy printer name */ printer = optarg; break; case 'L': /* pr's locale */ locale = optarg; break; case 'T': /* pr's title line */ title = optarg; break; case 'U': /* user name */ hdr++; Uflag = optarg; break; case 'Z': Zflag = optarg; break; case 'c': /* print cifplot output */ case 'd': /* print tex output (dvi files) */ case 'g': /* print graph(1G) output */ case 'l': /* literal output */ case 'n': /* print ditroff output */ case 't': /* print troff output (cat files) */ case 'p': /* print using ``pr'' */ case 'v': /* print vplot output */ format = optopt; break; case 'f': /* print fortran output */ format = 'r'; break; case 'h': /* nulifiy header page */ hdr = 0; break; case 'i': /* indent output */ iflag++; indent = strtol(optarg, &p, 10); if (*p) errx(1, "Bad argument to -i, number expected"); break; case 'm': /* send mail when done */ mailflg++; break; case 'q': /* just queue job */ qflag++; break; case 'r': /* remove file when done */ rflag++; break; case 's': /* try to link files */ sflag++; break; case 'w': /* versatec page width */ width = optarg; break; case ':': /* catch "missing argument" error */ if (optopt == 'i') { iflag++; /* -i without args is valid */ indent = 8; } else errs++; break; default: errs++; } argc -= optind; argv += optind; if (errs) usage(); if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; chkprinter(printer, pp); if (pp->no_copies && ncopies > 1) errx(1, "multiple copies are not allowed"); if (pp->max_copies > 0 && ncopies > pp->max_copies) errx(1, "only %ld copies are allowed", pp->max_copies); /* * Get the identity of the person doing the lpr using the same * algorithm as lprm. Actually, not quite -- lprm will override * the login name with "root" if the user is running as root; * the daemon actually checks for the string "root" in its * permission checking. Sigh. */ userid = getuid(); if (Uflag) { if (userid != 0 && userid != pp->daemon_user) errx(1, "only privileged users may use the `-U' flag"); lpr_username = Uflag; /* -U person doing 'lpr' */ } else { lpr_username = getlogin(); /* person doing 'lpr' */ if (userid != pp->daemon_user || lpr_username == 0) { if ((pw = getpwuid(userid)) == NULL) errx(1, "Who are you?"); lpr_username = pw->pw_name; } } /* * Check for restricted group access. */ if (pp->restrict_grp != NULL && userid != pp->daemon_user) { if ((gptr = getgrnam(pp->restrict_grp)) == NULL) errx(1, "Restricted group specified incorrectly"); if (gptr->gr_gid != getgid()) { while (*gptr->gr_mem != NULL) { if ((strcmp(lpr_username, *gptr->gr_mem)) == 0) break; gptr->gr_mem++; } if (*gptr->gr_mem == NULL) errx(1, "Not a member of the restricted group"); } } /* * Check to make sure queuing is enabled if userid is not root. */ lock_file_name(pp, buf, sizeof buf); if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS)) errx(1, "Printer queue is disabled"); /* * Initialize the control file. */ mktemps(pp); tfd = nfile(tfname); seteuid(euid); (void) fchown(tfd, pp->daemon_user, -1); /* owned by daemon for protection */ seteuid(uid); card('H', local_host); card('P', lpr_username); card('C', class); if (hdr && !pp->no_header) { if (jobname == NULL) { if (argc == 0) jobname = "stdin"; else jobname = ((arg = strrchr(argv[0], '/')) ? arg + 1 : argv[0]); } card('J', jobname); card('L', lpr_username); } if (format != 'p' && Zflag != 0) card('Z', Zflag); if (iflag) card('I', itoa(indent)); if (mailflg) card('M', lpr_username); if (format == 't' || format == 'n' || format == 'd') for (i = 0; i < 4; i++) if (fonts[i] != NULL) card('1'+i, fonts[i]); if (width != NULL) card('W', width); /* * XXX * Our use of `Z' here is incompatible with LPRng's * use. We assume that the only use of our existing * `Z' card is as shown for `p' format (pr) files. */ if (format == 'p') { char *s; if (locale) card('Z', locale); else if ((s = setlocale(LC_TIME, "")) != NULL) card('Z', s); } /* * Read the files and spool them. */ if (argc == 0) copy(pp, 0, " "); else while (argc--) { if (argv[0][0] == '-' && argv[0][1] == '\0') { /* use stdin */ copy(pp, 0, " "); argv++; continue; } if ((f = test(arg = *argv++)) < 0) continue; /* file unreasonable */ if (sflag && (cp = linked(arg)) != NULL) { (void) snprintf(buf, sizeof(buf), "%u %u", statb.st_dev, statb.st_ino); card('S', buf); if (format == 'p') card('T', title ? title : arg); for (i = 0; i < ncopies; i++) card(format, &dfname[inchar-2]); card('U', &dfname[inchar-2]); if (f) card('U', cp); card('N', arg); dfname[inchar]++; nact++; continue; } if (sflag) printf("%s: %s: not linked, copying instead\n", progname, arg); if (f) { /* * The user wants the file removed after it is copied * to the spool area, so see if the file can be moved * instead of copy/unlink'ed. This is much faster and * uses less spool space than copying the file. This * can be very significant when running services like * samba, pcnfs, CAP, et al. */ seteuid(euid); didlink = 0; /* * There are several things to check to avoid any * security issues. Some of these are redundant * under BSD's, but are necessary when lpr is built * under some other OS's (which I do do...) */ if (lstat(arg, &statb1) < 0) goto nohardlink; if (S_ISLNK(statb1.st_mode)) goto nohardlink; if (link(arg, dfname) != 0) goto nohardlink; didlink = 1; /* * Make sure the user hasn't tried to trick us via * any race conditions */ if (lstat(dfname, &statb2) < 0) goto nohardlink; if (statb1.st_dev != statb2.st_dev) goto nohardlink; if (statb1.st_ino != statb2.st_ino) goto nohardlink; /* * Skip if the file already had multiple hard links, * because changing the owner and access-bits would * change ALL versions of the file */ if (statb2.st_nlink > 2) goto nohardlink; /* * If we can access and remove the original file * without special setuid-ness then this method is * safe. Otherwise, abandon the move and fall back * to the (usual) copy method. */ seteuid(uid); ret = access(dfname, R_OK); if (ret == 0) ret = unlink(arg); seteuid(euid); if (ret != 0) goto nohardlink; /* * Unlink of user file was successful. Change the * owner and permissions, add entries to the control * file, and skip the file copying step. */ chown(dfname, pp->daemon_user, getegid()); chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); seteuid(uid); if (format == 'p') card('T', title ? title : arg); for (i = 0; i < ncopies; i++) card(format, &dfname[inchar-2]); card('U', &dfname[inchar-2]); card('N', arg); nact++; continue; nohardlink: if (didlink) unlink(dfname); seteuid(uid); /* restore old uid */ } /* end: if (f) */ if ((i = open(arg, O_RDONLY)) < 0) { printf("%s: cannot open %s\n", progname, arg); } else { copy(pp, i, arg); (void) close(i); if (f && unlink(arg) < 0) printf("%s: %s: not removed\n", progname, arg); } } if (nact) { (void) close(tfd); tfname[inchar]--; /* * Touch the control file to fix position in the queue. */ seteuid(euid); if ((tfd = open(tfname, O_RDWR)) >= 0) { char touch_c; if (read(tfd, &touch_c, 1) == 1 && lseek(tfd, (off_t)0, 0) == 0 && write(tfd, &touch_c, 1) != 1) { printf("%s: cannot touch %s\n", progname, tfname); tfname[inchar]++; cleanup(0); } (void) close(tfd); } if (link(tfname, cfname) < 0) { printf("%s: cannot rename %s\n", progname, cfname); tfname[inchar]++; cleanup(0); } unlink(tfname); seteuid(uid); if (qflag) /* just q things up */ exit(0); if (!startdaemon(pp)) printf("jobs queued, but cannot start daemon.\n"); exit(0); } cleanup(0); return (1); /* NOTREACHED */ }
void create() { seteuid(getuid()); set_name(HIW"巫师工作服"NOR,({"wizard suit","suit" }));
/** * Executes the python script by forking and calling execl. The python * script sge.py calls the commands qsub, qstat, qdel, etc. and writes * the result to a text file that is later readed by this C program. * Before this call the process changes its UID to the UID of the * account specified. * @param user String with the user account to execute the script under * @param script Absolute route to the script * @param scriptExec name of the executable (arg[0]) * @param action First parameter for sge.py, see sge.py for details * @param parameter Second parameter for sge.py, see sge.py for details * @param outputFile Third parameter for sge.py, this is a temporal file * created to pass the information between the python script and this * C program * @return 0 if everything is OK, NOTAUTHORIZEDFAULT otherwise */ int executeScript(char * user, char * script, char * scriptExec, char * action, char * parameter, char * outputFile) { int fd; pid_t pid; struct passwd *pw; char *arg0, buf[512]; //Make a temporal file for the script output fd = mkstemp(outputFile); if (fd == -1) { perror("executeScript: mkstemp"); return BESE_SYS_ERR; } #ifdef ROOTACCESS if (!user) { return BESE_SYS_ERR; } if ((pw = getpwnam(user)) == NULL) { fprintf(stderr, "executeScript: couldn't get user %s from passwd\n", user); return BESE_SYS_ERR; } #endif if ((pid = fork()) < 0) { fprintf(stderr,"executeScript: fork"); return BESE_SYS_ERR; } if (pid == 0) { #ifdef ROOTACCESS // child process if (seteuid(0)) { perror("executeScript (child): setuid 0"); _exit(1); } if (setgid(pw->pw_gid)) { perror("executeScript (child): setgid"); _exit(1); } if (setuid(pw->pw_uid)) { perror("executeScript (child): setuid"); _exit(1); } #endif execlp(script, scriptExec, action, parameter, outputFile, (char*) NULL); perror("executeScript (child): execl"); _exit(1); } else{ /* parent process */ if (waitpid(pid, NULL, 0) < 0) { perror("executeScript: waitpid"); return BESE_SYS_ERR; } } close(fd); return BESE_OK; }
void test_run_container() { printf("\nTesting run container\n"); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } FILE* creds = fopen(TEST_ROOT "/creds.txt", "w"); if (creds == NULL) { printf("FAIL: failed to create credentials file - %s\n", strerror(errno)); exit(1); } if (fprintf(creds, "secret key\n") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(creds) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } char * cgroups_pids[] = { TEST_ROOT "/cgroups-pid1.txt", TEST_ROOT "/cgroups-pid2.txt", 0 }; close(creat(cgroups_pids[0], O_RDWR)); close(creat(cgroups_pids[1], O_RDWR)); const char* script_name = TEST_ROOT "/container-script"; FILE* script = fopen(script_name, "w"); if (script == NULL) { printf("FAIL: failed to create script file - %s\n", strerror(errno)); exit(1); } if (seteuid(user_detail->pw_uid) != 0) { printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno)); exit(1); } if (fprintf(script, "#!/bin/bash\n" "touch foobar\n" "exit 0") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(script) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } fflush(stdout); fflush(stderr); char* container_dir = get_container_work_directory(TEST_ROOT "/local-1", yarn_username, "app_4", "container_1"); const char * pid_file = TEST_ROOT "/pid.txt"; pid_t child = fork(); if (child == -1) { printf("FAIL: failed to fork process for init_app - %s\n", strerror(errno)); exit(1); } else if (child == 0) { if (launch_container_as_user(yarn_username, "app_4", "container_1", container_dir, script_name, TEST_ROOT "/creds.txt", pid_file, local_dirs, log_dirs, "cgroups", cgroups_pids) != 0) { printf("FAIL: failed in child\n"); exit(42); } // should never return exit(1); } int status = 0; if (waitpid(child, &status, 0) <= 0) { printf("FAIL: failed waiting for process %d - %s\n", child, strerror(errno)); exit(1); } if (access(TEST_ROOT "/logs/userlogs/app_4/container_1", R_OK) != 0) { printf("FAIL: failed to create container log directory\n"); exit(1); } if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create container directory %s\n", container_dir); exit(1); } char buffer[100000]; sprintf(buffer, "%s/foobar", container_dir); if (access(buffer, R_OK) != 0) { printf("FAIL: failed to create touch file %s\n", buffer); exit(1); } free(container_dir); container_dir = get_app_log_directory(TEST_ROOT "/logs/userlogs", "app_4/container_1"); if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create app log directory %s\n", container_dir); exit(1); } free(container_dir); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } check_pid_file(pid_file, child); check_pid_file(cgroups_pids[0], child); check_pid_file(cgroups_pids[1], child); }
/* _sn 编号 _ts 时间 qu 问题 an 答案 wei 权重 aid 作者id */ void create() { ::create(); seteuid(getuid()); }
int main(int argc, char *argv[]) { struct stat st; static int socket_serv_fd = -1; char buf[64], shell[PATH_MAX], *result, debuggable[PROPERTY_VALUE_MAX]; char enabled[PROPERTY_VALUE_MAX], build_type[PROPERTY_VALUE_MAX]; char root_settings[PROPERTY_VALUE_MAX]; int i, dballow; mode_t orig_umask; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) { if (++i < argc) { su_to.command = argv[i]; } else { usage(); } } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--shell")) { if (++i < argc) { strncpy(shell, argv[i], sizeof(shell)); shell[sizeof(shell) - 1] = 0; } else { usage(); } } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { printf("%s\n", VERSION); exit(EXIT_SUCCESS); } else if (!strcmp(argv[i], "-V")) { printf("%d\n", VERSION_CODE); exit(EXIT_SUCCESS); } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { usage(); } else if (!strcmp(argv[i], "-") || !strcmp(argv[i], "-l") || !strcmp(argv[i], "--login")) { ++i; break; } else { break; } } if (i < argc-1) { usage(); } if (i == argc-1) { struct passwd *pw; pw = getpwnam(argv[i]); if (!pw) { su_to.uid = atoi(argv[i]); } else { su_to.uid = pw->pw_uid; } } if (from_init(&su_from) < 0) { deny(); } property_get("ro.debuggable", debuggable, "0"); property_get(ROOT_ACCESS_PROPERTY, enabled, ROOT_ACCESS_DEFAULT); property_get("ro.build.type", build_type, ""); property_get(ROOT_SETTINGS_PROPERTY, root_settings, ""); orig_umask = umask(027); // Root Settings-specific behavior if (strcmp("1", root_settings) == 0) { // only allow su on debuggable builds if (strcmp("1", debuggable) != 0) { LOGE("Root access is disabled on non-debug builds"); deny(); } // enforce persist.sys.root_access on non-eng builds if (strcmp("eng", build_type) != 0 && (atoi(enabled) & 1) != 1 ) { LOGE("Root access is disabled by system setting - enable it under settings -> developer options"); deny(); } // disallow su in a shell if appropriate if (su_from.uid == AID_SHELL && (atoi(enabled) == 1)) { LOGE("Root access is disabled by a system setting - enable it under settings -> developer options"); deny(); } } if (su_from.uid == AID_ROOT || su_from.uid == AID_SHELL) allow(shell, orig_umask); if (stat(REQUESTOR_DATA_PATH, &st) < 0) { PLOGE("stat"); deny(); } if (st.st_gid != st.st_uid) { LOGE("Bad uid/gid %d/%d for Superuser Requestor application", (int)st.st_uid, (int)st.st_gid); deny(); } if (mkdir(REQUESTOR_CACHE_PATH, 0770) >= 0) { chown(REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid); } setgroups(0, NULL); setegid(st.st_gid); seteuid(st.st_uid); LOGE("sudb - Opening database"); db = database_init(); if (!db) { LOGE("sudb - Could not open database, prompt user"); // if the database could not be opened, we can assume we need to // prompt the user dballow = DB_INTERACTIVE; } else { LOGE("sudb - Database opened"); dballow = database_check(db, &su_from, &su_to); // Close the database, we're done with it. If it stays open, // it will cause problems sqlite3_close(db); db = NULL; LOGE("sudb - Database closed"); } switch (dballow) { case DB_DENY: deny(); case DB_ALLOW: allow(shell, orig_umask); case DB_INTERACTIVE: break; default: deny(); } socket_serv_fd = socket_create_temp(); if (socket_serv_fd < 0) { deny(); } signal(SIGHUP, cleanup_signal); signal(SIGPIPE, cleanup_signal); signal(SIGTERM, cleanup_signal); signal(SIGABRT, cleanup_signal); atexit(cleanup); if (send_intent(&su_from, &su_to, socket_path, -1, 0) < 0) { deny(); } if (socket_receive_result(socket_serv_fd, buf, sizeof(buf)) < 0) { deny(); } close(socket_serv_fd); socket_cleanup(); result = buf; if (!strcmp(result, "DENY")) { deny(); } else if (!strcmp(result, "ALLOW")) { allow(shell, orig_umask); } else { LOGE("unknown response from Superuser Requestor: %s", result); deny(); } deny(); return -1; }
int perform(object me, object target) { string msg,temp,temp1; int extra,num,num1; int myexp,yourexp, exp_bonus,cond; object weapon,shadow,hisweapon,newweapon; extra = me->query_skill("xinyue-dagger",1); exp_bonus = (me->query("combat_exp")-3000000)/3000*extra/1000; if (exp_bonus> extra) exp_bonus=extra; if(me->query("class")!="wolfmount") return notify_fail("只有狼山弟子才能使出「斗转星移」的绝技。\n"); if ( extra < 106) return notify_fail("你的[新月斩]还不够纯熟!\n"); if( !target ) target = offensive_target(me); if( !target || !target->is_character() || !me->is_fighting(target) ) return notify_fail("[斗转星移]只能对战斗中的对手使用。\n"); weapon = me->query_temp("weapon"); myexp=me->query("combat_exp"); yourexp=target->query("combat_exp"); msg = HIR "$N一声长啸:"NOR+" "+HIC"斗"NOR+" "+HIY"转"NOR+ " "+HIW"星"NOR+" "+HIB"移"NOR+"\n"; message_vision(msg,me); if ((myexp*3/4+random(myexp*4)>yourexp)&& !target->query_temp("is_unconcious")) { msg= MAG"\n$N仿佛置身于一个极大的漩涡中,攻出的招式竟然反击回来!\n\n"NOR; message_vision(msg,target); seteuid(getuid()); if (!userp(target)) { sscanf(file_name(target),"%s#%d",temp,num); shadow=new(temp); } else { shadow=new("/d/fy/npc/shadefigure"); shadow->changeshape(target); if(hisweapon=target->query_temp("weapon")) { sscanf(file_name(hisweapon),"%s#%d",temp1,num1); newweapon=new(temp1); newweapon->move(shadow); newweapon->wield(); } } shadow->set("owner",me); shadow->set("possessed",me); shadow->move(environment(me)); if (!target->query_temp("weapon")) if (newweapon=shadow->query_temp("weapon")) newweapon->unequip(); shadow->add_killer(target->query("id")); simulate_set(target,shadow); shadow->add_temp("apply/attack", extra/2); message_vision(HIC " 斗\n" NOR,me); COMBAT_D->do_attack(shadow,target,msg); if (target->query_temp("damaged_during_attack")) target->set_temp("last_damage_from",me); message_vision(YEL " 转\n" NOR,me); simulate_set(target,shadow); COMBAT_D->do_attack(shadow,target,msg); if (target->query_temp("damaged_during_attack")) target->set_temp("last_damage_from",me); message_vision(HIW " 星\n" NOR,me); simulate_set(target,shadow); COMBAT_D->do_attack(shadow,target,msg); if (target->query_temp("damaged_during_attack")) target->set_temp("last_damage_from",me); message_vision(HIB " 移\n" NOR,me); simulate_set(target,shadow); COMBAT_D->do_attack(shadow,target,msg); if (target->query_temp("damaged_during_attack")) target->set_temp("last_damage_from",me); shadow->add_temp("apply/attack", -extra/2); if (me->is_killing(target->query("id"))) cond=1; destruct(shadow); }
void create() { seteuid(getuid()); set_name("采石工",({"worker"}));
QgsGrassShell::QgsGrassShell( QgsGrassTools *tools, QTabWidget * parent, const char * name ): QDialog( parent ), QgsGrassShellBase(), mTools( tools ) { mValid = false; mSkipLines = 2; mTabWidget = parent; #ifdef WIN32 QMessageBox::warning( 0, "Warning", "GRASS Shell is not supported on Windows." ); return; #else setupUi( this ); QGridLayout *layout = new QGridLayout( mTextFrame, 1, 1 ); mText = new QgsGrassShellText( this, mTextFrame ); layout->addWidget( mText, 0, 0 ); mText->show(); connect( mCloseButton, SIGNAL( clicked() ), this, SLOT( closeShell() ) ); mFont = QFont( "Courier", 10 ); mAppDir = mTools->appDir(); #ifndef Q_WS_MAC // Qt4.3.2/Mac Q3TextEdit readOnly property causes keys to be processed as keyboard actions mText->setReadOnly( TRUE ); #endif //mText->setFocusPolicy ( QWidget::NoFocus ); // To get key press directly #ifndef HAVE_OPENPTY mText->append( "GRASS shell is not supported" ); return; #endif // TODO set cursor IbeamCursor // This does not work - the cursor is used for scrollbars -> disabled //mText->setCursor ( QCursor(Qt::IbeamCursor) ); mParagraph = -1; // first will be 0 mIndex = -1; mNewLine = true; for ( int i = 0; i < ModeCount; i++ ) { resetMode( i ); } int uid; seteuid( uid = getuid() ); /* Run unprivileged */ // Get and open pseudo terminal // Note: 0 (stdin), 1 (stdout) or 2 (stderr) int fdSlave; // slave file descriptor seteuid( 0 ); int ret = openpty( &mFdMaster, &fdSlave, NULL, NULL, NULL ); if ( ret != 0 ) { QMessageBox::warning( 0, "Warning", "Cannot open pseudo terminal" ); return; } fchown( fdSlave, uid, ( gid_t ) - 1 ); fchmod( fdSlave, S_IRUSR | S_IWUSR ); seteuid( uid ); QgsDebugMsg( QString( "mFdMaster = %1" ).arg( mFdMaster ) ); QgsDebugMsg( QString( "fdSlave = %1" ).arg( fdSlave ) ); fcntl( mFdMaster, F_SETFL, O_NDELAY ); //fcntl( fdSlave, F_SETFL, O_NDELAY); // enable? QString slaveName = ttyname( fdSlave ); QgsDebugMsg( QString( "master ttyname = %1" ).arg( ttyname( mFdMaster ) ) ); QgsDebugMsg( QString( "slave ttyname = %1" ).arg( ttyname( fdSlave ) ) ); //::close( fdSlave ); // -> crash // Fork slave and open shell int pid = fork(); QgsDebugMsg( QString( "pid = %1" ).arg( pid ) ); if ( pid == -1 ) { QMessageBox::warning( 0, "Warning", "Cannot fork shell" ); return; } // Child - slave if ( pid == 0 ) { QgsDebugMsg( "child ->" ); // TODO close all opened file descriptors - close(0)??? ::close( mFdMaster ); //::close( fdSlave ); // -> freeze setsid(); seteuid( 0 ); int fd = ::open(( char* ) slaveName.ascii(), O_RDWR ); if ( fd < 0 ) { QMessageBox::warning( 0, "Warning", "Cannot open slave file " "in child process" ); return; } fchown( fd, uid, ( gid_t ) - 1 ); fchmod( fd, S_IRUSR | S_IWUSR ); setuid( uid ); dup2( fd, 0 ); /* stdin */ dup2( fd, 1 ); /* stdout */ dup2( fd, 2 ); /* stderr */ // TODO: test if shell is available QString shell = ( getenv( "SHELL" ) ); if ( shell.isEmpty() ) { shell = "/bin/bash"; } const char *norc = ""; QFileInfo si( shell ); if ( si.fileName() == "bash" || si.fileName() == "sh" ) { norc = "--norc"; } else if ( si.fileName() == "tcsh" || si.fileName() == "csh" ) { norc = "-f"; } // Warning: execle + --norc will not inherit not given variables // -> overwrite here const char *env = "GRASS_MESSAGE_FORMAT=gui"; char *envstr = new char[strlen( env )+1]; strcpy( envstr, env ); putenv( envstr ); putenv(( char * ) "GISRC_MODE_MEMORY" ); // unset env = "PS1=GRASS > "; envstr = new char[strlen( env )+1]; strcpy( envstr, env ); putenv( envstr ); env = "TERM=vt100"; envstr = new char[strlen( env )+1]; strcpy( envstr, env ); putenv( envstr ); //char *envar[] = { "PS1=GRASS > ", "TERM=vt100", "GISRC_MODE_MEMORY=", // "GRASS_MESSAGE_FORMAT=gui", (char *)0 }; //execle ( (char*)shell.ascii(), (char *)si.fileName().ascii(), // norc, (char *) 0, envar); execl(( char* )shell.ascii(), ( char * )si.fileName().ascii(), norc, ( char * ) 0 ); // Failed (QMessageBox here does not work) fprintf( stderr, "GRASS_INFO_ERROR(1,1): Cannot start shell %s\n", ( char* )shell.ascii() ); exit( 1 ); } mPid = pid; // Create socket notifier mOutNotifier = new QSocketNotifier( mFdMaster, QSocketNotifier::Read, this ); QObject::connect( mOutNotifier, SIGNAL( activated( int ) ), this, SLOT( readStdout( int ) ) ); // Set tab stops ??? mTabStop.resize( 200 ); for ( int i = 0 ; i * 8 < ( int )mTabStop.size(); i++ ) { mTabStop[i*8] = true; } // Set trap to write history on SIGUSR1 //QString trap = "trap 'history -w' SIGUSR1\015\012"; QString trap = "trap 'history -w' SIGUSR1\015"; write( mFdMaster, trap.ascii(), trap.length() ); mText->clear(); resizeTerminal(); mValid = true; #endif // !WIN32 }
int main (int argc, char *argv[]) { char *dir = NULL; char *spec, *host; char *nspec = NULL; int c, i; int nopt = 0; int vopt = 0; int fopt = 0; int aopt = 0; int dopt = 0; int rfd = -1, wfd = -1; Opt o; diod_log_init (argv[0]); o = opt_create (); opterr = 0; while ((c = GETOPT (argc, argv, OPTIONS, longopts)) != -1) { switch (c) { case 'f': /* --fake-mount */ fopt = 1; break; case 'n': /* --no-mtab */ nopt = 1; break; case 'v': /* --verbose */ vopt++; break; case 'o': /* --options OPT[,OPT]... */ opt_addf (o, "%s", optarg); break; case 'a': /* --9nbd-attach */ aopt++; break; case 'd': /* --9nbd-detach */ dopt++; break; default: usage (); } } /* Take care of 9nbd operations and exit. */ if (aopt) { _nbd_attach (o, argc - optind, argv + optind, nopt, vopt); exit (0); } if (dopt) { _nbd_detach (o, argc - optind, argv + optind, nopt, vopt); exit (0); } if (optind != argc - 2) usage (); if (geteuid () != 0) msg_exit ("you must be root"); spec = argv[optind++]; dir = argv[optind++]; host = _parse_spec (spec, o); _verify_mountpoint (dir); /* Remount - only pass mount flags into the VFS for an existing mount. * Take care of it here and exit. */ if (opt_find (o, "remount")) { if (opt_check_allowed_csv (o, "ro,rw,aname,remount")) msg_exit ("-oremount can only be used with ro,rw"); _diod_remount (o, spec, dir, vopt, fopt); goto done; } /* Ensure uname and access are set, and to diod-compatible values. * The uname user becomes the euid which will be used by munge auth. */ _parse_uname_access (o); if (seteuid (_uname2uid (opt_find (o, "uname"))) < 0) err_exit ("seteuid"); /* We require -otrans=fd because auth occurs in user space, then live fd * is passed to the kernel via -orfdno,wfdno. */ if (!opt_find (o, "trans")) opt_addf (o, "trans=%s", "fd"); else if (!opt_find (o, "trans=fd")) msg_exit ("only -otrans=fd transport is supported"); /* Set msize if not already set. Validate it later. */ if (!opt_find (o, "msize")) opt_addf (o, "msize=%d", DIOD_DEFAULT_MSIZE); /* Only .L version is supported. */ if (!opt_find (o, "version")) opt_addf (o, "version=%s", "9p2000.L"); else if (!opt_find (o, "version=9p2000.L")) msg_exit ("only -oversion=9p2000.L is supported (little p, big L)"); /* Set debug level. */ if (!opt_find (o, "debug")) opt_addf (o, "debug=%d", 0x1); /* send errors to dmesg */ /* Set rwdepth (number of concurrent reads with buffer > msize). * N.B. this option is not upstream yet but unknown options are ignored. */ if (!opt_find (o, "rwdepth")) opt_addf (o, "rwdepth=%d", 1); /* Server is on an inherited file descriptor. * For testing, we start server on a socketpair duped to fd 0. */ if (opt_find (o, "rfdno") || opt_find (o, "wfdno")) { if (!opt_scanf (o, "rfdno=%d", &rfd) || !opt_scanf (o, "wfdno=%d",&wfd)) msg_exit ("-orfdno,wfdno must be used together"); nopt = 1; /* force no mtab */ /* Connect to server on UNIX domain socket */ } else if (host[0] == '/') { if (opt_find (o, "port")) msg_exit ("-oport won't work with UNIX domain socket"); if ((rfd = diod_sock_connect_unix (host, 0)) < 0) exit (1); wfd = rfd; opt_addf (o, "rfdno=%d", rfd); opt_addf (o, "wfdno=%d", wfd); /* Connect to server on IANA port (or user-specified) and host. */ } else { char *port = opt_find (o, "port"); hostlist_iterator_t hi; hostlist_t hl; char *h; if (!port) port = "564"; if (!(hl = hostlist_create (host))) msg_exit ("error parsing host string: %s", host); if (!(hi = hostlist_iterator_create (hl))) msg_exit ("out of memory"); while ((h = hostlist_next (hi))) { if (vopt) msg ("trying to connect to %s:%s", h, port); if ((rfd = diod_sock_connect_inet (h, port, DIOD_SOCK_QUIET)) >= 0) break; } if (h) { /* create new 'spec' string identifying successful host */ char *p = strchr (spec , ':'); int len = strlen (h) + (p ? strlen (p) : 0) + 1; if (!(nspec = malloc (len))) msg_exit ("out of memory"); snprintf (nspec, len, "%s%s", h, p ? p : ""); } hostlist_destroy (hl); if (rfd < 0) msg_exit ("could not connect to server(s), giving up"); wfd = rfd; opt_delete (o, "port"); opt_addf (o, "rfdno=%d", rfd); opt_addf (o, "wfdno=%d", wfd); } NP_ASSERT (opt_find (o, "trans=fd")); NP_ASSERT (opt_scanf (o, "msize=%d", &i)); NP_ASSERT (opt_find (o, "version=9p2000.L")); NP_ASSERT (opt_scanf (o, "debug=%d", &i) || opt_scanf (o, "debug=%x", &i)); NP_ASSERT (opt_scanf (o, "wfdno=%d", &i) && opt_scanf (o, "rfdno=%d", &i)); NP_ASSERT ((opt_find (o, "access=user") && opt_find(o, "uname=root")) || (opt_scanf (o, "access=%d", &i) && opt_find(o, "uname"))); NP_ASSERT (!opt_find (o, "port")); _diod_mount (o, rfd, wfd, nspec ? nspec : spec, dir, vopt, fopt, nopt); done: opt_destroy (o); exit (0); }
// This test is expected to be executed either by a regular // user or by root. If executed by a regular user it doesn't // test all the functions that would depend on changing the // effective user id. If executed by a super-user everything // gets tested. Here are different ways of execing the test binary: // 1. regular user assuming user == yarn user // $ test-container-executor // 2. regular user with a given yarn user // $ test-container-executor yarn_user // 3. super user with a given user and assuming user == yarn user // # test-container-executor user // 4. super user with a given user and a given yarn user // # test-container-executor user yarn_user int main(int argc, char **argv) { LOGFILE = stdout; ERRORFILE = stderr; // clean up any junk from previous run if (system("chmod -R u=rwx " TEST_ROOT "; rm -fr " TEST_ROOT)) { exit(1); } if (mkdirs(TEST_ROOT "/logs/userlogs", 0755) != 0) { exit(1); } if (write_config_file(TEST_ROOT "/test.cfg", 1) != 0) { exit(1); } read_config(TEST_ROOT "/test.cfg"); local_dirs = extract_values(strdup(NM_LOCAL_DIRS)); log_dirs = extract_values(strdup(NM_LOG_DIRS)); create_nm_roots(local_dirs); // See the description above of various ways this test // can be executed in order to understand the following logic char* current_username = strdup(getpwuid(getuid())->pw_name); if (getuid() == 0 && (argc == 2 || argc == 3)) { username = argv[1]; yarn_username = (argc == 3) ? argv[2] : argv[1]; } else { username = current_username; yarn_username = (argc == 2) ? argv[1] : current_username; } set_nm_uid(geteuid(), getegid()); if (set_user(username)) { exit(1); } printf("\nStarting tests\n"); printf("\nTesting resolve_config_path()\n"); test_resolve_config_path(); printf("\nTesting get_user_directory()\n"); test_get_user_directory(); printf("\nTesting get_app_directory()\n"); test_get_app_directory(); printf("\nTesting get_container_directory()\n"); test_get_container_directory(); printf("\nTesting get_container_launcher_file()\n"); test_get_container_launcher_file(); printf("\nTesting get_app_log_dir()\n"); test_get_app_log_dir(); test_check_configuration_permissions(); printf("\nTesting delete_container()\n"); test_delete_container(); printf("\nTesting delete_app()\n"); test_delete_app(); test_check_user(); // the tests that change user need to be run in a subshell, so that // when they change user they don't give up our privs run_test_in_child("test_signal_container_group", test_signal_container_group); // init app and run container can't be run if you aren't testing as root if (getuid() == 0) { // these tests do internal forks so that the change_owner and execs // don't mess up our process. test_init_app(); test_run_container(); } seteuid(0); // test_delete_user must run as root since that's how we use the delete_as_user test_delete_user(); free_configurations(); printf("\nTrying banned default user()\n"); if (write_config_file(TEST_ROOT "/test.cfg", 0) != 0) { exit(1); } read_config(TEST_ROOT "/test.cfg"); username = "******"; test_check_user(); run("rm -fr " TEST_ROOT); printf("\nFinished tests\n"); free(current_username); free_configurations(); return 0; }
/** * Main function of "gnunet-helper-dns", which opens a VPN tunnel interface, * redirects all outgoing DNS traffic (except from the specified port) to that * interface and then passes traffic from and to the interface via stdin/stdout. * * Once stdin/stdout close or have other errors, the tunnel is closed and the * DNS traffic redirection is stopped. * * @param argc number of arguments * @param argv 0: binary name (should be "gnunet-helper-vpn") * 1: tunnel interface name (typically "gnunet-dns") * 2: IPv6 address for the tunnel ("FE80::1") * 3: IPv6 netmask length in bits ("64") * 4: IPv4 address for the tunnel ("1.2.3.4") * 5: IPv4 netmask ("255.255.0.0") * @return 0 on success, otherwise code indicating type of error: * 1 wrong number of arguments * 2 invalid arguments (i.e. port number / prefix length wrong) * 3 iptables not executable * 4 ip not executable * 5 failed to initialize tunnel interface * 6 failed to initialize control pipe * 8 failed to change routing table, cleanup successful * 9-23 failed to change routing table and failed to undo some changes to routing table * 24 failed to drop privs * 25-39 failed to drop privs and then failed to undo some changes to routing table * 40 failed to regain privs * 41-55 failed to regain prisv and then failed to undo some changes to routing table * 254 insufficient priviledges * 255 failed to handle kill signal properly */ int main (int argc, char *const*argv) { int r; char dev[IFNAMSIZ]; char mygid[32]; int fd_tun; uid_t uid; if (6 != argc) { fprintf (stderr, "Fatal: must supply 6 arguments!\n"); return 1; } /* assert privs so we can modify the firewall rules! */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno)); return 254; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); return 254; } #endif /* verify that the binaries were care about are executable */ if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Fatal: executable iptables not found in approved directories: %s\n", strerror (errno)); return 3; } if (0 == access ("/sbin/ip", X_OK)) sbin_ip = "/sbin/ip"; else if (0 == access ("/usr/sbin/ip", X_OK)) sbin_ip = "/usr/sbin/ip"; else { fprintf (stderr, "Fatal: executable ip not found in approved directories: %s\n", strerror (errno)); return 4; } if (0 == access ("/sbin/sysctl", X_OK)) sbin_sysctl = "/sbin/sysctl"; else if (0 == access ("/usr/sbin/sysctl", X_OK)) sbin_sysctl = "/usr/sbin/sysctl"; else { fprintf (stderr, "Fatal: executable sysctl not found in approved directories: %s\n", strerror (errno)); return 5; } /* setup 'mygid' string */ snprintf (mygid, sizeof (mygid), "%d", (int) getegid()); /* do not die on SIGPIPE */ if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) { fprintf (stderr, "Failed to protect against SIGPIPE: %s\n", strerror (errno)); return 7; } /* setup pipe to shutdown nicely on SIGINT */ if (0 != pipe (cpipe)) { fprintf (stderr, "Fatal: could not setup control pipe: %s\n", strerror (errno)); return 6; } if (cpipe[0] >= FD_SETSIZE) { fprintf (stderr, "Pipe file descriptor to large: %d", cpipe[0]); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } { /* make pipe non-blocking, as we theoretically could otherwise block in the signal handler */ int flags = fcntl (cpipe[1], F_GETFL); if (-1 == flags) { fprintf (stderr, "Failed to read flags for pipe: %s", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } flags |= O_NONBLOCK; if (0 != fcntl (cpipe[1], F_SETFL, flags)) { fprintf (stderr, "Failed to make pipe non-blocking: %s", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } } if ( (SIG_ERR == signal (SIGTERM, &signal_handler)) || (SIG_ERR == signal (SIGINT, &signal_handler)) || (SIG_ERR == signal (SIGHUP, &signal_handler)) ) { fprintf (stderr, "Fatal: could not initialize signal handler: %s\n", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 7; } /* get interface name */ strncpy (dev, argv[1], IFNAMSIZ); dev[IFNAMSIZ - 1] = '\0'; /* Disable rp filtering */ { char *const sysctl_args[] = {"sysctl", "-w", "net.ipv4.conf.all.rp_filter=0", NULL }; char *const sysctl_args2[] = {"sysctl", "-w", "net.ipv4.conf.default.rp_filter=0", NULL }; if ((0 != fork_and_exec (sbin_sysctl, sysctl_args)) || (0 != fork_and_exec (sbin_sysctl, sysctl_args2))) { fprintf (stderr, "Failed to disable rp filtering.\n"); return 5; } } /* now open virtual interface (first part that requires root) */ if (-1 == (fd_tun = init_tun (dev))) { fprintf (stderr, "Fatal: could not initialize tun-interface\n"); (void) signal (SIGTERM, SIG_IGN); (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return 5; } /* now set interface addresses */ { const char *address = argv[2]; long prefix_len = atol (argv[3]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "Fatal: prefix_len out of range\n"); (void) signal (SIGTERM, SIG_IGN); (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return 2; } set_address6 (dev, address, prefix_len); } { const char *address = argv[4]; const char *mask = argv[5]; set_address4 (dev, address, mask); } /* update routing tables -- next part why we need SUID! */ /* Forward everything from our EGID (which should only be held by the 'gnunet-service-dns') and with destination to port 53 on UDP, without hijacking */ r = 8; /* failed to fully setup routing table */ { char *const mangle_args[] = { "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_iptables, mangle_args)) goto cleanup_rest; } /* Mark all of the other DNS traffic using our mark DNS_MARK */ { char *const mark_args[] = { "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p", "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_iptables, mark_args)) goto cleanup_mangle_1; } /* Forward all marked DNS traffic to our DNS_TABLE */ { char *const forward_args[] = { "ip", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_args)) goto cleanup_mark_2; } /* Finally, add rule in our forwarding table to pass to our virtual interface */ { char *const route_args[] = { "ip", "route", "add", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_args)) goto cleanup_forward_3; } /* drop privs *except* for the saved UID; this is not perfect, but better than doing nothing */ #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, 0)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); r = 24; goto cleanup_route_4; } #else /* Note: no 'setuid' here as we must keep our saved UID as root */ if (0 != seteuid (uid)) { fprintf (stderr, "Failed to seteuid: %s\n", strerror (errno)); r = 24; goto cleanup_route_4; } #endif r = 0; /* did fully setup routing table (if nothing else happens, we were successful!) */ /* now forward until we hit a problem */ run (fd_tun); /* now need to regain privs so we can remove the firewall rules we added! */ #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid back to root: %s\n", strerror (errno)); r = 40; goto cleanup_route_4; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); r = 40; goto cleanup_route_4; } #endif /* update routing tables again -- this is why we could not fully drop privs */ /* now undo updating of routing tables; normal exit or clean-up-on-error case */ cleanup_route_4: { char *const route_clean_args[] = { "ip", "route", "del", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_clean_args)) r += 1; } cleanup_forward_3: { char *const forward_clean_args[] = { "ip", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_clean_args)) r += 2; } cleanup_mark_2: { char *const mark_clean_args[] = { "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_iptables, mark_clean_args)) r += 4; } cleanup_mangle_1: { char *const mangle_clean_args[] = { "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_iptables, mangle_clean_args)) r += 8; } cleanup_rest: /* close virtual interface */ (void) close (fd_tun); /* remove signal handler so we can close the pipes */ (void) signal (SIGTERM, SIG_IGN); (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return r; }
void create() { seteuid(geteuid()); restore(); }
int main() { struct flock fl; uid_t uid; FILE *pid_file; uid = geteuid(); if (uid != 0) { fprintf(stderr, "Sorry, root is required\n"); return -1; } pid_file_fd = open("/var/run/" DAEMON_NAME, O_CREAT | O_WRONLY, 0644); if (pid_file_fd == -1) { perror("open error"); return -1; } if (flock(pid_file_fd, LOCK_EX | LOCK_NB) == -1) { perror("block failed"); return -1; } openlog(DAEMON_NAME, LOG_CONS, LOG_DAEMON); struct passwd *pass = getpwnam(DAEMON_USERNAME); if (pass == NULL) { fprintf(stderr, "No such user: %s\n", DAEMON_USERNAME); return -1; } uid = pass->pw_uid; seteuid(uid); if (setpgrp() == -1) { perror("changing gid error"); return -1; } pid = fork(); if (pid != 0) /* parent process: we should exit */ { return 0; } /* now we are in child(daemon) process */ if (setsid() == -1) /* creating new session so daemon isn't killed by stopping initial terminal process */ { perror("creating session error"); return -1; } pid = getpid(); pid_file = fdopen(pid_file_fd, "w"); if (pid_file == NULL) { syslog(LOG_ERR, "Could manage to open fd [%d]\n", pid_file_fd); return -1; } fprintf(pid_file, "%ld", (long)pid); fflush(pid_file); /* closing standart fd */ close(0); close(1); close(2); /* now main code part starts */ key = ftok(SHMEMPATH, SHMEMKEY); shmid = shmget(key, sizeof(mem_t), IPC_CREAT | 0644); if (shmid == -1) { perror("shared memory id get error"); return 1; } semid = semget(key, NUMSEMS, IPC_CREAT | 0644); if (semid == -1) { printf("semaphors id get failed\n"); return 1; } data = (mem_t*)shmat(shmid, NULL, 0); if (data == NULL) { printf("shmat failed\n"); return 2; } while (1) { semop(semid, wait_client, 1); syslog(LOG_NOTICE, "%s", data->str); semop(semid, calculated, 1); } return 0; }
void create() { seteuid(ROOT_UID); }
static int drop_root(void) { struct passwd *pw; struct group * gr; int r; //Edison modify username 20131023 char dut_user[128]; memset(dut_user, 0, 128); strncpy(dut_user, nvram_safe_get("http_username"), 128); if (!(pw = getpwnam(dut_user))) { avahi_log_error( "Failed to find user '%s'.",dut_user); return -1; } if (!(gr = getgrnam(AVAHI_GROUP))) { avahi_log_error( "Failed to find group '"AVAHI_GROUP"'."); return -1; } avahi_log_info("Found user '%s' (UID %lu) and group '"AVAHI_GROUP"' (GID %lu).",dut_user ,(unsigned long) pw->pw_uid, (unsigned long) gr->gr_gid); if (initgroups(dut_user, gr->gr_gid) != 0) { avahi_log_error("Failed to change group list: %s", strerror(errno)); return -1; } #if defined(HAVE_SETRESGID) r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid); #elif defined(HAVE_SETEGID) if ((r = setgid(gr->gr_gid)) >= 0) r = setegid(gr->gr_gid); #elif defined(HAVE_SETREGID) r = setregid(gr->gr_gid, gr->gr_gid); #else #error "No API to drop privileges" #endif if (r < 0) { avahi_log_error("Failed to change GID: %s", strerror(errno)); return -1; } #if defined(HAVE_SETRESUID) r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); #elif defined(HAVE_SETEUID) if ((r = setuid(pw->pw_uid)) >= 0) r = seteuid(pw->pw_uid); #elif defined(HAVE_SETREUID) r = setreuid(pw->pw_uid, pw->pw_uid); #else #error "No API to drop privileges" #endif if (r < 0) { avahi_log_error("Failed to change UID: %s", strerror(errno)); return -1; } set_env("USER", pw->pw_name); set_env("LOGNAME", pw->pw_name); set_env("HOME", pw->pw_dir); avahi_log_info("Successfully dropped root privileges."); return 0; }
void create() { seteuid(getuid()); set("enchantment", FAINT); set("schools", ({ "alteration", "evocation" }) );
void test_run_container() { printf("\nTesting run container\n"); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } FILE* creds = fopen(TEST_ROOT "/creds.txt", "w"); if (creds == NULL) { printf("FAIL: failed to create credentials file - %s\n", strerror(errno)); exit(1); } if (fprintf(creds, "secret key\n") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(creds) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } const char* script_name = TEST_ROOT "/container-script"; FILE* script = fopen(script_name, "w"); if (script == NULL) { printf("FAIL: failed to create script file - %s\n", strerror(errno)); exit(1); } if (seteuid(user_detail->pw_uid) != 0) { printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno)); exit(1); } if (fprintf(script, "#!/bin/bash\n" "touch foobar\n" "exit 0") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(script) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } fflush(stdout); fflush(stderr); char* container_dir = get_container_work_directory(TEST_ROOT "/local-1", username, "app_4", "container_1"); const char * pid_file = TEST_ROOT "/pid.txt"; pid_t child = fork(); if (child == -1) { printf("FAIL: failed to fork process for init_app - %s\n", strerror(errno)); exit(1); } else if (child == 0) { if (launch_container_as_user(username, "app_4", "container_1", container_dir, script_name, TEST_ROOT "/creds.txt", pid_file, extract_values(local_dirs), extract_values(log_dirs)) != 0) { printf("FAIL: failed in child\n"); exit(42); } // should never return exit(1); } int status = 0; if (waitpid(child, &status, 0) <= 0) { printf("FAIL: failed waiting for process %d - %s\n", child, strerror(errno)); exit(1); } if (access(TEST_ROOT "/logs/userlogs/app_4/container_1", R_OK) != 0) { printf("FAIL: failed to create container log directory\n"); exit(1); } if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create container directory %s\n", container_dir); exit(1); } char buffer[100000]; sprintf(buffer, "%s/foobar", container_dir); if (access(buffer, R_OK) != 0) { printf("FAIL: failed to create touch file %s\n", buffer); exit(1); } free(container_dir); container_dir = get_app_log_directory("logs", "app_4/container_1"); if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create app log directory %s\n", container_dir); exit(1); } free(container_dir); if(access(pid_file, R_OK) != 0) { printf("FAIL: failed to create pid file %s\n", pid_file); exit(1); } int pidfd = open(pid_file, O_RDONLY); if (pidfd == -1) { printf("FAIL: failed to open pid file %s - %s\n", pid_file, strerror(errno)); exit(1); } char pidBuf[100]; ssize_t bytes = read(pidfd, pidBuf, 100); if (bytes == -1) { printf("FAIL: failed to read from pid file %s - %s\n", pid_file, strerror(errno)); exit(1); } pid_t mypid = child; char myPidBuf[33]; snprintf(myPidBuf, 33, "%d", mypid); if (strncmp(pidBuf, myPidBuf, strlen(myPidBuf)) != 0) { printf("FAIL: failed to find matching pid in pid file\n"); printf("FAIL: Expected pid %d : Got %.*s", mypid, (int)bytes, pidBuf); exit(1); } }
/* * Check the file mode in file and directory */ static void test_premission01(void ) { mode_t tmp_mode; struct stat statbuf; int status = 0; int fd; char* file01="file01"; char* file02="file02"; char* directory01="dir01"; char path[20]; char* test_data="Test Data"; char* data_buf; size_t len=strlen(test_data); int n; DIR *dp; const char* wd=__func__; mode_t mode=S_IRWXU|S_IRWXG|S_IRWXO ; uid_t user_id =65534; gid_t group_id =65534; uid_t another_user_id =65533; gid_t another_group_id =65533; /* *Create a new directory and change the current directory to this */ umask(00); status=mkdir(wd,mode); rtems_test_assert(status==0); status=chdir(wd); rtems_test_assert(status==0); status=seteuid(user_id); rtems_test_assert(status==0); status=setegid(group_id); rtems_test_assert(status==0); /* *Create a file with mode 0777 */ fd=creat(file01,mode); status=close(fd); rtems_test_assert(status==0); /* *Create a file with mode 0240 */ fd=creat(file02,0240); status=close(fd); rtems_test_assert(status==0); /* *Check the file mode uid and gid */ status = stat (file01, &statbuf); rtems_test_assert (status == 0); tmp_mode = (statbuf.st_mode) & ALLPERMS; printf("The file mode of %s is %03o\n",file01,(unsigned int)tmp_mode); rtems_test_assert(tmp_mode==mode); rtems_test_assert(statbuf.st_uid==user_id); rtems_test_assert(statbuf.st_gid==group_id); status = stat (file02, &statbuf); rtems_test_assert (status == 0); tmp_mode = (statbuf.st_mode) & ALLPERMS; printf("The file mode of %s is %03o\n",file02,(unsigned int)tmp_mode); rtems_test_assert(tmp_mode==0240); rtems_test_assert(statbuf.st_uid==user_id); rtems_test_assert(statbuf.st_gid==group_id); /* * Create directory and a file in it for tese */ status=mkdir(directory01,0777); rtems_test_assert(status==0); sprintf(path,"%s/%s",directory01,file01); fd=creat(path,0777); status=chmod(directory01,0340); rtems_test_assert (status == 0); status = stat (directory01, &statbuf); rtems_test_assert (status == 0); tmp_mode = (statbuf.st_mode) & ALLPERMS; printf("The file mode of %s is %03o\n",directory01,(unsigned int)tmp_mode); rtems_test_assert(tmp_mode==0340); rtems_test_assert(statbuf.st_uid==user_id); rtems_test_assert(statbuf.st_gid==group_id); /* * Check the file with open and write */ /* * Test write */ fd=open(file01,O_WRONLY); n=write(fd,test_data,len); rtems_test_assert(n==len); status=close(fd); rtems_test_assert(status==0); fd=open(file02,O_WRONLY); n=write(fd,test_data,len); rtems_test_assert(n==len); status=close(fd); rtems_test_assert(status==0); /* * Test read */ data_buf=(char*)malloc(len+1); fd=open(file01,O_RDWR); rtems_test_assert(fd!=-1); n=read(fd,data_buf,len); rtems_test_assert(n==len); status=close(fd); rtems_test_assert(status==0); EXPECT_ERROR(EACCES,open,file02,O_RDONLY); EXPECT_ERROR(EACCES,open,file02,O_RDWR); /* * Test read directory */ dp= opendir(directory01); rtems_test_assert(dp==NULL); rtems_test_assert(errno==EACCES); /* * Test write directory */ status = lstat (path, &statbuf); rtems_test_assert (status == 0); status=unlink(path); rtems_test_assert(status==0); /* * Change euid and check */ puts("Change euid and check"); status=seteuid(0); rtems_test_assert(status==0); status=seteuid(another_user_id); rtems_test_assert(status==0); fd=open(file01,O_WRONLY); n=write(fd,test_data,len); rtems_test_assert(n==len); status=close(fd); rtems_test_assert(status==0); EXPECT_ERROR(EACCES,open,file02,O_WRONLY); EXPECT_ERROR(EACCES,open,file02,O_RDWR); /* * Test read directory */ dp= opendir(directory01); rtems_test_assert(dp!=NULL); status=closedir(dp); rtems_test_assert(status==0); /* * Test write directory */ EXPECT_ERROR(EACCES,creat,path,mode); EXPECT_ERROR(EACCES,rename,path,"test"); EXPECT_ERROR(EACCES,truncate,path,0); EXPECT_ERROR(EACCES,link,path,"test"); EXPECT_ERROR(EACCES,unlink,path); /* * Change egid and check */ puts("Change egid and check"); status=seteuid(0); rtems_test_assert(status==0); status=setegid(another_group_id); rtems_test_assert(status==0); status=seteuid(another_user_id); rtems_test_assert(status==0); EXPECT_ERROR(EACCES,open,file02,O_WRONLY); EXPECT_ERROR(EACCES,open,file02,O_RDONLY); EXPECT_ERROR(EACCES,open,file02,O_RDWR); /* * Test read directory */ dp= opendir(directory01); rtems_test_assert(dp==NULL); rtems_test_assert(errno==EACCES); /* * Test write directory */ EXPECT_ERROR(EACCES,creat,path,mode); /* * Go back to parent directory */ status=seteuid(0); rtems_test_assert(status==0); status=setegid(0); rtems_test_assert(status==0); free(data_buf); status=chdir(".."); rtems_test_assert(status==0); }
int32_t SystemNative_SetEUid(uid_t euid) { return seteuid(euid); }
/****************************************************************************** * * * Function: daemon_start * * * * Purpose: init process as daemon * * * * Parameters: allow_root - allow root permission for application * * * * Author: Alexei Vladishev * * * * Comments: it doesn't allow running under 'root' if allow_root is zero * * * ******************************************************************************/ int daemon_start(int allow_root) { pid_t pid; struct passwd *pwd; struct sigaction phan; char user[7] = "zabbix"; /* running as root ? */ if (0 == allow_root && (0 == getuid() || 0 == getgid())) { pwd = getpwnam(user); if (NULL == pwd) { zbx_error("user %s does not exist", user); zbx_error("Cannot run as root!"); exit(FAIL); } if (-1 == setgid(pwd->pw_gid)) { zbx_error("cannot setgid to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #ifdef HAVE_FUNCTION_INITGROUPS if (-1 == initgroups(user, pwd->pw_gid)) { zbx_error("cannot initgroups to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #endif if (-1 == setuid(pwd->pw_uid)) { zbx_error("cannot setuid to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #ifdef HAVE_FUNCTION_SETEUID if (-1 == setegid(pwd->pw_gid) || -1 == seteuid(pwd->pw_uid)) { zbx_error("cannot setegid or seteuid to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #endif } if (0 != (pid = zbx_fork())) exit(0); setsid(); signal(SIGHUP, SIG_IGN); if (0 != (pid = zbx_fork())) exit(0); /* this is to eliminate warning: ignoring return value of chdir */ if (-1 == chdir("/")) assert(0); umask(0002); redirect_std(CONFIG_LOG_FILE); #ifdef HAVE_SYS_RESOURCE_SETPRIORITY if (0 != setpriority(PRIO_PROCESS, 0, 5)) zbx_error("Unable to set process priority to 5. Leaving default."); #endif /*------------------------------------------------*/ if (FAIL == create_pid_file(CONFIG_PID_FILE)) exit(FAIL); parent_pid = (int)getpid(); phan.sa_sigaction = child_signal_handler; sigemptyset(&phan.sa_mask); phan.sa_flags = SA_SIGINFO; sigaction(SIGINT, &phan, NULL); sigaction(SIGQUIT, &phan, NULL); sigaction(SIGTERM, &phan, NULL); sigaction(SIGPIPE, &phan, NULL); sigaction(SIGILL, &phan, NULL); sigaction(SIGFPE, &phan, NULL); sigaction(SIGSEGV, &phan, NULL); sigaction(SIGBUS, &phan, NULL); sigaction(SIGALRM, &phan, NULL); sigaction(SIGUSR1, &phan, NULL); /* Set SIGCHLD now to avoid race conditions when a child process is created before */ /* sigaction() is called. To avoid problems when scripts exit in zbx_execute() and */ /* other cases, SIGCHLD is set to SIG_IGN in zbx_child_fork(). */ phan.sa_sigaction = parent_signal_handler; sigaction(SIGCHLD, &phan, NULL); zbx_setproctitle("main process"); return MAIN_ZABBIX_ENTRY(); }
bool f_posix_seteuid(int uid) { return seteuid(uid); }
int main(int ac, char **av) { int lc, i; /* loop counter */ char *msg; /* message returned from parse_opts */ /* parse standard options */ if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL) { tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); } TST_TOTAL = sizeof(testcase) / sizeof(testcase[0]); /* perform global setup for test */ setup(); /* check looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { /* reset Tst_count in case we are looping. */ Tst_count = 0; for (i = 0; i < TST_TOTAL; i++) { if (setup_test(i) < 0) { continue; } TEST(clock_settime(clocks[i], temp)); if (TEST_ERRNO == ENOSYS) { /* System call not implemented */ Tst_count = TST_TOTAL; perror("clock_settime"); tst_brkm(TBROK, cleanup, ""); } /* Change the UID back to root */ if (i == TST_TOTAL - 1) { if (seteuid(0) == -1) { perror("seteuid"); tst_brkm(TBROK, tst_exit, "Failed to" " set the effective" " uid to root"); } } /* check return code */ if ((TEST_RETURN == -1) && (TEST_ERRNO == testcase[i]. exp_errno)) { tst_resm(TPASS, "clock_settime(2) expected" " failure; Got errno - %s : %s" , testcase[i].exp_errval, testcase[i].err_desc); } else { tst_resm(TFAIL, "clock_settime(2) failed to" " produce expected error; %d" " , errno : %s and got %d", testcase[i].exp_errno, testcase[i].exp_errval, TEST_RETURN); if (TEST_RETURN == 0) { if (clock_settime(CLOCK_REALTIME, &saved) < 0) { tst_resm(TWARN, "FATAL, COULD" " NOT SET THE" " CLOCK"); } } } /* end of else */ TEST_ERROR_LOG(TEST_ERRNO); } /* End of TEST CASE LOOPING */ } /* End for TEST_LOOPING */ /* Clean up and exit */ cleanup(); /* NOTREACHED */ return 0; }
int main(int ac, char **av) { int lc; /* loop counter */ char *msg; /* message returned from parse_opts */ char *file_name; /* testfile name */ char *test_desc; /* test specific error message */ int ind; /* counter to test different test conditions */ int pid; /* Parse standard options given to run the test. */ msg = parse_opts(ac, av, (option_t *) NULL, NULL); if (msg != (char *) NULL) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); tst_exit(); } /* Perform global setup for test */ setup(); /* set the expected errnos... */ TEST_EXP_ENOS(exp_enos); pid = FORK_OR_VFORK(); if (pid == -1) { tst_brkm(TBROK, cleanup, "fork() failed"); /*NOTREACHED*/ } else if (pid == 0) { if ((ltpuser = getpwnam(LTPUSER1)) == NULL) { tst_brkm(TBROK,cleanup,"%s not found in /etc/passwd", LTPUSER1); /*NOTREACHED*/ } /* get uid of user */ user_uid = ltpuser->pw_uid; seteuid(user_uid); /* Check looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { /* Reset Tst_count in case we are looping. */ Tst_count=0; for (ind = 0; Test_cases[ind].desc != NULL; ind++) { file_name = Test_cases[ind].pathname; test_desc = Test_cases[ind].desc; /* * Call utime(2) to test different test * conditions. Verify that it fails with -1 * return value and sets appropriate errno. */ TEST(utime(file_name, NULL)); /* Check return code from utime(2) */ if (TEST_RETURN == -1) { TEST_ERROR_LOG(TEST_ERRNO); if (TEST_ERRNO == Test_cases[ind].exp_errno) { tst_resm(TPASS, "utime() " "fails, %s, errno:%d", test_desc, TEST_ERRNO); } else { tst_resm(TFAIL, "utime(2) " "fails, %s, errno:%d, " "expected errno:%d", test_desc, TEST_ERRNO, Test_cases[ind].exp_errno); } } else { tst_resm(TFAIL, "utime(2) returned %d, " "expected -1, errno:%d", TEST_RETURN, Test_cases[ind].exp_errno); } } /* End of TEST CASE LOOPING. */ Tst_count++; /* incr TEST_LOOP counter */ } /* End for TEST_LOOPING */ } else { waitpid(pid, &status, 0); _exit(0); /* * Exit here and let the child clean up. * This allows the errno information set * by the TEST_ERROR_LOG macro and the * PASS/FAIL status to be preserved for * use during cleanup. */ } /* Call cleanup() to undo setup done for the test. */ cleanup(); /*NOTREACHED*/ return(0); } /* End main */
/** * \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; }