Esempio n. 1
0
int
main(int argc, char **argv)
{
	struct group *gr;
	struct stat st;
	int retries, backoff;
	int ask, ch, cnt, quietlog, rootlogin, rval;
	uid_t uid, euid;
	gid_t egid;
	char *term;
	char *p, *ttyn;
	char tname[sizeof(_PATH_TTY) + 10];
	char *arg0;
	const char *tp;
	const char *shell = NULL;
	login_cap_t *lc = NULL;
	login_cap_t *lc_user = NULL;
	pid_t pid;
#ifdef USE_BSM_AUDIT
	char auditsuccess = 1;
#endif

	signal(SIGQUIT, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	if (setjmp(timeout_buf)) {
		if (failures)
			badlogin(username);
		fprintf(stderr, "Login timed out after %d seconds\n",
		    timeout);
		bail(NO_SLEEP_EXIT, 0);
	}
	signal(SIGALRM, timedout);
	alarm(timeout);
	setpriority(PRIO_PROCESS, 0, 0);

	openlog("login", LOG_ODELAY, LOG_AUTH);

	uid = getuid();
	euid = geteuid();
	egid = getegid();

	while ((ch = getopt(argc, argv, "fh:p")) != -1)
		switch (ch) {
		case 'f':
			fflag = 1;
			break;
		case 'h':
			if (uid != 0)
				errx(1, "-h option: %s", strerror(EPERM));
			if (strlen(optarg) >= MAXHOSTNAMELEN)
				errx(1, "-h option: %s: exceeds maximum "
				    "hostname size", optarg);
			hflag = 1;
			hostname = optarg;
			break;
		case 'p':
			pflag = 1;
			break;
		case '?':
		default:
			if (uid == 0)
				syslog(LOG_ERR, "invalid flag %c", ch);
			usage();
		}
	argc -= optind;
	argv += optind;

	if (argc > 0) {
		username = strdup(*argv);
		if (username == NULL)
			err(1, "strdup()");
		ask = 0;
	} else {
		ask = 1;
	}

	setproctitle("-%s", getprogname());

	for (cnt = getdtablesize(); cnt > 2; cnt--)
		close(cnt);

	/*
	 * Get current TTY
	 */
	ttyn = ttyname(STDIN_FILENO);
	if (ttyn == NULL || *ttyn == '\0') {
		snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
		ttyn = tname;
	}
	if (strncmp(ttyn, _PATH_DEV, sizeof(_PATH_DEV) -1) == 0)
		tty = ttyn + sizeof(_PATH_DEV) -1;
	else
		tty = ttyn;

	/*
	 * Get "login-retries" & "login-backoff" from default class
	 */
	lc = login_getclass(NULL);
	prompt = login_getcapstr(lc, "login_prompt",
	    default_prompt, default_prompt);
	passwd_prompt = login_getcapstr(lc, "passwd_prompt",
	    default_passwd_prompt, default_passwd_prompt);
	retries = login_getcapnum(lc, "login-retries",
	    DEFAULT_RETRIES, DEFAULT_RETRIES);
	backoff = login_getcapnum(lc, "login-backoff",
	    DEFAULT_BACKOFF, DEFAULT_BACKOFF);
	login_close(lc);
	lc = NULL;

	/*
	 * Try to authenticate the user until we succeed or time out.
	 */
	for (cnt = 0;; ask = 1) {
		if (ask) {
			fflag = 0;
			if (olduser != NULL)
				free(olduser);
			olduser = username;
			username = getloginname();
		}
		rootlogin = 0;

		/*
		 * Note if trying multiple user names; log failures for
		 * previous user name, but don't bother logging one failure
		 * for nonexistent name (mistyped username).
		 */
		if (failures && strcmp(olduser, username) != 0) {
			if (failures > (pwd ? 0 : 1))
				badlogin(olduser);
		}

		/*
		 * Load the PAM policy and set some variables
		 */
		pam_err = pam_start("login", username, &pamc, &pamh);
		if (pam_err != PAM_SUCCESS) {
			pam_syslog("pam_start()");
#ifdef USE_BSM_AUDIT
			au_login_fail("PAM Error", 1);
#endif
			bail(NO_SLEEP_EXIT, 1);
		}
		pam_err = pam_set_item(pamh, PAM_TTY, tty);
		if (pam_err != PAM_SUCCESS) {
			pam_syslog("pam_set_item(PAM_TTY)");
#ifdef USE_BSM_AUDIT
			au_login_fail("PAM Error", 1);
#endif
			bail(NO_SLEEP_EXIT, 1);
		}
		pam_err = pam_set_item(pamh, PAM_RHOST, hostname);
		if (pam_err != PAM_SUCCESS) {
			pam_syslog("pam_set_item(PAM_RHOST)");
#ifdef USE_BSM_AUDIT
			au_login_fail("PAM Error", 1);
#endif
			bail(NO_SLEEP_EXIT, 1);
		}

		pwd = getpwnam(username);
		if (pwd != NULL && pwd->pw_uid == 0)
			rootlogin = 1;

		/*
		 * If the -f option was specified and the caller is
		 * root or the caller isn't changing their uid, don't
		 * authenticate.
		 */
		if (pwd != NULL && fflag &&
		    (uid == (uid_t)0 || uid == (uid_t)pwd->pw_uid)) {
			/* already authenticated */
			rval = 0;
#ifdef USE_BSM_AUDIT
			auditsuccess = 0; /* opened a terminal window only */
#endif
		} else {
			fflag = 0;
			setpriority(PRIO_PROCESS, 0, -4);
			rval = auth_pam();
			setpriority(PRIO_PROCESS, 0, 0);
		}

		if (pwd && rval == 0)
			break;

		pam_cleanup();

		/*
		 * We are not exiting here, but this corresponds to a failed
		 * login event, so set exitstatus to 1.
		 */
#ifdef USE_BSM_AUDIT
		au_login_fail("Login incorrect", 1);
#endif

		printf("Login incorrect\n");
		failures++;

		pwd = NULL;

		/*
		 * Allow up to 'retry' (10) attempts, but start
		 * backing off after 'backoff' (3) attempts.
		 */
		if (++cnt > backoff) {
			if (cnt >= retries) {
				badlogin(username);
				bail(SLEEP_EXIT, 1);
			}
			sleep((u_int)((cnt - backoff) * 5));
		}
	}

	/* committed to login -- turn off timeout */
	alarm((u_int)0);
	signal(SIGHUP, SIG_DFL);

	endpwent();

#ifdef USE_BSM_AUDIT
	/* Audit successful login. */
	if (auditsuccess)
		au_login_success();
#endif

	/*
	 * Establish the login class.
	 */
	lc = login_getpwclass(pwd);
	lc_user = login_getuserclass(pwd);

	if (!(quietlog = login_getcapbool(lc_user, "hushlogin", 0)))
		quietlog = login_getcapbool(lc, "hushlogin", 0);

	/*
	 * Switching needed for NFS with root access disabled.
	 *
	 * XXX: This change fails to modify the additional groups for the
	 * process, and as such, may restrict rights normally granted
	 * through those groups.
	 */
	setegid(pwd->pw_gid);
	seteuid(rootlogin ? 0 : pwd->pw_uid);
	if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) {
		if (login_getcapbool(lc, "requirehome", 0))
			refused("Home directory not available", "HOMEDIR", 1);
		if (chdir("/") < 0)
			refused("Cannot find root directory", "ROOTDIR", 1);
		if (!quietlog || *pwd->pw_dir)
			printf("No home directory.\nLogging in with home = \"/\".\n");
		pwd->pw_dir = strdup("/");
		if (pwd->pw_dir == NULL) {
			syslog(LOG_NOTICE, "strdup(): %m");
			bail(SLEEP_EXIT, 1);
		}
	}
	seteuid(euid);
	setegid(egid);
	if (!quietlog) {
		quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
		if (!quietlog)
			pam_silent = 0;
	}

	shell = login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell);
	if (*pwd->pw_shell == '\0')
		pwd->pw_shell = strdup(_PATH_BSHELL);
	if (pwd->pw_shell == NULL) {
		syslog(LOG_NOTICE, "strdup(): %m");
		bail(SLEEP_EXIT, 1);
	}
	if (*shell == '\0')   /* Not overridden */
		shell = pwd->pw_shell;
	if ((shell = strdup(shell)) == NULL) {
		syslog(LOG_NOTICE, "strdup(): %m");
		bail(SLEEP_EXIT, 1);
	}

	/*
	 * Set device protections, depending on what terminal the
	 * user is logged in. This feature is used on Suns to give
	 * console users better privacy.
	 */
	login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);

	/*
	 * Clear flags of the tty.  None should be set, and when the
	 * user sets them otherwise, this can cause the chown to fail.
	 * Since it isn't clear that flags are useful on character
	 * devices, we just clear them.
	 *
	 * We don't log in the case of EOPNOTSUPP because dev might be
	 * on NFS, which doesn't support chflags.
	 *
	 * We don't log in the EROFS because that means that /dev is on
	 * a read only file system and we assume that the permissions there
	 * are sane.
	 */
	if (ttyn != tname && chflags(ttyn, 0))
		if (errno != EOPNOTSUPP && errno != EROFS)
			syslog(LOG_ERR, "chflags(%s): %m", ttyn);
	if (ttyn != tname && chown(ttyn, pwd->pw_uid,
	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
		if (errno != EROFS)
			syslog(LOG_ERR, "chown(%s): %m", ttyn);

	/*
	 * Exclude cons/vt/ptys only, assume dialup otherwise
	 * TODO: Make dialup tty determination a library call
	 * for consistency (finger etc.)
	 */
	if (hflag && isdialuptty(tty))
		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);

#ifdef LOGALL
	/*
	 * Syslog each successful login, so we don't have to watch
	 * hundreds of wtmp or lastlogin files.
	 */
	if (hflag)
		syslog(LOG_INFO, "login from %s on %s as %s",
		       hostname, tty, pwd->pw_name);
	else
		syslog(LOG_INFO, "login on %s as %s",
		       tty, pwd->pw_name);
#endif

	/*
	 * If fflag is on, assume caller/authenticator has logged root
	 * login.
	 */
	if (rootlogin && fflag == 0) {
		if (hflag)
			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
			    username, tty, hostname);
		else
			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s",
			    username, tty);
	}

	/*
	 * Destroy environment unless user has requested its
	 * preservation - but preserve TERM in all cases
	 */
	term = getenv("TERM");
	if (!pflag)
		environ = envinit;
	if (term != NULL) {
		if (setenv("TERM", term, 0) == -1)
			err(1, "setenv: cannot set TERM=%s", term);
	}

	/*
	 * PAM modules might add supplementary groups during pam_setcred().
	 */
	if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) {
		syslog(LOG_ERR, "setusercontext() failed - exiting");
		bail(NO_SLEEP_EXIT, 1);
	}

	pam_err = pam_setcred(pamh, pam_silent|PAM_ESTABLISH_CRED);
	if (pam_err != PAM_SUCCESS) {
		pam_syslog("pam_setcred()");
		bail(NO_SLEEP_EXIT, 1);
	}
	pam_cred_established = 1;

	pam_err = pam_open_session(pamh, pam_silent);
	if (pam_err != PAM_SUCCESS) {
		pam_syslog("pam_open_session()");
		bail(NO_SLEEP_EXIT, 1);
	}
	pam_session_established = 1;

	/*
	 * We must fork() before setuid() because we need to call
	 * pam_close_session() as root.
	 */
	pid = fork();
	if (pid < 0) {
		err(1, "fork");
	} else if (pid != 0) {
		/*
		 * Parent: wait for child to finish, then clean up
		 * session.
		 */
		int status;
		setproctitle("-%s [pam]", getprogname());
		waitpid(pid, &status, 0);
		bail(NO_SLEEP_EXIT, 0);
	}

	/*
	 * NOTICE: We are now in the child process!
	 */

	/*
	 * Add any environment variables the PAM modules may have set.
	 */
	export_pam_environment();

	/*
	 * We're done with PAM now; our parent will deal with the rest.
	 */
	pam_end(pamh, 0);
	pamh = NULL;

	/*
	 * We don't need to be root anymore, so set the login name and
	 * the UID.
	 */
	if (setlogin(username) != 0) {
		syslog(LOG_ERR, "setlogin(%s): %m - exiting", username);
		bail(NO_SLEEP_EXIT, 1);
	}
	if (setusercontext(lc, pwd, pwd->pw_uid,
	    LOGIN_SETALL & ~(LOGIN_SETLOGIN|LOGIN_SETGROUP)) != 0) {
		syslog(LOG_ERR, "setusercontext() failed - exiting");
		exit(1);
	}

	if (setenv("SHELL", pwd->pw_shell, 1) == -1)
		err(1, "setenv: cannot set SHELL=%s", pwd->pw_shell);
	if (setenv("HOME", pwd->pw_dir, 1) == -1)
		err(1, "setenv: cannot set HOME=%s", pwd->pw_dir);
	/* Overwrite "term" from login.conf(5) for any known TERM */
	if (term == NULL && (tp = stypeof(tty)) != NULL) {
		if (setenv("TERM", tp, 1) == -1)
			err(1, "setenv: cannot set TERM=%s", tp);
	} else {
		if (setenv("TERM", TERM_UNKNOWN, 0) == -1)
			err(1, "setenv: cannot set TERM=%s", TERM_UNKNOWN);
	}

	if (setenv("LOGNAME", username, 1) == -1)
		err(1, "setenv: cannot set LOGNAME=%s", username);
	if (setenv("USER", username, 1) == -1)
		err(1, "setenv: cannot set USER=%s", username);
	if (setenv("PATH",
	    rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0) == -1) {
		err(1, "setenv: cannot set PATH=%s",
		    rootlogin ? _PATH_STDPATH : _PATH_DEFPATH);
	}

	if (!quietlog) {
		const char *cw;

		cw = login_getcapstr(lc, "copyright", NULL, NULL);
		if (cw == NULL || motd(cw) == -1)
			printf("%s", copyright);

		printf("\n");

		cw = login_getcapstr(lc, "welcome", NULL, NULL);
		if (cw != NULL && access(cw, F_OK) == 0)
			motd(cw);
		else
			motd(_PATH_MOTDFILE);

		if (login_getcapbool(lc_user, "nocheckmail", 0) == 0 &&
		    login_getcapbool(lc, "nocheckmail", 0) == 0) {
			char *cx;

			/* $MAIL may have been set by class. */
			cx = getenv("MAIL");
			if (cx == NULL) {
				asprintf(&cx, "%s/%s",
				    _PATH_MAILDIR, pwd->pw_name);
			}
			if (cx && stat(cx, &st) == 0 && st.st_size != 0)
				printf("You have %smail.\n",
				    (st.st_mtime > st.st_atime) ? "new " : "");
			if (getenv("MAIL") == NULL)
				free(cx);
		}
	}

	login_close(lc_user);
	login_close(lc);

	signal(SIGALRM, SIG_DFL);
	signal(SIGQUIT, SIG_DFL);
	signal(SIGINT, SIG_DFL);
	signal(SIGTSTP, SIG_IGN);

	/*
	 * Login shells have a leading '-' in front of argv[0]
	 */
	p = strrchr(pwd->pw_shell, '/');
	if (asprintf(&arg0, "-%s", p ? p + 1 : pwd->pw_shell) >= MAXPATHLEN) {
		syslog(LOG_ERR, "user: %s: shell exceeds maximum pathname size",
		    username);
		errx(1, "shell exceeds maximum pathname size");
	} else if (arg0 == NULL) {
		err(1, "asprintf()");
	}

	execlp(shell, arg0, NULL);
	err(1, "%s", shell);

	/*
	 * That's it, folks!
	 */
}
Esempio n. 2
0
int main(int argc, char **argv)
{
	int c;
	int cnt;
	char *childArgv[10];
	char *buff;
	int childArgc = 0;
	int retcode;

	char *pwdbuf = NULL;
	struct passwd *pwd = NULL, _pwd;

	struct login_context cxt = {
		.tty_mode = TTY_MODE,		/* tty chmod() */
		.pid = getpid(),		/* PID */
		.conv = { misc_conv, NULL }	/* PAM conversation function */
	};

	timeout = (unsigned int)getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT);

	signal(SIGALRM, timedout);
	siginterrupt(SIGALRM, 1);	/* we have to interrupt syscalls like ioclt() */
	alarm(timeout);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGINT, SIG_IGN);

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	setpriority(PRIO_PROCESS, 0, 0);
	initproctitle(argc, argv);

	/*
	 * -p is used by getty to tell login not to destroy the environment
	 * -f is used to skip a second login authentication
	 * -h is used by other servers to pass the name of the remote
	 *    host to login so that it may be placed in utmp and wtmp
	 */
	while ((c = getopt(argc, argv, "fHh:pV")) != -1)
		switch (c) {
		case 'f':
			cxt.noauth = 1;
			break;

		case 'H':
			cxt.nohost = 1;
			break;

		case 'h':
			if (getuid()) {
				fprintf(stderr,
					_("login: -h for super-user only.\n"));
				exit(EXIT_FAILURE);
			}
			init_remote_info(&cxt, optarg);
			break;

		case 'p':
			cxt.keep_env = 1;
			break;

		case 'V':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case '?':
		default:
			fprintf(stderr, _("usage: login [ -p ] [ -h host ] [ -H ] [ -f username | username ]\n"));
			exit(EXIT_FAILURE);
		}
	argc -= optind;
	argv += optind;

	if (*argv) {
		char *p = *argv;
		cxt.username = xstrdup(p);

		/* wipe name - some people mistype their password here */
		/* (of course we are too late, but perhaps this helps a little ..) */
		while (*p)
			*p++ = ' ';
	}

	for (cnt = get_fd_tabsize() - 1; cnt > 2; cnt--)
		close(cnt);

	setpgrp();	 /* set pgid to pid this means that setsid() will fail */

	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);

	init_tty(&cxt);
	init_loginpam(&cxt);

	/* login -f, then the user has already been authenticated */
	cxt.noauth = cxt.noauth && getuid() == 0 ? 1 : 0;

	if (!cxt.noauth)
		loginpam_auth(&cxt);

	/*
	 * Authentication may be skipped (for example, during krlogin, rlogin,
	 * etc...), but it doesn't mean that we can skip other account checks.
	 * The account could be disabled or password expired (although
	 * kerberos ticket is valid).         -- [email protected] (22-Feb-2006)
	 */
	loginpam_acct(&cxt);

	if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
		warnx(_("\nSession setup problem, abort."));
		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
		       cxt.username, __FUNCTION__, __LINE__);
		pam_end(cxt.pamh, PAM_SYSTEM_ERR);
		sleepexit(EXIT_FAILURE);
	}

	pwd = cxt.pwd;
	cxt.username = pwd->pw_name;

	/*
	 * Initialize the supplementary group list. This should be done before
	 * pam_setcred because the PAM modules might add groups during
	 * pam_setcred.
	 *
         * For root we don't call initgroups, instead we call setgroups with
	 * group 0. This avoids the need to step through the whole group file,
	 * which can cause problems if NIS, NIS+, LDAP or something similar
	 * is used and the machine has network problems.
	 */
	retcode = pwd->pw_uid ? initgroups(cxt.username, pwd->pw_gid) :	/* user */
			        setgroups(0, NULL);			/* root */
	if (retcode < 0) {
		syslog(LOG_ERR, _("groups initialization failed: %m"));
		warnx(_("\nSession setup problem, abort."));
		pam_end(cxt.pamh, PAM_SYSTEM_ERR);
		sleepexit(EXIT_FAILURE);
	}

	/*
	 * Open PAM session (after successful authentication and account check)
	 */
	loginpam_session(&cxt);

	/* committed to login -- turn off timeout */
	alarm((unsigned int)0);

	endpwent();

	cxt.quiet = get_hushlogin_status(pwd);

	log_utmp(&cxt);
	log_audit(&cxt, 1);
	log_lastlog(&cxt);

	chown_tty(&cxt);

	if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) {
		syslog(LOG_ALERT, _("setgid() failed"));
		exit(EXIT_FAILURE);
	}

	if (pwd->pw_shell == NULL || *pwd->pw_shell == '\0')
		pwd->pw_shell = _PATH_BSHELL;

	init_environ(&cxt);		/* init $HOME, $TERM ... */

	setproctitle("login", cxt.username);

	log_syslog(&cxt);

	if (!cxt.quiet) {
		motd();

#ifdef LOGIN_STAT_MAIL
		/*
		 * This turns out to be a bad idea: when the mail spool
		 * is NFS mounted, and the NFS connection hangs, the
		 * login hangs, even root cannot login.
		 * Checking for mail should be done from the shell.
		 */
		{
			struct stat st;
			char *mail;

			mail = getenv("MAIL");
			if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
				if (st.st_mtime > st.st_atime)
					printf(_("You have new mail.\n"));
				else
					printf(_("You have mail.\n"));
			}
		}
#endif
	}

	/*
	 * Detach the controlling terminal, fork() and create, new session
	 * and reinilizalize syslog stuff.
	 */
	fork_session(&cxt);

	/* discard permissions last so can't get killed and drop core */
	if (setuid(pwd->pw_uid) < 0 && pwd->pw_uid) {
		syslog(LOG_ALERT, _("setuid() failed"));
		exit(EXIT_FAILURE);
	}

	/* wait until here to change directory! */
	if (chdir(pwd->pw_dir) < 0) {
		warn(_("%s: change directory failed"), pwd->pw_dir);

		if (!getlogindefs_bool("DEFAULT_HOME", 1))
			exit(0);
		if (chdir("/"))
			exit(EXIT_FAILURE);
		pwd->pw_dir = "/";
		printf(_("Logging in with home = \"/\".\n"));
	}

	/* if the shell field has a space: treat it like a shell script */
	if (strchr(pwd->pw_shell, ' ')) {
		buff = xmalloc(strlen(pwd->pw_shell) + 6);

		strcpy(buff, "exec ");
		strcat(buff, pwd->pw_shell);
		childArgv[childArgc++] = "/bin/sh";
		childArgv[childArgc++] = "-sh";
		childArgv[childArgc++] = "-c";
		childArgv[childArgc++] = buff;
	} else {
		char tbuf[PATH_MAX + 2], *p;

		tbuf[0] = '-';
		xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ?
				    p + 1 : pwd->pw_shell), sizeof(tbuf) - 1);

		childArgv[childArgc++] = pwd->pw_shell;
		childArgv[childArgc++] = xstrdup(tbuf);
	}

	childArgv[childArgc++] = NULL;

	execvp(childArgv[0], childArgv + 1);

	if (!strcmp(childArgv[0], "/bin/sh"))
		warn(_("couldn't exec shell script"));
	else
		warn(_("no shell"));

	exit(EXIT_SUCCESS);
}
Esempio n. 3
0
int
main(int argc, char **argv)
{
	int ch, np, ret, Xflag = 0;
	pcap_handler phandler = dump_packet;
	const char *errstr = NULL;
	char *pidf = NULL;

	ret = 0;

	closefrom(STDERR_FILENO + 1);

	while ((ch = getopt(argc, argv, "Dxd:f:i:p:s:")) != -1) {
		switch (ch) {
		case 'D':
			Debug = 1;
			break;
		case 'd':
			delay = strtonum(optarg, 5, 60*60, &errstr);
			if (errstr)
				usage();
			break;
		case 'f':
			filename = optarg;
			break;
		case 'i':
			interface = optarg;
			break;
		case 'p':
			pidf = optarg;
			break;
		case 's':
			snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
			    &errstr);
			if (snaplen <= 0)
				snaplen = DEF_SNAPLEN;
			if (errstr)
				snaplen = PFLOGD_MAXSNAPLEN;
			break;
		case 'x':
			Xflag++;
			break;
		default:
			usage();
		}

	}

	log_debug = Debug;
	argc -= optind;
	argv += optind;

	/* does interface exist */
	if (!if_exists(interface)) {
		warn("Failed to initialize: %s", interface);
		logmsg(LOG_ERR, "Failed to initialize: %s", interface);
		logmsg(LOG_ERR, "Exiting, init failure");
		exit(1);
	}

	if (!Debug) {
		openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
		if (daemon(0, 0)) {
			logmsg(LOG_WARNING, "Failed to become daemon: %s",
			    strerror(errno));
		}
		pidfile(pidf);
	}

	tzset();
	(void)umask(S_IRWXG | S_IRWXO);

	/* filter will be used by the privileged process */
	if (argc) {
		filter = copy_argv(argv);
		if (filter == NULL)
			logmsg(LOG_NOTICE, "Failed to form filter expression");
	}

	/* initialize pcap before dropping privileges */
	if (init_pcap()) {
		logmsg(LOG_ERR, "Exiting, init failure");
		exit(1);
	}

	/* Privilege separation begins here */
	if (priv_init()) {
		logmsg(LOG_ERR, "unable to privsep");
		exit(1);
	}

	setproctitle("[initializing]");
	/* Process is now unprivileged and inside a chroot */
	signal(SIGTERM, sig_close);
	signal(SIGINT, sig_close);
	signal(SIGQUIT, sig_close);
	signal(SIGALRM, sig_alrm);
	signal(SIGUSR1, sig_usr1);
	signal(SIGHUP, sig_hup);
	alarm(delay);

	buffer = malloc(PFLOGD_BUFSIZE);

	if (buffer == NULL) {
		logmsg(LOG_WARNING, "Failed to allocate output buffer");
		phandler = dump_packet_nobuf;
	} else {
		bufleft = buflen = PFLOGD_BUFSIZE;
		bufpos = buffer;
		bufpkt = 0;
	}

	if (reset_dump(Xflag) < 0) {
		if (Xflag)
			return (1);

		logmsg(LOG_ERR, "Logging suspended: open error");
		set_suspended(1);
	} else if (Xflag)
		return (0);

	while (1) {
		np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
		    phandler, (u_char *)dpcap);
		if (np < 0) {
			if (!if_exists(interface) == -1) {
				logmsg(LOG_NOTICE, "interface %s went away",
				    interface);
				ret = -1;
				break;
			}
			logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
		}

		if (gotsig_close)
			break;
		if (gotsig_hup) {
			if (reset_dump(0)) {
				logmsg(LOG_ERR,
				    "Logging suspended: open error");
				set_suspended(1);
			}
			gotsig_hup = 0;
		}

		if (gotsig_alrm) {
			if (dpcap)
				flush_buffer(dpcap);
			else 
				gotsig_hup = 1;
			gotsig_alrm = 0;
			alarm(delay);
		}

		if (gotsig_usr1) {
			log_pcap_stats();
			gotsig_usr1 = 0;
		}
	}

	logmsg(LOG_NOTICE, "Exiting");
	if (dpcap) {
		flush_buffer(dpcap);
		fclose(dpcap);
	}
	purge_buffer();

	log_pcap_stats();
	pcap_close(hpcap);
	if (!Debug)
		closelog();
	return (ret);
}
Esempio n. 4
0
/*
 * Generic function to handle CRIU_REQ_TYPE__FEATURE_CHECK.
 *
 * The function will have resp.success = true for most cases
 * and the actual result will be in resp.features.
 *
 * For each feature which has been requested in msg->features
 * the corresponding parameter will be set in resp.features.
 */
static int handle_feature_check(int sk, CriuReq * msg)
{
	CriuResp resp = CRIU_RESP__INIT;
	CriuFeatures feat = CRIU_FEATURES__INIT;
	int pid, status;
	int ret;

	/* enable setting of an optional message */
	feat.has_mem_track = 1;
	feat.mem_track = false;
	feat.has_lazy_pages = 1;
	feat.lazy_pages = false;

	pid = fork();
	if (pid < 0) {
		pr_perror("Can't fork");
		goto out;
	}

	if (pid == 0) {
		/* kerndat_init() is called from setup_opts_from_req() */
		if (setup_opts_from_req(sk, msg->opts))
			exit(1);

		setproctitle("feature-check --rpc");

		if ((msg->features->has_mem_track == 1) &&
		    (msg->features->mem_track == true))
			feat.mem_track = kdat.has_dirty_track;

		if ((msg->features->has_lazy_pages == 1) &&
		    (msg->features->lazy_pages == true))
			feat.lazy_pages = kdat.has_uffd && uffd_noncooperative();

		resp.features = &feat;
		resp.type = msg->type;
		/* The feature check is working, actual results are in resp.features */
		resp.success = true;

		/*
		 * If this point is reached the information about the features
		 * is transmitted from the forked CRIU process (here).
		 * If an error occurred earlier, the feature check response will be
		 * be send from the parent process.
		 */
		ret = send_criu_msg(sk, &resp);
		exit(!!ret);
	}
	if (waitpid(pid, &status, 0) != pid) {
		pr_perror("Unable to wait %d", pid);
		goto out;
	}
	if (status != 0)
		goto out;

	/*
	 * The child process was not able to send an answer. Tell
	 * the RPC client that something did not work as expected.
	 */
out:
	resp.type = msg->type;
	resp.success = false;

	return send_criu_msg(sk, &resp);
}
Esempio n. 5
0
int
main(int argc, char *argv[])
{
	int c, error, gdb_port, err, bvmcons;
	int max_vcpus;
	struct vmctx *ctx;
	uint64_t rip;
	size_t memsize;

	bvmcons = 0;
	progname = basename(argv[0]);
	gdb_port = 0;
	guest_ncpus = 1;
	memsize = 256 * MB;

	while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) {
		switch (c) {
		case 'a':
			x2apic_mode = 0;
			break;
		case 'A':
			acpi = 1;
			break;
		case 'b':
			bvmcons = 1;
			break;
		case 'p':
			pincpu = atoi(optarg);
			break;
                case 'c':
			guest_ncpus = atoi(optarg);
			break;
		case 'g':
			gdb_port = atoi(optarg);
			break;
		case 'l':
			if (lpc_device_parse(optarg) != 0) {
				errx(EX_USAGE, "invalid lpc device "
				    "configuration '%s'", optarg);
			}
			break;
		case 's':
			if (pci_parse_slot(optarg) != 0)
				exit(1);
			else
				break;
                case 'm':
			error = vm_parse_memsize(optarg, &memsize);
			if (error)
				errx(EX_USAGE, "invalid memsize '%s'", optarg);
			break;
		case 'H':
			guest_vmexit_on_hlt = 1;
			break;
		case 'I':
			/*
			 * The "-I" option was used to add an ioapic to the
			 * virtual machine.
			 *
			 * An ioapic is now provided unconditionally for each
			 * virtual machine and this option is now deprecated.
			 */
			break;
		case 'P':
			guest_vmexit_on_pause = 1;
			break;
		case 'e':
			strictio = 1;
			break;
		case 'U':
			guest_uuid_str = optarg;
			break;
		case 'w':
			strictmsr = 0;
			break;
		case 'W':
			virtio_msix = 0;
			break;
		case 'x':
			x2apic_mode = 1;
			break;
		case 'h':
			usage(0);			
		default:
			usage(1);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		usage(1);

	vmname = argv[0];

	ctx = vm_open(vmname);
	if (ctx == NULL) {
		perror("vm_open");
		exit(1);
	}

	max_vcpus = num_vcpus_allowed(ctx);
	if (guest_ncpus > max_vcpus) {
		fprintf(stderr, "%d vCPUs requested but only %d available\n",
			guest_ncpus, max_vcpus);
		exit(1);
	}

	fbsdrun_set_capabilities(ctx, BSP);

	err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
	if (err) {
		fprintf(stderr, "Unable to setup memory (%d)\n", err);
		exit(1);
	}

	init_mem();
	init_inout();
	ioapic_init(ctx);

	rtc_init(ctx);

	/*
	 * Exit if a device emulation finds an error in it's initilization
	 */
	if (init_pci(ctx) != 0)
		exit(1);

	if (gdb_port != 0)
		init_dbgport(gdb_port);

	if (bvmcons)
		init_bvmcons();

	error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
	assert(error == 0);

	/*
	 * build the guest tables, MP etc.
	 */
	mptable_build(ctx, guest_ncpus);

	error = smbios_build(ctx);
	assert(error == 0);

	if (acpi) {
		error = acpi_build(ctx, guest_ncpus);
		assert(error == 0);
	}

	/*
	 * Change the proc title to include the VM name.
	 */
	setproctitle("%s", vmname); 
	
	/*
	 * Add CPU 0
	 */
	fbsdrun_addcpu(ctx, BSP, BSP, rip);

	/*
	 * Head off to the main event dispatch loop
	 */
	mevent_dispatch();

	exit(1);
}
Esempio n. 6
0
int
main(int argc, char *argv[])
{
	extern char *optarg;		/* argument to option if any */
	int i;				/* counter in a for loop */
	char *p;			/* used to obtain the key */
	DES_cblock msgbuf;		/* I/O buffer */
	int kflag;			/* command-line encryption key */

	setproctitle("-");		/* Hide command-line arguments */

	/* initialize the initialization vector */
	MEMZERO(ivec, 8);

	/* process the argument list */
	kflag = 0;
	while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1)
		switch(i) {
		case 'a':		/* key is ASCII */
			keybase = KEY_ASCII;
			break;
		case 'b':		/* use ECB mode */
			alg = ALG_ECB;
			break;
		case 'd':		/* decrypt */
			mode = MODE_DECRYPT;
			break;
		case 'F':		/* use alternative CFB mode */
			alg = ALG_CFBA;
			if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0)
				errx(1, "-F: number must be 1-56 inclusive");
			else if (fbbits == -1)
				errx(1, "-F: number must be a multiple of 7");
			break;
		case 'f':		/* use CFB mode */
			alg = ALG_CFB;
			if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
				errx(1, "-f: number must be 1-64 inclusive");
			else if (fbbits == -1)
				errx(1, "-f: number must be a multiple of 8");
			break;
		case 'k':		/* encryption key */
			kflag = 1;
			cvtkey(msgbuf, optarg);
			break;
		case 'm':		/* number of bits for MACing */
			mode = MODE_AUTHENTICATE;
			if ((macbits = setbits(optarg, 1)) > 64)
				errx(1, "-m: number must be 0-64 inclusive");
			break;
		case 'o':		/* use OFB mode */
			alg = ALG_OFB;
			if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
				errx(1, "-o: number must be 1-64 inclusive");
			else if (fbbits == -1)
				errx(1, "-o: number must be a multiple of 8");
			break;
		case 'p':		/* preserve parity bits */
			pflag = 1;
			break;
		case 'v':		/* set initialization vector */
			cvtkey(ivec, optarg);
			break;
		default:		/* error */
			usage();
		}

	if (!kflag) {
		/*
		 * if the key's not ASCII, assume it is
		 */
		keybase = KEY_ASCII;
		/*
		 * get the key
		 */
		p = getpass("Enter key: ");
		/*
		 * copy it, nul-padded, into the key area
		 */
		cvtkey(msgbuf, p);
	}

	makekey(&msgbuf);
	inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT;

	switch(alg) {
	case ALG_CBC:
		switch(mode) {
		case MODE_AUTHENTICATE:	/* authenticate using CBC mode */
			cbcauth();
			break;
		case MODE_DECRYPT:	/* decrypt using CBC mode */
			cbcdec();
			break;
		case MODE_ENCRYPT:	/* encrypt using CBC mode */
			cbcenc();
			break;
		}
		break;
	case ALG_CFB:
		switch(mode) {
		case MODE_AUTHENTICATE:	/* authenticate using CFB mode */
			cfbauth();
			break;
		case MODE_DECRYPT:	/* decrypt using CFB mode */
			cfbdec();
			break;
		case MODE_ENCRYPT:	/* encrypt using CFB mode */
			cfbenc();
			break;
		}
		break;
	case ALG_CFBA:
		switch(mode) {
		case MODE_AUTHENTICATE:	/* authenticate using CFBA mode */
			errx(1, "can't authenticate with CFBA mode");
			break;
		case MODE_DECRYPT:	/* decrypt using CFBA mode */
			cfbadec();
			break;
		case MODE_ENCRYPT:	/* encrypt using CFBA mode */
			cfbaenc();
			break;
		}
		break;
	case ALG_ECB:
		switch(mode) {
		case MODE_AUTHENTICATE:	/* authenticate using ECB mode */
			errx(1, "can't authenticate with ECB mode");
			break;
		case MODE_DECRYPT:	/* decrypt using ECB mode */
			ecbdec();
			break;
		case MODE_ENCRYPT:	/* encrypt using ECB mode */
			ecbenc();
			break;
		}
		break;
	case ALG_OFB:
		switch(mode) {
		case MODE_AUTHENTICATE:	/* authenticate using OFB mode */
			errx(1, "can't authenticate with OFB mode");
			break;
		case MODE_DECRYPT:	/* decrypt using OFB mode */
			ofbdec();
			break;
		case MODE_ENCRYPT:	/* encrypt using OFB mode */
			ofbenc();
			break;
		}
		break;
	}
	return (0);
}
Esempio n. 7
0
File: shmctl.c Progetto: ptt/pttbbs
int utmpfix(int argc, char **argv)
{
    int     i, fast = 0, nownum = SHM->UTMPnumber;
    int     which, nactive = 0, dofork = 1, daemonsleep = 0;
    time_t  now;
    const char    *clean;
    char buf[1024];
    IDLE_t  idle[USHM_SIZE];
    char    changeflag = 0;
    time_t  idletimeout = IDLE_TIMEOUT;
    int     lowerbound = 100, upperbound = 0;
    char    ch;

    int     killtop = 0;
    struct {
	pid_t   pid;
	int     where;
    } killlist[USHM_SIZE];

    while( (ch = getopt(argc, argv, "nt:l:FD:u:")) != -1 )
	switch( ch ){
	case 'n':
	    fast = 1;
	    break;
	case 't':
	    idletimeout = atoi(optarg);
	    break;
	case 'l':
	    lowerbound = atoi(optarg);
	    break;
	case 'F':
	    dofork = 0;
	    break;
	case 'D':
	    daemonsleep = atoi(optarg);
	    break;
	case 'u':
	    upperbound = atoi(optarg);
	    break;
	default:
	    printf("usage:\tshmctl\tutmpfix [-n] [-t timeout] [-F] [-D sleep]\n");
	    return 1;
	}

    if( daemonsleep )
	switch( fork() ){
	case -1:
	    perror("fork()");
	    return 0;
	case 0:
	    break;
	default:
	    return 0;
	}

    if( daemonsleep || dofork ){
	int     times = 1000, status;
	pid_t   pid;
	while( daemonsleep ? 1 : times-- )
	    switch( pid = fork() ){
	    case -1:
		sleep(1);
		break;
	    case 0:
#ifndef VALGRIND
		setproctitle("utmpfix");
#endif
		goto DoUtmpfix;
	    default:
#ifndef VALGRIND
		setproctitle(daemonsleep ? "utmpfixd(wait for %d)" :
			     "utmpfix(wait for %d)", (int)pid);
#endif
		waitpid(pid, &status, 0);
		if( WIFEXITED(status) && !daemonsleep )
		    return 0;
		if( !WIFEXITED(status) ){
		    /* last utmpfix fails, so SHM->UTMPbusystate is holded */
		    SHM->UTMPbusystate = 0;
		}
	    }
	return 0; // never reach
    }

 DoUtmpfix:
    killtop=0;
    changeflag=0;
    for( i = 0 ; i < 5 ; ++i )
	if( !SHM->UTMPbusystate )
	    break;
	else{
	    puts("utmpshm is busy....");
	    sleep(1);
	}
    SHM->UTMPbusystate = 1;

    printf("starting scaning... %s \n", (fast ? "(fast mode)" : ""));
    nownum = SHM->UTMPnumber;
    now = time(NULL);
    for( i = 0, nactive = 0 ; i < USHM_SIZE ; ++i )
	if( SHM->uinfo[i].pid ){
	    idle[nactive].index = i;
	    idle[nactive].idle = now - SHM->uinfo[i].lastact;
	    ++nactive;
	}
    if( !fast )
	qsort(idle, nactive, sizeof(IDLE_t), sfIDLE);

    #define addkilllist(a)			\
        do {					\
	    pid_t pid=SHM->uinfo[(a)].pid;	\
	    if(pid > 0) {			\
		killlist[killtop].where = (a);	\
		killlist[killtop++].pid = pid;	\
	    }					\
        } while( 0 )
    for( i = 0 ; i < nactive ; ++i ){
	which = idle[i].index;
	clean = NULL;
	if( !isalpha(SHM->uinfo[which].userid[0]) ){
	    clean = "userid error";
	    addkilllist(which);
	}
	else if( memchr(SHM->uinfo[which].userid, '\0', IDLEN + 1) == NULL ){
	    clean = "userid without z";
	    addkilllist(which);
	}
	else if( SHM->uinfo[which].friendtotal > MAX_FRIEND || SHM->uinfo[which].friendtotal<0 ){
	    clean = "too many/less friend";
	    addkilllist(which);
	}
	else if( searchuser(SHM->uinfo[which].userid, NULL) == 0 ){
	    clean = "user not exist";
	    addkilllist(which);
	}
	else if( kill(SHM->uinfo[which].pid, 0) < 0 ){
	    /* 此條件應放最後; 其他欄位沒問題但 process 不存在才 purge_utmp */
	    clean = "process error";
	    purge_utmp(&SHM->uinfo[which]);
	}
#ifdef DOTIMEOUT
	else if( (strcasecmp(SHM->uinfo[which].userid, STR_GUEST)==0 &&
	      idle[i].idle > 60*15) ||
	    (!fast && nownum > lowerbound && 
	     idle[i].idle > idletimeout ) ) {
	  sprintf(buf, "timeout(%s",
	      ctime4(&SHM->uinfo[which].lastact));
	  buf[strlen(buf) - 1] = 0;
	  strcat(buf, ")");
	  clean = buf;
	  addkilllist(which);
	  purge_utmp(&SHM->uinfo[which]);
	  printf("%s\n", buf);
	  --nownum;
	  continue;
	}
#endif
	
	if( clean ){
	    printf("clean %06d(%s), userid: %s\n",
		   i, clean, SHM->uinfo[which].userid);
	    memset(&SHM->uinfo[which], 0, sizeof(userinfo_t));
	    --nownum;
	    changeflag = 1;
	}
    }
    for( i = 0 ; i < killtop ; ++i ){
	printf("sending SIGHUP to %d\n", (int)killlist[i].pid);
	kill(killlist[i].pid, SIGHUP);
    }
    sleep(3);
    for( i = 0 ; i < killtop ; ++i )
	// FIXME 前面已經 memset 把 SHM->uinfo[which] 清掉了, 此處檢查 pid 無用
	if( SHM->uinfo[killlist[i].where].pid == killlist[i].pid &&
	    kill(killlist[i].pid, 0) == 0 ){ // still alive
	    printf("sending SIGKILL to %d\n", (int)killlist[i].pid);
	    kill(killlist[i].pid, SIGKILL);
	    purge_utmp(&SHM->uinfo[killlist[i].where]);
	}
    SHM->UTMPbusystate = 0;
    if( changeflag )
	SHM->UTMPneedsort = 1;

    if( daemonsleep ){
	do{
	    sleep(daemonsleep);
	} while( upperbound && SHM->UTMPnumber < upperbound );
	goto DoUtmpfix; /* XXX: goto */
    }
    return 0;
}
Esempio n. 8
0
struct rspamd_worker *
rspamd_fork_worker (struct rspamd_main *rspamd_main,
		struct rspamd_worker_conf *cf,
		guint index,
		struct event_base *ev_base)
{
	struct rspamd_worker *wrk;
	gint rc;
	struct rlimit rlim;

	/* Starting worker process */
	wrk = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker));

	if (!rspamd_socketpair (wrk->control_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	if (!rspamd_socketpair (wrk->srv_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	wrk->srv = rspamd_main;
	wrk->type = cf->type;
	wrk->cf = g_malloc (sizeof (struct rspamd_worker_conf));
	memcpy (wrk->cf, cf, sizeof (struct rspamd_worker_conf));
	wrk->index = index;
	wrk->ctx = cf->ctx;

	wrk->pid = fork ();

	switch (wrk->pid) {
	case 0:
		/* Update pid for logging */
		rspamd_log_update_pid (cf->type, rspamd_main->logger);
		/* Remove the inherited event base */
		event_reinit (rspamd_main->ev_base);
		event_base_free (rspamd_main->ev_base);
		/* Lock statfile pool if possible XXX */
		/* Init PRNG after fork */
		rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg);
		rspamd_random_seed_fast ();
		if (rc != OTTERY_ERR_NONE) {
			msg_err_main ("cannot initialize PRNG: %d", rc);
			g_assert (0);
		}

		g_random_set_seed (ottery_rand_uint32 ());
		/* Drop privilleges */
		rspamd_worker_drop_priv (rspamd_main);
		/* Set limits */
		rspamd_worker_set_limits (rspamd_main, cf);
		/* Re-set stack limit */
		getrlimit (RLIMIT_STACK, &rlim);
		rlim.rlim_cur = 100 * 1024 * 1024;
		rlim.rlim_max = rlim.rlim_cur;
		setrlimit (RLIMIT_STACK, &rlim);

		setproctitle ("%s process", cf->worker->name);
		rspamd_pidfile_close (rspamd_main->pfh);
		/* Do silent log reopen to avoid collisions */
		rspamd_log_close (rspamd_main->logger);
		rspamd_log_open (rspamd_main->logger);
		wrk->start_time = rspamd_get_calendar_ticks ();

#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30))
# if (GLIB_MINOR_VERSION > 20)
		/* Ugly hack for old glib */
		if (!g_thread_get_initialized ()) {
			g_thread_init (NULL);
		}
# else
		g_thread_init (NULL);
# endif
#endif
		msg_info_main ("starting %s process %P", cf->worker->name, getpid ());
		/* Close parent part of socketpair */
		close (wrk->control_pipe[0]);
		close (wrk->srv_pipe[0]);
		rspamd_socket_nonblocking (wrk->control_pipe[1]);
		rspamd_socket_nonblocking (wrk->srv_pipe[1]);
		/* Execute worker */
		cf->worker->worker_start_func (wrk);
		exit (EXIT_FAILURE);
		break;
	case -1:
		msg_err_main ("cannot fork main process. %s", strerror (errno));
		rspamd_pidfile_remove (rspamd_main->pfh);
		exit (-errno);
		break;
	default:
		/* Close worker part of socketpair */
		close (wrk->control_pipe[1]);
		close (wrk->srv_pipe[1]);
		rspamd_socket_nonblocking (wrk->control_pipe[0]);
		rspamd_socket_nonblocking (wrk->srv_pipe[0]);
		rspamd_srv_start_watching (wrk, ev_base);
		/* Insert worker into worker's table, pid is index */
		g_hash_table_insert (rspamd_main->workers, GSIZE_TO_POINTER (
				wrk->pid), wrk);
		break;
	}

	return wrk;
}
Esempio n. 9
0
void ManageSession(struct display *d)
{
	static int pid = 0;
	Display *dpy;
	greet_user_rtn greet_stat;
#ifdef WITH_CONSOLE_KIT
	char *ck_session_cookie = NULL;
#endif

	WDMDebug("ManageSession %s\n", d->name);
	(void)XSetIOErrorHandler(IOErrorHandler);
	(void)XSetErrorHandler(ErrorHandler);
#ifndef HAS_SETPROCTITLE
	SetTitle(d->name, (char *)0);
#else
	setproctitle("%s", d->name);
#endif
	/*
	 * Load system default Resources
	 */
	LoadXloginResources(d);

	verify.version = 1;
	greet.version = 1;
	greet_stat = GreetUser(d, &dpy, &verify, &greet);

	if (greet_stat == Greet_Success) {
		clientPid = 0;
		if (!Setjmp(abortSession)) {
			(void)Signal(SIGTERM, catchTerm);
			/*
			 * Start the clients, changing uid/groups
			 *     setting up environment and running the session
			 */
#ifdef WITH_CONSOLE_KIT
			ck_session_cookie = open_ck_session(getpwnam(greet.name), d);
#endif
			if (StartClient(&verify, d, &clientPid, greet.name, greet.password
#ifdef WITH_CONSOLE_KIT
							, ck_session_cookie
#endif
				)) {
				WDMDebug("Client Started\n");

				/*
				 * Wait for session to end,
				 */
				for (;;) {
					if (d->pingInterval) {
						if (!Setjmp(pingTime)) {
							(void)Signal(SIGALRM, catchAlrm);
							(void)alarm(d->pingInterval * 60);
							pid = wait((waitType *) 0);
							(void)alarm(0);
						} else {
							(void)alarm(0);
							if (!PingServer(d, (Display *) NULL))
								SessionPingFailed(d);
						}
					} else {
						pid = wait((waitType *) 0);
					}
					if (pid == clientPid)
						break;
				}
			} else {
				WDMError("session start failed\n");
			}
		} else {
			/*
			 * when terminating the session, nuke
			 * the child and then run the reset script
			 */
			AbortClient(clientPid);
		}
	}
#ifdef WITH_CONSOLE_KIT
	if (ck_session_cookie != NULL) {
		close_ck_session(ck_session_cookie);
		free(ck_session_cookie);
	}
#endif

	/*
	 * run system-wide reset file
	 */
	WDMDebug("Source reset program %s\n", d->reset);
	source(verify.systemEnviron, d->reset);
	SessionExit(d, OBEYSESS_DISPLAY, TRUE);
}
Esempio n. 10
0
int
client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags)
{
	struct sockaddr_un		sa;
	struct stat			sb;
	struct msg_identify_data	data;
	struct winsize			ws;
	size_t				size;
	int				fd, fd2, mode;
	char			       *name, *term;
#ifdef HAVE_SETPROCTITLE
	char		 		rpathbuf[MAXPATHLEN];
#endif

#ifdef HAVE_SETPROCTITLE
	if (realpath(path, rpathbuf) == NULL)
		strlcpy(rpathbuf, path, sizeof rpathbuf);
	setproctitle("client (%s)", rpathbuf);
#endif

	if (lstat(path, &sb) != 0) {
		if (cmdflags & CMD_STARTSERVER && errno == ENOENT) {
			if ((fd = server_start(path)) == -1)
				goto start_failed;
			goto server_started;
		}
		goto not_found;
	}
	if (!S_ISSOCK(sb.st_mode)) {
		errno = ENOTSOCK;
		goto not_found;
	}

	memset(&sa, 0, sizeof sa);
	sa.sun_family = AF_UNIX;
	size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
	if (size >= sizeof sa.sun_path) {
		errno = ENAMETOOLONG;
		goto not_found;
	}

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		fatal("socket");

	if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
		if (errno == ECONNREFUSED) {
			if (unlink(path) != 0 || !(cmdflags & CMD_STARTSERVER))
				goto not_found;
			if ((fd = server_start(path)) == -1)
				goto start_failed;
			goto server_started;
		}
		goto not_found;
	}

server_started:
	if ((mode = fcntl(fd, F_GETFL)) == -1)
		fatal("fcntl failed");
	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
		fatal("fcntl failed");
	imsg_init(&cctx->ibuf, fd);

	if (cmdflags & CMD_SENDENVIRON)
		client_send_environ(cctx);
	if (isatty(STDIN_FILENO)) {
		if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
			fatal("ioctl(TIOCGWINSZ)");
		data.flags = flags;
		data.sx = ws.ws_col;
		data.sy = ws.ws_row;

		if (getcwd(data.cwd, sizeof data.cwd) == NULL)
			*data.cwd = '\0';

		*data.term = '\0';
		if ((term = getenv("TERM")) != NULL) {
			if (strlcpy(data.term,
			    term, sizeof data.term) >= sizeof data.term)
				*data.term = '\0';
		}

		*data.tty = '\0';
		if ((name = ttyname(STDIN_FILENO)) == NULL)
			fatal("ttyname failed");
		if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
			fatalx("ttyname failed");

		fd2 = dup(STDIN_FILENO);
		imsg_compose(&cctx->ibuf, MSG_IDENTIFY,
		    PROTOCOL_VERSION, -1, fd2, &data, sizeof data);
	}

	return (0);

start_failed:
	log_warnx("server failed to start");
	return (1);

not_found:
	log_warn("server not found");
	return (1);
}
Esempio n. 11
0
File: main.cpp Progetto: madf/stg
//-----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
SETTINGS_IMPL settings;

if (argc == 2)
    {
    settings.SetConfFile(argv[1]);
    }
else
    {
    // Usage
    }

if (settings.ReadSettings())
    {
    printf("ReadSettingsError\n");
    printf("%s\n", settings.GetStrError().c_str());
    exit(-1);
    }
settings.Print();

if (settings.GetDaemon())
    {
    switch (fork())
        {
        case -1:
            exit(1);
            break;

        case 0:
            setsid();
            break;

        default:
            exit(0);
            break;
        }
    }

clnp = new IA_CLIENT_PROT(settings.GetServerName(), settings.GetServerPort(), settings.GetLocalName(), settings.GetLocalPort());

if (!settings.GetNoWeb())
    {
    web = new WEB();
    web->SetRefreshPagePeriod(settings.GetRefreshPeriod());
    web->SetListenAddr(settings.GetListenWebIP());
    web->Start();
    }

clnp->SetLogin(settings.GetLogin());
clnp->SetPassword(settings.GetPassword());

clnp->SetStatusChangedCb(StatusChanged, NULL);
clnp->SetInfoCb(ShowMessage, NULL);
clnp->SetErrorCb(ShowError, NULL);
clnp->SetDirNameCb(SetDirName, NULL);
clnp->SetStatChangedCb(StatUpdate, NULL);
clnp->SetReconnect(settings.GetReconnect());

clnp->Start();

SetSignalHandlers();

#ifdef LINUX
for (int i = 1; i < argc; i++)
    memset(argv[i], 0, strlen(argv[i]));

if(argc > 1)
    strcpy(argv[1], "Connecting...");
#endif

#ifdef FREEBSD
setproctitle("Connecting...");
#endif
clnp->Connect();

while (1)
    {
    struct timespec ts = {0, 200000000};
    nanosleep(&ts, NULL);

    char state[20];

    if (clnp->GetAuthorized())
        {
        if (settings.GetShowPid())
            sprintf(state, "On %d", getpid());
        else
            strcpy(state, "Online");
        }
    else
        {
        if (settings.GetShowPid())
            sprintf(state, "Off %d", getpid());
        else
            strcpy(state, "Offline");
        }

    #ifdef LINUX
    for (int i = 1; i < argc; i++)
        memset(argv[i], 0, strlen(argv[i]));
    if(argc > 1)
        strcpy(argv[1], state);
    #endif

    #ifdef FREEBSD
    setproctitle(state);
    #endif

    #ifdef FREEBSD_5
    setproctitle(state);
    #endif
    }

return 0;
}
Esempio n. 12
0
int
main(int argc, char *argv[])
{
	struct ntpd_conf	 lconf;
	struct pollfd		 pfd[POLL_MAX];
	pid_t			 chld_pid = 0, pid;
	const char		*conffile;
	int			 ch, nfds;
	int			 pipe_chld[2];
	struct passwd		*pw;

	conffile = CONFFILE;

	bzero(&lconf, sizeof(lconf));

	log_init(1);		/* log to stderr until daemonized */

	while ((ch = getopt(argc, argv, "df:nsSv")) != -1) {
		switch (ch) {
		case 'd':
			lconf.debug = 1;
			break;
		case 'f':
			conffile = optarg;
			break;
		case 'n':
			lconf.noaction = 1;
			break;
		case 's':
			lconf.settime = 1;
			break;
		case 'S':
			lconf.settime = 0;
			break;
		case 'v':
			debugsyslog = 1;
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}

	argc -= optind;
	argv += optind;
	if (argc > 0)
		usage();

	if (parse_config(conffile, &lconf))
		exit(1);

	if (lconf.noaction) {
		fprintf(stderr, "configuration OK\n");
		exit(0);
	}

	if (geteuid())
		errx(1, "need root privileges");

	if ((pw = getpwnam(NTPD_USER)) == NULL)
		errx(1, "unknown user %s", NTPD_USER);

	reset_adjtime();
	if (!lconf.settime) {
		log_init(lconf.debug);
		if (!lconf.debug)
			if (daemon(1, 0))
				fatal("daemon");
	} else
		timeout = SETTIME_TIMEOUT * 1000;

	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1)
		fatal("socketpair");

	signal(SIGCHLD, sighdlr);
	/* fork child process */
	chld_pid = ntp_main(pipe_chld, &lconf, pw);

	setproctitle("[priv]");
	readfreq();

	signal(SIGTERM, sighdlr);
	signal(SIGINT, sighdlr);
	signal(SIGHUP, sighdlr);

	close(pipe_chld[1]);

	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
		fatal(NULL);
	imsg_init(ibuf, pipe_chld[0]);

	while (quit == 0) {
		pfd[PFD_PIPE].fd = ibuf->fd;
		pfd[PFD_PIPE].events = POLLIN;
		if (ibuf->w.queued)
			pfd[PFD_PIPE].events |= POLLOUT;

		if ((nfds = poll(pfd, 1, timeout)) == -1)
			if (errno != EINTR) {
				log_warn("poll error");
				quit = 1;
			}

		if (nfds == 0 && lconf.settime) {
			lconf.settime = 0;
			timeout = INFTIM;
			log_init(lconf.debug);
			log_debug("no reply received in time, skipping initial "
			    "time setting");
			if (!lconf.debug)
				if (daemon(1, 0))
					fatal("daemon");
		}

		if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
			if (msgbuf_write(&ibuf->w) < 0) {
				log_warn("pipe write error (to child)");
				quit = 1;
			}

		if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) {
			nfds--;
			if (dispatch_imsg(&lconf) == -1)
				quit = 1;
		}

		if (sigchld) {
			if (check_child(chld_pid, "child")) {
				quit = 1;
				chld_pid = 0;
			}
			sigchld = 0;
		}

	}

	signal(SIGCHLD, SIG_DFL);

	if (chld_pid)
		kill(chld_pid, SIGTERM);

	do {
		if ((pid = wait(NULL)) == -1 &&
		    errno != EINTR && errno != ECHILD)
			fatal("wait");
	} while (pid != -1 || (pid == -1 && errno == EINTR));

	msgbuf_clear(&ibuf->w);
	free(ibuf);
	log_info("Terminating");
	return (0);
}
Esempio n. 13
0
/* route decision engine */
pid_t
rde(struct ripd_conf *xconf, int pipe_parent2rde[2], int pipe_ripe2rde[2],
    int pipe_parent2ripe[2])
{
	struct event		 ev_sigint, ev_sigterm;
	struct passwd		*pw;
	struct redistribute	*r;
	pid_t			 pid;

	switch (pid = fork()) {
	case -1:
		fatal("cannot fork");
		/* NOTREACHED */
	case 0:
		break;
	default:
		return (pid);
	}

	rdeconf = xconf;

	if ((pw = getpwnam(RIPD_USER)) == NULL)
		fatal("getpwnam");

	if (chroot(pw->pw_dir) == -1)
		fatal("chroot");
	if (chdir("/") == -1)
		fatal("chdir(\"/\")");

	setproctitle("route decision engine");
	ripd_process = PROC_RDE_ENGINE;

	if (setgroups(1, &pw->pw_gid) ||
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
		fatal("can't drop privileges");

	event_init();

	/* setup signal handler */
	signal_set(&ev_sigint, SIGINT, rde_sig_handler, NULL);
	signal_set(&ev_sigterm, SIGTERM, rde_sig_handler, NULL);
	signal_add(&ev_sigint, NULL);
	signal_add(&ev_sigterm, NULL);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGHUP, SIG_IGN);

	/* setup pipes */
	close(pipe_ripe2rde[0]);
	close(pipe_parent2rde[0]);
	close(pipe_parent2ripe[0]);
	close(pipe_parent2ripe[1]);

	if ((iev_ripe = malloc(sizeof(struct imsgev))) == NULL ||
	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
		fatal(NULL);
	imsg_init(&iev_ripe->ibuf, pipe_ripe2rde[1]);
	iev_ripe->handler =  rde_dispatch_imsg;
	imsg_init(&iev_main->ibuf, pipe_parent2rde[1]);
	iev_main->handler = rde_dispatch_parent;

	/* setup event handler */
	iev_ripe->events = EV_READ;
	event_set(&iev_ripe->ev, iev_ripe->ibuf.fd, iev_ripe->events,
	    iev_ripe->handler, iev_ripe);
	event_add(&iev_ripe->ev, NULL);

	iev_main->events = EV_READ;
	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
	    iev_main->handler, iev_main);
	event_add(&iev_main->ev, NULL);
	rt_init();

	/* remove unneeded config stuff */
	while ((r = SIMPLEQ_FIRST(&rdeconf->redist_list)) != NULL) {
		SIMPLEQ_REMOVE_HEAD(&rdeconf->redist_list, entry);
		free(r);
	}

	event_dispatch();

	rde_shutdown();
	/* NOTREACHED */

	return (0);
}
Esempio n. 14
0
/**
 * Set proctitle. Append cmd in the protitle.
 * 
 * You should call proc_title_init() to init the proc_title before call
 * proc_title_set() to append cmd.
 * 
 * @param cmd
 */
void proc_title_set(const char *cmd)
{
	setproctitle("%s: %s", proc_title, cmd);
}
Esempio n. 15
0
int
main(int argc, char **argv)
{
	char	*s, *path, *label, **var, tmp[PATH_MAX];
	int	 opt, flags, keys;

#if defined(DEBUG) && defined(__OpenBSD__)
	malloc_options = (char *) "AFGJPX";
#endif

	setlocale(LC_TIME, "");
	tzset();

	if (**argv == '-')
		flags = CLIENT_LOGIN;
	else
		flags = 0;

	label = path = NULL;
	while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
		switch (opt) {
		case '2':
			flags |= CLIENT_256COLOURS;
			break;
		case 'c':
			free(shell_cmd);
			shell_cmd = xstrdup(optarg);
			break;
		case 'C':
			if (flags & CLIENT_CONTROL)
				flags |= CLIENT_CONTROLCONTROL;
			else
				flags |= CLIENT_CONTROL;
			break;
		case 'V':
			printf("%s %s\n", __progname, VERSION);
			exit(0);
		case 'f':
			set_cfg_file(optarg);
			break;
		case 'l':
			flags |= CLIENT_LOGIN;
			break;
		case 'L':
			free(label);
			label = xstrdup(optarg);
			break;
		case 'q':
			break;
		case 'S':
			free(path);
			path = xstrdup(optarg);
			break;
		case 'u':
			flags |= CLIENT_UTF8;
			break;
		case 'v':
			debug_level++;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (shell_cmd != NULL && argc != 0)
		usage();

	if (!(flags & CLIENT_UTF8)) {
		/*
		 * If the user has set whichever of LC_ALL, LC_CTYPE or LANG
		 * exist (in that order) to contain UTF-8, it is a safe
		 * assumption that either they are using a UTF-8 terminal, or
		 * if not they know that output from UTF-8-capable programs may
		 * be wrong.
		 */
		if ((s = getenv("LC_ALL")) == NULL || *s == '\0') {
			if ((s = getenv("LC_CTYPE")) == NULL || *s == '\0')
				s = getenv("LANG");
		}
		if (s != NULL && (strcasestr(s, "UTF-8") != NULL ||
		    strcasestr(s, "UTF8") != NULL))
			flags |= CLIENT_UTF8;
	}

	environ_init(&global_environ);
	for (var = environ; *var != NULL; var++)
		environ_put(&global_environ, *var);
	if (getcwd(tmp, sizeof tmp) != NULL)
		environ_set(&global_environ, "PWD", tmp);

	options_init(&global_options, NULL);
	options_table_populate_tree(server_options_table, &global_options);

	options_init(&global_s_options, NULL);
	options_table_populate_tree(session_options_table, &global_s_options);
	options_set_string(&global_s_options, "default-shell", "%s",
	    getshell());

	options_init(&global_w_options, NULL);
	options_table_populate_tree(window_options_table, &global_w_options);

	/* Enable UTF-8 if the first client is on UTF-8 terminal. */
	if (flags & CLIENT_UTF8) {
		options_set_number(&global_s_options, "status-utf8", 1);
		options_set_number(&global_s_options, "mouse-utf8", 1);
		options_set_number(&global_w_options, "utf8", 1);
	}

	/* Override keys to vi if VISUAL or EDITOR are set. */
	if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
		if (strrchr(s, '/') != NULL)
			s = strrchr(s, '/') + 1;
		if (strstr(s, "vi") != NULL)
			keys = MODEKEY_VI;
		else
			keys = MODEKEY_EMACS;
		options_set_number(&global_s_options, "status-keys", keys);
		options_set_number(&global_w_options, "mode-keys", keys);
	}

	/*
	 * Figure out the socket path. If specified on the command-line with -S
	 * or -L, use it, otherwise try $TMUX or assume -L default.
	 */
	if (path == NULL) {
		/* If no -L, use the environment. */
		if (label == NULL) {
			s = getenv("TMUX");
			if (s != NULL) {
				path = xstrdup(s);
				path[strcspn (path, ",")] = '\0';
				if (*path == '\0') {
					free(path);
					label = xstrdup("default");
				}
			} else
				label = xstrdup("default");
		}

		/* -L or default set. */
		if (label != NULL) {
			if ((path = makesocketpath(label)) == NULL) {
				fprintf(stderr, "can't create socket: %s\n",
				    strerror(errno));
				exit(1);
			}
		}
	}
	free(label);

	if (strlcpy(socket_path, path, sizeof socket_path) >=
	    sizeof socket_path) {
		fprintf(stderr, "socket path too long: %s\n", path);
		exit(1);
	}
	free(path);

#ifdef HAVE_SETPROCTITLE
	/* Set process title. */
	setproctitle("%s (%s)", __progname, socket_path);
#endif

	/* Pass control to the client. */
	exit(client_main(osdep_event_init(), argc, argv, flags));
}
Esempio n. 16
0
static void
tls_exec_client(const char *user, int startfd, const char *srcaddr,
    const char *dstaddr, const char *fingerprint, const char *defport,
    int timeout, int debuglevel)
{
	struct proto_conn *tcp;
	char *saddr, *daddr;
	SSL_CTX *sslctx;
	SSL *ssl;
	long ret;
	int sockfd, tcpfd;
	uint8_t connected;

	pjdlog_debug_set(debuglevel);
	pjdlog_prefix_set("[TLS sandbox] (client) ");
#ifdef HAVE_SETPROCTITLE
	setproctitle("[TLS sandbox] (client) ");
#endif
	proto_set("tcp:port", defport);

	sockfd = startfd;

	/* Change tls:// to tcp://. */
	if (srcaddr == NULL) {
		saddr = NULL;
	} else {
		saddr = strdup(srcaddr);
		if (saddr == NULL)
			pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
		bcopy("tcp://", saddr, 6);
	}
	daddr = strdup(dstaddr);
	if (daddr == NULL)
		pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
	bcopy("tcp://", daddr, 6);

	/* Establish TCP connection. */
	if (proto_connect(saddr, daddr, timeout, &tcp) == -1)
		exit(EX_TEMPFAIL);

	SSL_load_error_strings();
	SSL_library_init();

	/*
	 * TODO: On FreeBSD we could move this below sandbox() once libc and
	 *       libcrypto use sysctl kern.arandom to obtain random data
	 *       instead of /dev/urandom and friends.
	 */
	sslctx = SSL_CTX_new(TLSv1_client_method());
	if (sslctx == NULL)
		pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");

	if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0)
		pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client.");
	pjdlog_debug(1, "Privileges successfully dropped.");

	SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

	/* Load CA certs. */
	/* TODO */
	//SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL);

	ssl = SSL_new(sslctx);
	if (ssl == NULL)
		pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");

	tcpfd = proto_descriptor(tcp);

	block(tcpfd);

	if (SSL_set_fd(ssl, tcpfd) != 1)
		pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");

	ret = SSL_connect(ssl);
	ssl_check_error(ssl, (int)ret);

	nonblock(sockfd);
	nonblock(tcpfd);

	tls_certificate_verify(ssl, fingerprint);

	/*
	 * The following byte is send to make proto_connect_wait() to work.
	 */
	connected = 1;
	for (;;) {
		switch (send(sockfd, &connected, sizeof(connected), 0)) {
		case -1:
			if (errno == EINTR || errno == ENOBUFS)
				continue;
			if (errno == EAGAIN) {
				(void)wait_for_fd(sockfd, -1);
				continue;
			}
			pjdlog_exit(EX_TEMPFAIL, "send() failed");
		case 0:
			pjdlog_debug(1, "Connection terminated.");
			exit(0);
		case 1:
			break;
		}
		break;
	}

	tls_loop(sockfd, ssl);
}
Esempio n. 17
0
/*
 * Periodically test network connection. On signals, determine what
 * happened or what to do with child. Return as necessary for exit 
 * or restart of child.
 */
int
ssh_watch(int sock)
{
	int	r;
	int	val;
	static	int	secs_left;
	int	my_poll_time = first_poll_time;
	time_t	now;
	double	secs_to_shutdown;

#if defined(HAVE_SETPROCTITLE)
	setproctitle("parent of %d (%d)", 
	    (int)cchild, start_count);
#endif

	for (;;) {
		if (restart_ssh) {
			errlog(LOG_INFO, "signalled to kill and restart ssh");
			ssh_kill();
			return P_RESTART;
		}
		if ((val = sigsetjmp(jumpbuf, 1)) == 0) {

			errlog(LOG_DEBUG, "check on child %d", cchild);

			/* poll for expired child */
			r = ssh_wait(WNOHANG);
			if (r != P_CONTINUE) {
				errlog(LOG_DEBUG, 
				    "expired child, returning %d", r);
				return r;
			}

			secs_left = alarm(0);
			if (secs_left == 0)
				secs_left = my_poll_time;

			my_poll_time = poll_time;

			if (max_lifetime != 0) {
				time(&now);
				secs_to_shutdown = max_lifetime - difftime(now,pid_start_time);
				if (secs_to_shutdown < poll_time)
					secs_left = secs_to_shutdown;
			}

			errlog(LOG_DEBUG, 
			    "set alarm for %d secs", secs_left);

			alarm(secs_left);
			dolongjmp = 1;
			pause();

		} else {

			switch(val) {
			case SIGINT:
			case SIGTERM:
			case SIGQUIT:
			case SIGABRT:
				errlog(LOG_INFO, 
				    "received signal to exit (%d)", val);
				ssh_kill();
				return P_EXIT;
				break;
			case SIGALRM:
				if (exceeded_lifetime()) {
					ssh_kill();
					return P_EXIT;
				}

				if (writep && sock != -1 &&
				    !conn_test(sock, mhost, writep)) {
					errlog(LOG_INFO, 
					    "port down, restarting ssh");
					ssh_kill();
					return P_RESTART;
				}
#ifdef TOUCH_PIDFILE
				/*
				 * utimes() with a NULL time argument sets
				 * file access and modification times to
				 * the current time
				 */
				if (pid_file_name && 
				    utimes(pid_file_name, NULL) != 0) {
					errlog(LOG_ERR,
					    "could not touch pid file: %s",
					    strerror(errno));
				}
#endif
				break;
			default:
				break;
			}
		}
	}
}
Esempio n. 18
0
static int
tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
{
	struct tls_ctx *tlsctx;
	struct proto_conn *sock;
	pid_t pid;
	int error;

	PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0');
	PJDLOG_ASSERT(dstaddr != NULL);
	PJDLOG_ASSERT(timeout >= -1);
	PJDLOG_ASSERT(ctxp != NULL);

	if (strncmp(dstaddr, "tls://", 6) != 0)
		return (-1);
	if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0)
		return (-1);

	if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
		return (errno);

#if 0
	/*
	 * We use rfork() with the following flags to disable SIGCHLD
	 * delivery upon the sandbox process exit.
	 */
	pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0));
#else
	/*
	 * We don't use rfork() to be able to log information about sandbox
	 * process exiting.
	 */
	pid = fork();
#endif
	switch (pid) {
	case -1:
		/* Failure. */
		error = errno;
		proto_close(sock);
		return (error);
	case 0:
		/* Child. */
		pjdlog_prefix_set("[TLS sandbox] (client) ");
#ifdef HAVE_SETPROCTITLE
		setproctitle("[TLS sandbox] (client) ");
#endif
		tls_call_exec_client(sock, srcaddr, dstaddr, timeout);
		/* NOTREACHED */
	default:
		/* Parent. */
		tlsctx = calloc(1, sizeof(*tlsctx));
		if (tlsctx == NULL) {
			error = errno;
			proto_close(sock);
			(void)kill(pid, SIGKILL);
			return (error);
		}
		proto_send(sock, NULL, 0);
		tlsctx->tls_sock = sock;
		tlsctx->tls_tcp = NULL;
		tlsctx->tls_side = TLS_SIDE_CLIENT;
		tlsctx->tls_wait_called = false;
		tlsctx->tls_magic = TLS_CTX_MAGIC;
		if (timeout >= 0) {
			error = tls_connect_wait(tlsctx, timeout);
			if (error != 0) {
				(void)kill(pid, SIGKILL);
				tls_close(tlsctx);
				return (error);
			}
		}
		*ctxp = tlsctx;
		return (0);
	}
}
Esempio n. 19
0
/*ARGSUSED*/
static void
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;
#ifdef HAVE_LOGIN_CAP
	login_cap_t *lc;
	const char *from_host, *from_ip;

        from_host = get_canonical_hostname(options.use_dns);
        from_ip = get_remote_ipaddr();
#endif

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_cstring(NULL);
	service = packet_get_cstring(NULL);
	method = packet_get_cstring(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->user = xstrdup(user);
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("input_userauth_request: setting up authctxt for %s", user);
		} else {
			logit("input_userauth_request: invalid user %s", user);
			authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_INVALID_USER));
#endif
		}
#ifdef USE_PAM
		if (options.use_pam)
			PRIVSEP(start_pam(authctxt));
#endif
		setproctitle("%s%s", authctxt->valid ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
		userauth_banner();
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}

#ifdef HAVE_LOGIN_CAP
        if (authctxt->pw != NULL) {
                lc = login_getpwclass(authctxt->pw);
                if (lc == NULL)
                        lc = login_getclassbyname(NULL, authctxt->pw);
                if (!auth_hostok(lc, from_host, from_ip)) {
                        logit("Denied connection for %.200s from %.200s [%.200s].",
                            authctxt->pw->pw_name, from_host, from_ip);
                        packet_disconnect("Sorry, you are not allowed to connect.");
                }
                if (!auth_timeok(lc, time(NULL))) {
                        logit("LOGIN %.200s REFUSED (TIME) FROM %.200s",
                            authctxt->pw->pw_name, from_host);
                        packet_disconnect("Logins not available right now.");
                }
                login_close(lc);
                lc = NULL;
        }
#endif  /* HAVE_LOGIN_CAP */

	/* reset state */
	auth2_challenge_stop(authctxt);
#ifdef JPAKE
	auth2_jpake_stop(authctxt);
#endif

#ifdef GSSAPI
	/* XXX move to auth2_gssapi_stop() */
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

	authctxt->postponed = 0;

	/* try to authenticate user */
	m = authmethod_lookup(method);
	if (m != NULL && authctxt->failures < options.max_authtries) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(authctxt);
	}
	userauth_finish(authctxt, authenticated, method);

	xfree(service);
	xfree(user);
	xfree(method);
}
Esempio n. 20
0
static int
tls_accept(void *ctx, void **newctxp)
{
	struct tls_ctx *tlsctx = ctx;
	struct tls_ctx *newtlsctx;
	struct proto_conn *sock, *tcp;
	pid_t pid;
	int error;

	PJDLOG_ASSERT(tlsctx != NULL);
	PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
	PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN);

	if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
		return (errno);

	/* Accept TCP connection. */
	if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) {
		error = errno;
		proto_close(sock);
		return (error);
	}

	pid = fork();
	switch (pid) {
	case -1:
		/* Failure. */
		error = errno;
		proto_close(sock);
		return (error);
	case 0:
		/* Child. */
		pjdlog_prefix_set("[TLS sandbox] (server) ");
#ifdef HAVE_SETPROCTITLE
		setproctitle("[TLS sandbox] (server) ");
#endif
		/* Close listen socket. */
		proto_close(tlsctx->tls_tcp);
		tls_call_exec_server(sock, tcp);
		/* NOTREACHED */
		PJDLOG_ABORT("Unreachable.");
	default:
		/* Parent. */
		newtlsctx = calloc(1, sizeof(*tlsctx));
		if (newtlsctx == NULL) {
			error = errno;
			proto_close(sock);
			proto_close(tcp);
			(void)kill(pid, SIGKILL);
			return (error);
		}
		proto_local_address(tcp, newtlsctx->tls_laddr,
		    sizeof(newtlsctx->tls_laddr));
		PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0);
		bcopy("tls://", newtlsctx->tls_laddr, 6);
		*strrchr(newtlsctx->tls_laddr, ':') = '\0';
		proto_remote_address(tcp, newtlsctx->tls_raddr,
		    sizeof(newtlsctx->tls_raddr));
		PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0);
		bcopy("tls://", newtlsctx->tls_raddr, 6);
		*strrchr(newtlsctx->tls_raddr, ':') = '\0';
		proto_close(tcp);
		proto_recv(sock, NULL, 0);
		newtlsctx->tls_sock = sock;
		newtlsctx->tls_tcp = NULL;
		newtlsctx->tls_wait_called = true;
		newtlsctx->tls_side = TLS_SIDE_SERVER_WORK;
		newtlsctx->tls_magic = TLS_CTX_MAGIC;
		*newctxp = newtlsctx;
		return (0);
	}
}
Esempio n. 21
0
/*
 * Performs authentication of an incoming connection.  Session key has already
 * been exchanged and encryption is enabled.
 */
void
do_authentication(Authctxt *authctxt)
{
	u_int ulen;
	char *user, *style = NULL, *role = NULL;

	/* Get the name of the user that we wish to log in as. */
	packet_read_expect(SSH_CMSG_USER);

	/* Get the user name. */
	user = packet_get_cstring(&ulen);
	packet_check_eom();

	if ((role = strchr(user, '/')) != NULL)
		*role++ = '\0';

	if ((style = strchr(user, ':')) != NULL)
		*style++ = '\0';
	else if (role && (style = strchr(role, ':')) != NULL)
		*style++ = '\0';

	authctxt->user = user;
	authctxt->style = style;
	authctxt->role = role;

	/* Verify that the user is a valid user. */
	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
		authctxt->valid = 1;
	else {
		debug("do_authentication: invalid user %s", user);
		authctxt->pw = fakepw();
	}

	setproctitle("%s%s", authctxt->valid ? user : "******",
	    use_privsep ? " [net]" : "");

#ifdef USE_PAM
	if (options.use_pam)
		PRIVSEP(start_pam(authctxt));
#endif

	/*
	 * If we are not running as root, the user must have the same uid as
	 * the server.
	 */
#ifndef HAVE_CYGWIN
	if (!use_privsep && getuid() != 0 && authctxt->pw &&
	    authctxt->pw->pw_uid != getuid())
		packet_disconnect("Cannot change user when server not running as root.");
#endif

	/*
	 * Loop until the user has been authenticated or the connection is
	 * closed, do_authloop() returns only if authentication is successful
	 */
	do_authloop(authctxt);

	/* The user has been authenticated and accepted. */
	packet_start(SSH_SMSG_SUCCESS);
	packet_send();
	packet_write_wait();
}
Esempio n. 22
0
pid_t
proc_run(struct privsep *ps, struct privsep_proc *p,
    struct privsep_proc *procs, unsigned int nproc,
    void (*run)(struct privsep *, struct privsep_proc *, void *), void *arg)
{
	pid_t			 pid;
	struct passwd		*pw;
	const char		*root;
	struct control_sock	*rcs;
	unsigned int		 n;

	if (ps->ps_noaction)
		return (0);

	proc_open(ps, p, procs, nproc);

	/* Fork child handlers */
	switch (pid = fork()) {
	case -1:
		fatal("proc_run: cannot fork");
	case 0:
		log_procinit(p->p_title);

		/* Set the process group of the current process */
		setpgid(0, 0);
		break;
	default:
		return (pid);
	}

	pw = ps->ps_pw;

	if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
		if (control_init(ps, &ps->ps_csock) == -1)
			fatalx(__func__);
		TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry)
			if (control_init(ps, rcs) == -1)
				fatalx(__func__);
	}

	/* Change root directory */
	if (p->p_chroot != NULL)
		root = p->p_chroot;
	else
		root = pw->pw_dir;

	if (chroot(root) == -1)
		fatal("proc_run: chroot");
	if (chdir("/") == -1)
		fatal("proc_run: chdir(\"/\")");

	privsep_process = p->p_id;

	setproctitle("%s", p->p_title);

	if (setgroups(1, &pw->pw_gid) ||
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
		fatal("proc_run: cannot drop privileges");

	/* Fork child handlers */
	for (n = 1; n < ps->ps_instances[p->p_id]; n++) {
		if (fork() == 0) {
			ps->ps_instance = p->p_instance = n;
			break;
		}
	}

#ifdef DEBUG
	log_debug("%s: %s %d/%d, pid %d", __func__, p->p_title,
	    ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid());
#endif

	event_init();

	signal_set(&ps->ps_evsigint, SIGINT, proc_sig_handler, p);
	signal_set(&ps->ps_evsigterm, SIGTERM, proc_sig_handler, p);
	signal_set(&ps->ps_evsigchld, SIGCHLD, proc_sig_handler, p);
	signal_set(&ps->ps_evsighup, SIGHUP, proc_sig_handler, p);
	signal_set(&ps->ps_evsigpipe, SIGPIPE, proc_sig_handler, p);
	signal_set(&ps->ps_evsigusr1, SIGUSR1, proc_sig_handler, p);

	signal_add(&ps->ps_evsigint, NULL);
	signal_add(&ps->ps_evsigterm, NULL);
	signal_add(&ps->ps_evsigchld, NULL);
	signal_add(&ps->ps_evsighup, NULL);
	signal_add(&ps->ps_evsigpipe, NULL);
	signal_add(&ps->ps_evsigusr1, NULL);

	proc_listen(ps, procs, nproc);

	if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
		TAILQ_INIT(&ctl_conns);
		if (control_listen(&ps->ps_csock) == -1)
			fatalx(__func__);
		TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry)
			if (control_listen(rcs) == -1)
				fatalx(__func__);
	}
Esempio n. 23
0
static int start_page_server_req(int sk, CriuOpts *req, bool daemon_mode)
{
	int ret = -1, pid, start_pipe[2];
	ssize_t count;
	bool success = false;
	CriuResp resp = CRIU_RESP__INIT;
	CriuPageServerInfo ps = CRIU_PAGE_SERVER_INFO__INIT;
	struct ps_info info;

	if (pipe(start_pipe)) {
		pr_perror("No start pipe");
		goto out;
	}

	pid = fork();
	if (pid == 0) {
		close(start_pipe[0]);

		if (setup_opts_from_req(sk, req))
			goto out_ch;

		setproctitle("page-server --rpc --address %s --port %hu", opts.addr, opts.port);

		pr_debug("Starting page server\n");

		pid = cr_page_server(daemon_mode, false, start_pipe[1]);
		if (pid < 0)
			goto out_ch;

		if (daemon_mode) {
			info.pid = pid;
			info.port = opts.port;

			count = write(start_pipe[1], &info, sizeof(info));
			if (count != sizeof(info))
				goto out_ch;
		}

		ret = 0;
out_ch:
		if (daemon_mode && ret < 0 && pid > 0)
			kill(pid, SIGKILL);
		close(start_pipe[1]);
		exit(ret);
	}

	close(start_pipe[1]);

	if (daemon_mode) {
		if (waitpid(pid, &ret, 0) != pid) {
			pr_perror("Unable to wait %d", pid);
			goto out;
		}
		if (WIFEXITED(ret)) {
			if (WEXITSTATUS(ret)) {
				pr_err("Child exited with an error\n");
				goto out;
			}
		} else {
			pr_err("Child wasn't terminated normally\n");
			goto out;
		}
	}

	count = read(start_pipe[0], &info, sizeof(info));
	close(start_pipe[0]);
	if (count != sizeof(info))
		goto out;

	ps.pid = info.pid;
	ps.has_port = true;
	ps.port = info.port;

	success = true;
	ps.has_pid = true;
	resp.ps = &ps;

	pr_debug("Page server started\n");
out:
	resp.type = CRIU_REQ_TYPE__PAGE_SERVER;
	resp.success = success;
	return send_criu_msg(sk, &resp);
}
Esempio n. 24
0
int
main(int argc, char *argv[])
{
    ni_status status;
    ni_name myname = argv[0];
    int create = 0;
    int log_pri = LOG_NOTICE;
    ni_name dbsource_name = NULL;
    ni_name dbsource_addr = NULL;
    ni_name dbsource_tag = NULL;
    struct rlimit rlim;
    char *str;
    unsigned db_checksum;
    FILE *logf;
    int nctoken;

    logf = NULL;
    forcedIsRoot = 0;

    Argv = argv;	/* Save program and argument information for setproctitle */
    Argc = argc;

    argc--;
    argv++;
    while (argc > 0 && **argv == '-')
    {
        if (strcmp(*argv, "-d") == 0)
        {
            debug = 1;
            log_pri = LOG_DEBUG;
            if (argc < 2) logf = stderr;
            else
            {
                debug = atoi(argv[1]);
                argc -= 1;
                argv += 1;
            }
        }
        else if (strcmp(*argv, "-l") == 0)
        {
            if (argc < 2) usage(myname);
            else
            {
                log_pri = atoi(argv[1]);
                argc -= 1;
                argv += 1;
            }
        }
        else if (strcmp(*argv, "-n") == 0) forcedIsRoot = 1;
        else if (strcmp(*argv, "-s") == 0) standalone = 1;
        else if (strcmp(*argv, "-m") == 0) create++;
        else if (strcmp(*argv, "-c") == 0)
        {
            if (argc < 4) usage(myname);

            create++;
            dbsource_name = argv[1];
            dbsource_addr = argv[2];
            dbsource_tag = argv[3];
            argc -= 3;
            argv += 3;
        }
        else usage(myname);

        argc--;
        argv++;
    }

    if (argc != 1) usage(myname);

    if (debug == 0)
    {
        closeall();
        if (standalone == 1) daemon(1, 1);
    }

    db_tag = malloc(strlen(argv[0]) + 1);
    strcpy(db_tag, argv[0]);

    str = malloc(strlen("netinfod ") + strlen(db_tag) + 1);
    sprintf(str, "netinfod %s", db_tag);
    system_log_open(str, (LOG_NDELAY | LOG_PID), LOG_NETINFO, logf);
    free(str);
    system_log_set_max_priority(log_pri);

    system_log(LOG_DEBUG, "version %s (pid %d) - starting",
               _PROJECT_VERSION_, getpid());

    rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
    setrlimit(RLIMIT_CORE, &rlim);

    rlim.rlim_cur = rlim.rlim_max = FD_SETSIZE;
    setrlimit(RLIMIT_NOFILE, &rlim);

    umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

    srandom(gethostid() ^ time(NULL));

    readall_syslock = syslock_new(0);
    lockup_syslock= syslock_new(0);
    cleanupwait = CLEANUPWAIT;
    auth_count[GOOD] = 0;
    auth_count[BAD] = 0;
    auth_count[WGOOD] = 0;
    auth_count[WBAD] = 0;

    if (create)
    {
        if (dbsource_addr == NULL)
        {
            system_log(LOG_DEBUG, "creating master");
            status = dir_mastercreate(db_tag);
        }
        else
        {
            system_log(LOG_DEBUG, "creating clone");
            status = dir_clonecreate(db_tag, dbsource_name,
                                     dbsource_addr, dbsource_tag);
        }

        if (status != NI_OK)
        {
            system_log_close();
            exit(status);
        }
    }

    nctoken = -1;
    notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken);

    if (standalone == 0) signal(SIGTERM, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, (void *)catch_sighup);
    signal(SIGCHLD, (void *)readall_catcher);
    if (debug == 0)
    {
        signal(SIGINT, (void *)dblock_catcher);
        if (standalone == 0)
        {
            if (setsid() < 0) syslog(LOG_WARNING, "setsid failed: %m");
        }
    }

    writepid(db_tag);

    status = start_service(db_tag);
    if (status != NI_OK)
    {
        system_log(LOG_ERR, "start_service failed: %s - exiting", ni_error(status));
        system_log_close();
        exit(status);
    }

    setproctitle("netinfod %s (%s)", db_tag, i_am_clone ? "clone" : "master");

    if (i_am_clone)
    {
        system_log(LOG_DEBUG, "checking clone");
        cloneReadallResponseOK = get_clone_readall(db_ni);
        dir_clonecheck();
        if (get_sanitycheck(db_ni)) sanitycheck(db_tag);
        system_log(LOG_DEBUG, "finished clone check");
    }
    else
    {
        system_log(LOG_DEBUG, "setting up master server");
        promote_admins = get_promote_admins(db_ni);
        get_readall_info(db_ni, &max_readall_proxies, &strict_proxies);
        max_subthreads = get_max_subthreads(db_ni);
        update_latency_secs = get_update_latency(db_ni);

        /* Tracking readall proxy pids uses ObjC, so isolate it */
        initialize_readall_proxies(-1 == max_readall_proxies ?
                                   MAX_READALL_PROXIES : max_readall_proxies);

        system_log(LOG_DEBUG, "starting notify thread");
        (void) notify_start();
    }

    /* Shutdown gracefully after this point */
    if (standalone == 1) signal(SIGTERM, (void *)sig_shutdown);
    signal(SIGUSR1, (void *)sig_shutdown);

    system_log(LOG_DEBUG, "starting RPC service");

    ni_svc_run(_rpc_dtablesize() - (FD_SLOPSIZE + max_subthreads));

    system_log(LOG_DEBUG, "shutting down");

    /*
     * Tell the readall proxies to shut down
     */
    if (readall_proxies > 0)
    {
        system_log(LOG_INFO, "killing %d readall prox%s", readall_proxies,
                   1 == readall_proxies ? "y" : "ies");
        if (!kill_proxies())
            system_log(LOG_WARNING, "some readall proxies still running");
    }

    db_checksum = ni_getchecksum(db_ni);
    ni_shutdown(db_ni, db_checksum);
    system_log(LOG_INFO, "exiting; checksum %u", db_checksum);
    system_log_close();
    exit(0);
}
Esempio n. 25
0
void
set_proc_title(const char *format, ...)
{
	va_list ap;

#ifndef PS_USE_NONE

#ifdef PS_USE_CLOBBER_ARGV
	/* If ps_buffer is a pointer, it might still be null */
	if (!ps_buffer)
		return;
#endif

	/* Update ps_buffer to contain both fixed part and activity */
	va_start(ap, format);
	vsnprintf(ps_buffer + ps_buffer_fixed_size,
		  ps_buffer_size - ps_buffer_fixed_size, format, ap);
	va_end(ap);

	/* Transmit new setting to kernel, if necessary */
#ifdef PS_USE_SETPROCTITLE
	setproctitle("%s", ps_buffer);
#endif

#ifdef PS_USE_PSTAT
	{
		union pstun pst;

		pst.pst_command = ps_buffer;
		pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0);
	}
#endif /* PS_USE_PSTAT */

#ifdef PS_USE_PS_STRINGS
	PS_STRINGS->ps_nargvstr = 1;
	PS_STRINGS->ps_argvstr = ps_buffer;
#endif /* PS_USE_PS_STRINGS */

#ifdef PS_USE_CLOBBER_ARGV
	{
		int buflen;

		/* pad unused memory */
		buflen = strlen(ps_buffer);
		/* clobber remainder of old status string */
		if (last_status_len > buflen)
			memset(ps_buffer + buflen, PS_PADDING, last_status_len - buflen);
		last_status_len = buflen;
	}
#endif /* PS_USE_CLOBBER_ARGV */

#ifdef PS_USE_WIN32
	{
		/*
		 * Win32 does not support showing any changed arguments. To make it at
		 * all possible to track which backend is doing what, we create a
		 * named object that can be viewed with for example Process Explorer.
		 */
		static HANDLE ident_handle = INVALID_HANDLE_VALUE;
		char name[PS_BUFFER_SIZE + 32];

		if (ident_handle != INVALID_HANDLE_VALUE)
			CloseHandle(ident_handle);

		sprintf(name, "pgident(%d): %s", MyProcPid, ps_buffer);

		ident_handle = CreateEvent(NULL, TRUE, FALSE, name);
	}
#endif /* PS_USE_WIN32 */
#endif /* not PS_USE_NONE */
}
Esempio n. 26
0
void
vsf_sysutil_setproctitle_internal(const char* p_buf)
{
  setproctitle("%s", p_buf);
}
Esempio n. 27
0
int main (int argc, char **argv) {
    const char *progname   = NULL;
    const char *script     = NULL;
    int child_status       = 0;
    size_t i;

    array_init (&new_argv);

    set_sig_handler ();

    /* discard runawk's own ARGV[0] */
    --argc, ++argv;

    if (argc == 0) {
        usage ();
        return 30;
    }

    /* cwd */
    if (!getcwd (cwd, sizeof (cwd))) {
        perror ("runawk: getcwd (3) failed");
        die (32);
    }

    array_pushdup (&new_argv, NULL); /* will fill in progname later */

    if (AWK2) {
        array_pushdup (&new_argv, AWK2);
    }

    /* need to parse a run-together shebang line? */
    if (argc >= 2 && argv [0][0] == '-' && argv[1][0] != '-' && strchr(argv[0], ' ')) {
        shebang.argc = --argc;
        shebang.argv = ++argv;
        array_init (&shebang.array);
        char *p;
        char *token = argv[-1];
        for (p = token; *p; ) {
            if (*p == ' ') {
                *p++ = 0;
                array_pushdup(&shebang.array, token);
                token = p;
            } else {
                p++;
            }
        }
        if (p > token) {
            array_pushdup(&shebang.array, token);
        }
        argc = shebang.array.size;
        argv = (char **) shebang.array.contents;
    } else {
        shebang.argc = 0;
    }

    /* parse options manually */
    for (; argc && argv [0][0] == '-'; --argc, ++argv) {

        /* --help */
        if (!strcmp (argv [0], "--help")) {
            usage ();
            die (0);
        }

        /* --version */
        if (!strcmp (argv [0], "--version")) {
            version ();
            die (0);
        }

        /* --stdin */
        if (!strcmp (argv [0], "--stdin")) {
            add_stdin = 1;
            continue;
        }

        /* -F <FS>*/
        if (!strcmp (argv [0], "-F")) {
            if (argc == 1) {
                fprintf (stderr, "runawk: missing argument for -F option\n");
                die (39);
            }
            array_pushdup (&new_argv, "-F");
            array_pushdup (&new_argv, argv [1]);
            --argc;
            ++argv;
            continue;
        }

        /* -F<FS>*/
        if (!strncmp (argv [0], "-F", 2)) {
            array_pushdup (&new_argv, "-F");
            array_pushdup (&new_argv, argv [0]+2);
            continue;
        }

        /* -v|--assign <VAR=VALUE> */
        if (!strcmp (argv [0], "-v") || !strcmp (argv [0], "--assign")) {
            if (argc == 1) {
                fprintf (stderr, "runawk: missing argument for -v option\n");
                die (39);
            }
            array_pushdup (&new_argv, "-v");
            array_pushdup (&new_argv, argv [1]);
            --argc;
            ++argv;
            continue;
        }

        /* -v<VAR=VALUE> */
        if (!strncmp (argv [0], "-v", 2)) {
            array_pushdup (&new_argv, "-v");
            array_pushdup (&new_argv, argv [0]+2);
            continue;
        }

        /* -f|--file <FILE> */
        if (!strcmp (argv [0], "-f") || !strcmp (argv [0], "--file")) {
            if (argc == 1) {
                fprintf (stderr, "runawk: missing argument for -f option\n");
                die (39);
            }
            add_file (cwd, argv [1], 0);
            --argc;
            ++argv;
            continue;
        }

        /* -f<FILE> */
        if (!strncmp (argv [0], "-f", 2)) {
            add_file (cwd, argv [0]+2, 0);
            continue;
        }

        /* -e|--source <PROGRAM TEXT> */
        if (!strcmp (argv [0], "-e") || !strcmp (argv [0], "--source")) {
            if (argc == 1) {
                fprintf (stderr, "runawk: missing argument for -e option\n");
                die (39);
            }
            script = argv [1];
            --argc;
            ++argv;
            continue;
        }

        /* -e<PROGRAM TEXT> */
        if (!strncmp (argv [0], "-e", 2)) {
            script = argv [0]+2;
            continue;
        }

        if (!strcmp (argv [0], "--exec")) {
            if (shebang.argc) {
                if (script) {
                    fprintf (stderr, "runawk: --exec conflicts with --source\n");
                    die (39);
                }
                execing = 1;
                // add_file(cwd, shebang.argv [0], 1);
                // ++shebang.argv;
                // --shebang.argc;
                --argc;
                ++argv;
                break;
            }
            if (argc == 1) {
                fprintf (stderr, "runawk: missing argument for --exec option\n");
                die (39);
            }
            execing = 1;
            // add_file (cwd, argv [1], 1);
            --argc;
            ++argv;
            break;
        }

        /* -- */
        if (!strcmp (argv [0], "--")) {
            --argc;
            ++argv;
            break;
        }

        /* --unknown */
        if (!strncmp (argv [0], "--", 2)) {
            array_pushdup (&new_argv, argv [0]);
            continue;
        }
        
        /* -x etc */
        if (argv[0][1]) {
            fprintf (stderr, "runawk: unknown option -%c\n", *(argv [0]+1));
            die (1);
        }

        /* - */
        break;
    }

    if (shebang.argc) {
        if (argc) {
            fprintf (stderr, "runawk: can't parse shebang line: %s\n", argv[0]);
            die (1);
        }
        array_free (&shebang.array);
        argv = shebang.argv;
        argc = shebang.argc;
    }

    progname = interpreter;

    if (script) {
        add_buffer (script, strlen (script));
    } else {
        /* program_file */
        if (argc < 1) {
            usage ();
            die (30);
        }

        --argc;
        add_file (cwd, *argv, execing);
        progname = *argv;
#if 0
        setprogname (*argv);
        setproctitle (*argv);
#endif
        ++argv;
    }

    /* exec */
    new_argv.contents [0] = xstrdup (progname);

    if (files && !execing)
        array_pushdup (&new_argv, "--");

    for (i=0; i < (size_t) argc; ++i) {
        array_pushdup (&new_argv, argv [i]);
    }

    if (add_stdin) {
        array_pushdup (&new_argv, "/dev/stdin");
    }

    array_pushdup (&new_argv, NULL);

    awk_pid = fork ();
    switch (awk_pid) {
        case -1:
            perror ("runawk: fork(2) failed");
            die (42);
            break;

        case 0:
            /* child */
            execvp (interpreter, (char *const *) new_argv.contents);
            fprintf (stderr, "runawk: running '%s' failed: %s\n", interpreter, strerror (errno));
            exit (1);
            break;

        default:
            /* parent */
            waitpid (-1, &child_status, 0);

            array_free (&new_argv);

            if (killing_sig) {
                die (0);
            } else if (WIFSIGNALED (child_status)) {
                die (128 + WTERMSIG (child_status));
            } else if (WIFEXITED (child_status)) {
                die (WEXITSTATUS (child_status));
            } else {
                die (200);
            }
    }

    die (0);
    return 0; /* this should not happen but fixes gcc warning */
}
Esempio n. 28
0
pid_t
control(void)
{
	struct sockaddr_un	 sun;
	int			 fd;
	mode_t			 old_umask;
	pid_t			 pid;
	struct passwd		*pw;
	struct event		 ev_sigint;
	struct event		 ev_sigterm;
	struct peer		 peers [] = {
		{ PROC_SCHEDULER,	imsg_dispatch },
		{ PROC_QUEUE,		imsg_dispatch },
		{ PROC_SMTP,		imsg_dispatch },
		{ PROC_MFA,		imsg_dispatch },
		{ PROC_PARENT,		imsg_dispatch },
		{ PROC_LKA,		imsg_dispatch },
		{ PROC_MDA,		imsg_dispatch },
		{ PROC_MTA,		imsg_dispatch }
	};

	switch (pid = fork()) {
	case -1:
		fatal("control: cannot fork");
	case 0:
		break;
	default:
		return (pid);
	}

	purge_config(PURGE_EVERYTHING);

	pw = env->sc_pw;

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		fatal("control: socket");

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_UNIX;
	if (strlcpy(sun.sun_path, SMTPD_SOCKET,
	    sizeof(sun.sun_path)) >= sizeof(sun.sun_path))
		fatal("control: socket name too long");

	if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0)
		fatalx("control socket already listening");

	if (unlink(SMTPD_SOCKET) == -1)
		if (errno != ENOENT)
			fatal("control: cannot unlink socket");

	old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
	if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
		(void)umask(old_umask);
		fatal("control: bind");
	}
	(void)umask(old_umask);

	if (chmod(SMTPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) {
		(void)unlink(SMTPD_SOCKET);
		fatal("control: chmod");
	}

	session_socket_blockmode(fd, BM_NONBLOCK);
	control_state.fd = fd;

	stat_backend = env->sc_stat;
	stat_backend->init();

	if (chroot(pw->pw_dir) == -1)
		fatal("control: chroot");
	if (chdir("/") == -1)
		fatal("control: chdir(\"/\")");

	smtpd_process = PROC_CONTROL;
	setproctitle("%s", env->sc_title[smtpd_process]);

	if (setgroups(1, &pw->pw_gid) ||
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
		fatal("control: cannot drop privileges");

	imsg_callback = control_imsg;
	event_init();

	signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL);
	signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL);
	signal_add(&ev_sigint, NULL);
	signal_add(&ev_sigterm, NULL);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGHUP, SIG_IGN);

	TAILQ_INIT(&ctl_conns);

	config_pipes(peers, nitems(peers));
	config_peers(peers, nitems(peers));
	control_listen();

	if (event_dispatch() < 0)
		fatal("event_dispatch");
	control_shutdown();

	return (0);
}
Esempio n. 29
0
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");

	user = packet_get_cstring(NULL);
	service = packet_get_cstring(NULL);
	method = packet_get_cstring(NULL);
	debug("userauth-request for user %s service %s method %s", user, service, method);
	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

	if ((style = strchr(user, ':')) != NULL)
		*style++ = 0;

	if (authctxt->attempt++ == 0) {
		/* setup auth context */
		authctxt->pw = PRIVSEP(getpwnamallow(user));
		authctxt->user = xstrdup(user);
		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
			authctxt->valid = 1;
			debug2("input_userauth_request: setting up authctxt for %s", user);
		} else {
			logit("input_userauth_request: invalid user %s", user);
			authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
			PRIVSEP(audit_event(SSH_INVALID_USER));
#endif
		}
#ifdef USE_PAM
		if (options.use_pam)
			PRIVSEP(start_pam(authctxt));
#endif
		setproctitle("%s%s", authctxt->valid ? user : "******",
		    use_privsep ? " [net]" : "");
		authctxt->service = xstrdup(service);
		authctxt->style = style ? xstrdup(style) : NULL;
		if (use_privsep)
			mm_inform_authserv(service, style);
		userauth_banner();
		if (auth2_setup_methods_lists(authctxt) != 0)
			packet_disconnect("no authentication methods enabled");
	} else if (strcmp(user, authctxt->user) != 0 ||
	    strcmp(service, authctxt->service) != 0) {
		packet_disconnect("Change of username or service not allowed: "
		    "(%s,%s) -> (%s,%s)",
		    authctxt->user, authctxt->service, user, service);
	}
	/* reset state */
	auth2_challenge_stop(authctxt);

#ifdef GSSAPI
	/* XXX move to auth2_gssapi_stop() */
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

	authctxt->postponed = 0;
	authctxt->server_caused_failure = 0;

	/* try to authenticate user */
	m = authmethod_lookup(authctxt, method);
	if (m != NULL && authctxt->failures < options.max_authtries) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(authctxt);
	}
	userauth_finish(authctxt, authenticated, method, NULL);

	free(service);
	free(user);
	free(method);
	return 0;
}
Esempio n. 30
0
/*
 * Performs authentication of an incoming connection.  Session key has already
 * been exchanged and encryption is enabled.
 */
Authctxt *
do_authentication(void)
{
	Authctxt *authctxt;
	u_int ulen;
	char *user, *style = NULL;

	/* Get the name of the user that we wish to log in as. */
	packet_read_expect(SSH_CMSG_USER);

	/* Get the user name. */
	user = packet_get_string(&ulen);
	packet_check_eom();

	if ((style = strchr(user, ':')) != NULL)
		*style++ = '\0';

#ifdef KRB5
	/* XXX - SSH.com Kerberos v5 braindeath. */
	if ((datafellows & SSH_BUG_K5USER) &&
	    options.kerberos_authentication) {
		char *p;
		if ((p = strchr(user, '@')) != NULL)
			*p = '\0';
	}
#endif

	authctxt = authctxt_new();
	authctxt->user = user;
	authctxt->style = style;

	/* Verify that the user is a valid user. */
	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
		authctxt->valid = 1;
	else
		debug("do_authentication: illegal user %s", user);

	setproctitle("%s%s", authctxt->pw ? user : "******",
	    use_privsep ? " [net]" : "");

#ifdef USE_PAM
	PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user));
#endif

	/*
	 * If we are not running as root, the user must have the same uid as
	 * the server. (Unless you are running Windows)
	 */
#ifndef HAVE_CYGWIN
	if (!use_privsep && getuid() != 0 && authctxt->pw &&
	    authctxt->pw->pw_uid != getuid())
		packet_disconnect("Cannot change user when server not running as root.");
#endif

	/*
	 * Loop until the user has been authenticated or the connection is
	 * closed, do_authloop() returns only if authentication is successful
	 */
	do_authloop(authctxt);

	/* The user has been authenticated and accepted. */
	packet_start(SSH_SMSG_SUCCESS);
	packet_send();
	packet_write_wait();

	return (authctxt);
}