Пример #1
0
/*
 * 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);
	}
}
Пример #2
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;
}
Пример #3
0
void create() { seteuid(getuid()); }
Пример #4
0
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);
}
Пример #5
0
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;
}
Пример #6
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 */
}
Пример #7
0
void create()
{
       seteuid(getuid());
       set_name(HIW"巫师工作服"NOR,({"wizard suit","suit" }));
Пример #8
0
/**
 * 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);
}
Пример #10
0
/*
	_sn		编号
	_ts		时间
	qu		问题
	an		答案
	wei		权重
	aid		作者id
*/
void create()
{
	::create();
	seteuid(getuid());
}
Пример #11
0
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;
}
Пример #12
0
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);
        }
Пример #13
0
void create()
{
	seteuid(getuid());
        set_name("采石工",({"worker"}));
Пример #14
0
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
}
Пример #15
0
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;
}
Пример #17
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;
}
Пример #18
0
void create()
{
	seteuid(geteuid());
	restore();
}
Пример #19
0
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;
}
Пример #20
0
void create() { seteuid(ROOT_UID); } 
Пример #21
0
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;
}
Пример #22
0
void create() {
    seteuid(getuid());
    set("enchantment", FAINT);
    set("schools", ({ "alteration", "evocation" }) );
Пример #23
0
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);
  }
}
Пример #24
0
/*
 * 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);
}
Пример #25
0
int32_t SystemNative_SetEUid(uid_t euid)
{
    return seteuid(euid);
}
Пример #26
0
/******************************************************************************
 *                                                                            *
 * 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();
}
Пример #27
0
bool f_posix_seteuid(int uid) {
  return seteuid(uid);
}
Пример #28
0
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;
}
Пример #29
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 */
Пример #30
0
/**
 * \param[in] rUser user name
 * \return true = success, false = failure
 * 
 * \attention This function is very complex and may contain
 *            various bugs including security ones. Please keep
 *            it in mind..
 */
bool edit_table(const std::string& rUser)
{
  std::string tp(IncronTab::GetUserTablePath(rUser));
  
  struct passwd* ppwd = getpwnam(rUser.c_str());
  if (ppwd == NULL) {
    fprintf(stderr, "cannot find user '%s': %s\n", rUser.c_str(), strerror(errno));
    return false;
  }
  
  uid_t uid = ppwd->pw_uid;
  uid_t gid = ppwd->pw_gid;
  
  char s[NAME_MAX];
  strcpy(s, "/tmp/incron.table-XXXXXX");
  
  uid_t iu = geteuid();
  uid_t ig = getegid();

  if (setegid(gid) != 0 || seteuid(uid) != 0) {
    fprintf(stderr, "cannot change effective UID/GID for user '%s': %s\n", rUser.c_str(), strerror(errno));
    return false;
  }
  
  int fd = mkstemp(s);
  if (fd == -1) {
    fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno));
    return false;
  }
  
  bool ok = false;
  FILE* out = NULL;
  FILE* in = NULL;
  time_t mt = (time_t) 0;
  const char* e = NULL;
  std::string ed;
  
  if (setegid(ig) != 0 || seteuid(iu) != 0) {
    fprintf(stderr, "cannot change effective UID/GID: %s\n", strerror(errno));
    close(fd);
    goto end;
  }
    
  out = fdopen(fd, "w");
  if (out == NULL) {
    fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno));
    close(fd);
    goto end;
  }
  
  in = fopen(tp.c_str(), "r");
  if (in == NULL) {
    if (errno == ENOENT) {
      in = fopen("/dev/null", "r");
      if (in == NULL) {
        fprintf(stderr, "cannot get empty table for '%s': %s\n", rUser.c_str(), strerror(errno));
        fclose(out);
        goto end;
      }
    }
    else {
      fprintf(stderr, "cannot read old table for '%s': %s\n", rUser.c_str(), strerror(errno));
      fclose(out);
      goto end;
    }
  }
  
  char buf[1024];
  while (fgets(buf, 1024, in) != NULL) {
    fputs(buf, out);
  }
  fclose(in);
  fclose(out);
  
  struct stat st;
  if (stat(s, &st) != 0) {
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
    goto end;
  }
  
  mt = st.st_mtime; // save modification time for detecting its change
  
  // Editor selecting algorithm:
  // 1. Check EDITOR environment variable
  // 2. Check VISUAL environment variable
  // 3. Try to get from configuration
  // 4. Check presence of /etc/alternatives/editor
  // 5. Use hard-wired editor
  
  e = getenv("EDITOR");
  if (e == NULL) {
    e = getenv("VISUAL");
    if (e == NULL) {
      
      if (!IncronCfg::GetValue("editor", ed))
        throw InotifyException("configuration is corrupted", EINVAL);
      
      if (!ed.empty()) {
        e = ed.c_str();
      }
      else {
        if (access(INCRON_ALT_EDITOR, X_OK) == 0)
          e = INCRON_ALT_EDITOR;
        else
          e = INCRON_DEFAULT_EDITOR;
      }
    }
  }
  
  // this block is explicite due to gotos' usage simplification
  {
    pid_t pid = fork();
    if (pid == 0) {
      if (setgid(gid) != 0 || setuid(uid) != 0) {
        fprintf(stderr, "cannot set user '%s': %s\n", rUser.c_str(), strerror(errno));
        goto end;
      }    
      
      execlp(e, e, s, (const char*) NULL);
      _exit(1);
    }
    else if (pid > 0) {
      int status;
      if (wait(&status) != pid) {
        perror("error while waiting for editor");
        goto end;
      }
      if (!(WIFEXITED(status)) || WEXITSTATUS(status) != 0) {
        perror("editor finished with error");
        goto end;
      }
    }
    else {
      perror("cannot start editor");
      goto end;
    }
  }
  
  if (stat(s, &st) != 0) {
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
    goto end;
  }
  
  if (st.st_mtime == mt) {
    fprintf(stderr, "table unchanged\n");
    ok = true;
    goto end;
  }
  
  {
    IncronTab ict;
    if (ict.Load(s) && ict.Save(tp)) {
      if (chmod(tp.c_str(), S_IRUSR | S_IWUSR) != 0) {
        fprintf(stderr, "cannot change mode of temporary file: %s\n", strerror(errno));
      }
    }
    else {
      fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno));
      goto end;
    }
    
  }
  
  ok = true;
  fprintf(stderr, "table updated\n");
  
end:  
  
  unlink(s);
  return ok;
}