Esempio n. 1
0
static void
update(void)
{
	struct timespec ts;
	struct conf c;
	struct dbinfo dbi;
	unsigned int f, n;
	char buf[128];
	void *ss = &c.c_ss;

	if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
		(*lfun)(LOG_ERR, "clock_gettime failed (%m)"); 
		return;
	}

again:
	for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1;
	    f = 0, n++)
	{
		time_t when = c.c_duration + dbi.last;
		if (debug > 1) {
			char b1[64], b2[64];
			sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss);
			(*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d "
			    "last=%s " "now=%s", __func__, n, buf, dbi.count,
			    c.c_duration, fmttime(b1, sizeof(b1), dbi.last),
			    fmttime(b2, sizeof(b2), ts.tv_sec));
		}
		if (c.c_duration == -1 || when >= ts.tv_sec)
			continue;
		if (dbi.id[0]) {
			run_change("rem", &c, dbi.id, 0);
			sockaddr_snprintf(buf, sizeof(buf), "%a", ss);
			syslog(LOG_INFO, "released %s/%d:%d after %d seconds",
			    buf, c.c_lmask, c.c_port, c.c_duration);
		}
		state_del(state, &c);
		goto again;
	}
}
Esempio n. 2
0
static const char *
gethost(struct output *o)
{
	if (!numeric)
		return o->o_host;
	else {
		static char buf[512];
		buf[0] = '\0';
		(void)sockaddr_snprintf(buf, sizeof(buf), "%a",
		    (struct sockaddr *)&o->o_ss);
		return buf;
	}
}
Esempio n. 3
0
/*
 * apply the mask and the port to the address given
 */
static void
conf_addr_set(struct conf *c, const struct sockaddr_storage *ss)
{
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;
	in_port_t *port;
	void *addr;
	size_t alen;

	c->c_lmask = c->c_rmask;
	c->c_ss = *ss;

	if (c->c_ss.ss_family != c->c_family) {
		(*lfun)(LOG_CRIT, "%s: Internal error: mismatched family "
		    "%u != %u", __func__, c->c_ss.ss_family, c->c_family);
		abort();
	}

	switch (c->c_ss.ss_family) {
	case AF_INET:
		sin = (void *)&c->c_ss;
		port = &sin->sin_port;
		addr = &sin->sin_addr;
		alen = sizeof(sin->sin_addr);
		break;
	case AF_INET6:
		sin6 = (void *)&c->c_ss;
		port = &sin6->sin6_port;
		addr = &sin6->sin6_addr;
		alen = sizeof(sin6->sin6_addr);
		break;
	default:
		(*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
		    __func__, c->c_ss.ss_family);
		abort();
	}

	*port = htons((in_port_t)c->c_port);
	conf_apply_mask(addr, alen, c->c_lmask);
	if (c->c_lmask == FSTAR)
		c->c_lmask = (int)(alen * 8);
	if (debug) {
		char buf[128];
		sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&c->c_ss);
		(*lfun)(LOG_DEBUG, "Applied address %s", buf);
	}
}
Esempio n. 4
0
int
main(int argc, char *argv[])
{
	int sfd;
	int c;
	struct sockaddr_storage ss;
	const char *msg = "hello";
	const char *addr = "127.0.0.1";
	int type = SOCK_STREAM;
	in_port_t port = 6161;
	socklen_t slen;
	char buf[128];

	while ((c = getopt(argc, argv, "a:m:p:u")) != -1) {
		switch (c) {
		case 'a':
			addr = optarg;
			break;
		case 'm':
			msg = optarg;
			break;
		case 'p':
			port = (in_port_t)atoi(optarg);
			break;
		case 'u':
			type = SOCK_DGRAM;
			break;
		default:
			usage(c);
		}
	}

	getaddr(addr, port, &ss, &slen);

	if ((sfd = socket(AF_INET, type, 0)) == -1)
		err(EXIT_FAILURE, "socket");

	sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (const void *)&ss);
	printf("connecting to: %s\n", buf);
	if (connect(sfd, (const void *)&ss, slen) == -1)
		err(EXIT_FAILURE, "connect");

	size_t len = strlen(msg) + 1;
	if (write(sfd, msg, len) != (ssize_t)len)
		err(EXIT_FAILURE, "write");
	return 0;
}
Esempio n. 5
0
const char *
conf_print(char *buf, size_t len, const char *pref, const char *delim,
    const struct conf *c)
{
	char ha[128], hb[32], b[5][64];
	int sp;

#define N(n, v) conf_num(b[n], sizeof(b[n]), (v))

	switch (c->c_ss.ss_family) {
	case 0:
		snprintf(ha, sizeof(ha), "*");
		break;
	case AF_MAX:
		snprintf(ha, sizeof(ha), "%s", SIF_NAME(&c->c_ss));
		break;
	default:
		sockaddr_snprintf(ha, sizeof(ha), "%a", (const void *)&c->c_ss);
		break;
	}

	fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask);
	fmtport(ha, sizeof(ha), c->c_port);
	
	sp = *delim == '\t' ? 20 : -1;
	hb[0] = '\0';
	if (*delim)
		snprintf(buf, len, "%s%*.*s%s%s%s" "%s%s%s%s"
		    "%s%s" "%s%s%s",
		    pref, sp, sp, ha, delim, N(0, c->c_proto), delim,
		    N(1, c->c_family), delim, N(2, c->c_uid), delim,
		    conf_namemask(hb, sizeof(hb), c), delim,
		    N(3, c->c_nfail), delim, N(4, c->c_duration));
	else
		snprintf(buf, len, "%starget:%s, proto:%s, family:%s, "
		    "uid:%s, name:%s, nfail:%s, duration:%s", pref,
		    ha, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid),
		    conf_namemask(hb, sizeof(hb), c),
		    N(3, c->c_nfail), N(4, c->c_duration));
	return buf;
}
Esempio n. 6
0
static void
printaddrinfo(struct addrinfo *addrinfo)
{
	struct addrinfo *ai;
	char buf[1024];
	int n;
	struct protoent *protoent;

	for (ai = addrinfo; ai != NULL; ai = ai->ai_next) {
		/* Print the socket type.  */
		if ((ai->ai_socktype >= 0) &&
		    ((size_t)ai->ai_socktype < __arraycount(socket_types)) &&
		    (socket_types[ai->ai_socktype] != NULL))
			n = printf("%s", socket_types[ai->ai_socktype]);
		else
			n = printf("%d", ai->ai_socktype);
		if (n < 0)
			err(1, "printf");

		/* Print the address family.  */
		if ((ai->ai_family >= 0) &&
		    ((size_t)ai->ai_family < __arraycount(address_families)) &&
		    (address_families[ai->ai_family] != NULL))
			n = printf(" %s", address_families[ai->ai_family]);
		else
			n = printf(" %d", ai->ai_family);
		if (n < 0)
			err(1, "printf");

		/* Print the protocol number.  */
		protoent = getprotobynumber(ai->ai_protocol);
		if (protoent == NULL)
			n = printf(" %d", ai->ai_protocol);
		else
			n = printf(" %s", protoent->p_name);
		if (n < 0)
			err(1, "printf");

		/* Format the sockaddr.  */
		switch (ai->ai_family) {
		case AF_INET:
		case AF_INET6:
			n = sockaddr_snprintf(buf, sizeof(buf), " %a %p",
			    ai->ai_addr);
			break;

		default:
			n = sockaddr_snprintf(buf, sizeof(buf),
			    "%a %p %I %F %R %S", ai->ai_addr);
		}

		/*
		 * Check for sockaddr_snprintf failure.
		 *
		 * XXX sockaddr_snprintf's error reporting is botched
		 * -- man page says it sets errno, but if getnameinfo
		 * fails, errno is not where it reports the error...
		 */
		if (n < 0) {
			warnx("sockaddr_snprintf failed");
			continue;
		}
		if (sizeof(buf) <= (size_t)n)
			warnx("truncated sockaddr_snprintf output");

		/* Print the formatted sockaddr.  */
		if (printf("%s\n", buf) < 0)
			err(1, "printf");
	}
}
Esempio n. 7
0
static void
process(bl_t bl)
{
	struct sockaddr_storage rss;
	socklen_t rsl;
	char rbuf[BUFSIZ];
	bl_info_t *bi;
	struct conf c;
	struct dbinfo dbi;
	struct timespec ts;

	if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
		(*lfun)(LOG_ERR, "clock_gettime failed (%m)"); 
		return;
	}

	if ((bi = bl_recv(bl)) == NULL) {
		(*lfun)(LOG_ERR, "no message (%m)"); 
		return;
	}

	if (getremoteaddress(bi, &rss, &rsl) == -1)
		goto out;

	if (debug) {
		sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss);
		(*lfun)(LOG_DEBUG, "processing type=%d fd=%d remote=%s msg=%s"
		    " uid=%lu gid=%lu", bi->bi_type, bi->bi_fd, rbuf,
		    bi->bi_msg, (unsigned long)bi->bi_uid,
		    (unsigned long)bi->bi_gid);
	}

	if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) {
		(*lfun)(LOG_DEBUG, "no rule matched");
		goto out;
	}


	if (state_get(state, &c, &dbi) == -1)
		goto out;

	if (debug) {
		char b1[128], b2[128];
		(*lfun)(LOG_DEBUG, "%s: db state info for %s: count=%d/%d "
		    "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail,
		    fmttime(b1, sizeof(b1), dbi.last),
		    fmttime(b2, sizeof(b2), ts.tv_sec));
	}

	switch (bi->bi_type) {
	case BL_ADD:
		dbi.count++;
		dbi.last = ts.tv_sec;
		if (dbi.id[0]) {
			/*
			 * We should not be getting this since the rule
			 * should have blocked the address. A possible
			 * explanation is that someone removed that rule,
			 * and another would be that we got another attempt
			 * before we added the rule. In anycase, we remove
			 * and re-add the rule because we don't want to add
			 * it twice, because then we'd lose track of it.
			 */
			(*lfun)(LOG_DEBUG, "rule exists %s", dbi.id);
			(void)run_change("rem", &c, dbi.id, 0);
			dbi.id[0] = '\0';
		}
		if (c.c_nfail != -1 && dbi.count >= c.c_nfail) {
			int res = run_change("add", &c, dbi.id, sizeof(dbi.id));
			if (res == -1)
				goto out;
			sockaddr_snprintf(rbuf, sizeof(rbuf), "%a",
			    (void *)&rss);
			(*lfun)(LOG_INFO,
			    "blocked %s/%d:%d for %d seconds",
			    rbuf, c.c_lmask, c.c_port, c.c_duration);
				
		}
		break;
	case BL_DELETE:
		if (dbi.last == 0)
			goto out;
		dbi.last = 0;
		break;
	default:
		(*lfun)(LOG_ERR, "unknown message %d", bi->bi_type); 
	}
	if (state_put(state, &c, &dbi) == -1)
		goto out;
out:
	close(bi->bi_fd);
}
Esempio n. 8
0
int
main(int argc, char *argv[])
{
	struct group *gr;
	struct stat st;
	int ask, ch, cnt, fflag, hflag, pflag, sflag, quietlog, rootlogin, rval;
	uid_t uid, saved_uid;
	gid_t saved_gid, saved_gids[NGROUPS_MAX];
	int nsaved_gids;
#ifdef notdef
	char *domain;
#endif
	char *p, *ttyn;
	const char *pwprompt;
	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
	char localhost[MAXHOSTNAMELEN + 1];
	int need_chpass, require_chpass;
	int login_retries = DEFAULT_RETRIES, 
	    login_backoff = DEFAULT_BACKOFF;
	time_t pw_warntime = _PASSWORD_WARNDAYS * SECSPERDAY;
	char *loginname = NULL;
#ifdef KERBEROS5
	int Fflag;
	krb5_error_code kerror;
#endif
#if defined(KERBEROS5)
	int got_tickets = 0;
#endif
#ifdef LOGIN_CAP
	char *shell = NULL;
	login_cap_t *lc = NULL;
#endif

	tbuf[0] = '\0';
	rval = 0;
	pwprompt = NULL;
	nested = NULL;
	need_chpass = require_chpass = 0;

	(void)signal(SIGALRM, timedout);
	(void)alarm(timeout);
	(void)signal(SIGQUIT, SIG_IGN);
	(void)signal(SIGINT, SIG_IGN);
	(void)setpriority(PRIO_PROCESS, 0, 0);

	openlog("login", 0, LOG_AUTH);

	/*
	 * -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/utmpx and wtmp/wtmpx
	 * -a in addition to -h, a server may supply -a to pass the actual
	 *    server address.
	 * -s is used to force use of S/Key or equivalent.
	 */
	if (gethostname(localhost, sizeof(localhost)) < 0) {
		syslog(LOG_ERR, "couldn't get local hostname: %m");
		strcpy(hostname, "amnesiac");
	}
#ifdef notdef
	domain = strchr(localhost, '.');
#endif
	localhost[sizeof(localhost) - 1] = '\0';

	fflag = hflag = pflag = sflag = 0;
	have_ss = 0;
#ifdef KERBEROS5
	Fflag = 0;
	have_forward = 0;
#endif
	uid = getuid();
	while ((ch = getopt(argc, argv, "a:Ffh:ps")) != -1)
		switch (ch) {
		case 'a':
			if (uid)
				errx(EXIT_FAILURE, "-a option: %s", strerror(EPERM));
			decode_ss(optarg);
#ifdef notdef
			(void)sockaddr_snprintf(optarg,
			    sizeof(struct sockaddr_storage), "%a", (void *)&ss);
#endif
			break;
		case 'F':
#ifdef KERBEROS5
			Fflag = 1;
#endif
			/* FALLTHROUGH */
		case 'f':
			fflag = 1;
			break;
		case 'h':
			if (uid)
				errx(EXIT_FAILURE, "-h option: %s", strerror(EPERM));
			hflag = 1;
#ifdef notdef
			if (domain && (p = strchr(optarg, '.')) != NULL &&
			    strcasecmp(p, domain) == 0)
				*p = '\0';
#endif
			hostname = optarg;
			break;
		case 'p':
			pflag = 1;
			break;
		case 's':
			sflag = 1;
			break;
		default:
		case '?':
			usage();
			break;
		}

	setproctitle(NULL);
	argc -= optind;
	argv += optind;

	if (*argv) {
		username = loginname = *argv;
		ask = 0;
	} else
		ask = 1;

#ifdef F_CLOSEM
	(void)fcntl(3, F_CLOSEM, 0);
#else
	for (cnt = getdtablesize(); cnt > 2; cnt--)
		(void)close(cnt);
#endif

	ttyn = ttyname(STDIN_FILENO);
	if (ttyn == NULL || *ttyn == '\0') {
		(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
		ttyn = tname;
	}
	if ((tty = strstr(ttyn, "/pts/")) != NULL)
		++tty;
	else if ((tty = strrchr(ttyn, '/')) != NULL)
		++tty;
	else
		tty = ttyn;

	if (issetugid()) {
		nested = strdup(user_from_uid(getuid(), 0));
		if (nested == NULL) {
			syslog(LOG_ERR, "strdup: %m");
			sleepexit(EXIT_FAILURE);
		}
	}

#ifdef LOGIN_CAP
	/* Get "login-retries" and "login-backoff" from default class */
	if ((lc = login_getclass(NULL)) != NULL) {
		login_retries = (int)login_getcapnum(lc, "login-retries",
		    DEFAULT_RETRIES, DEFAULT_RETRIES);
		login_backoff = (int)login_getcapnum(lc, "login-backoff", 
		    DEFAULT_BACKOFF, DEFAULT_BACKOFF);
		login_close(lc);
		lc = NULL;
	}
#endif

#ifdef KERBEROS5
	kerror = krb5_init_context(&kcontext);
	if (kerror) {
		/*
		 * If Kerberos is not configured, that is, we are
		 * not using Kerberos, do not log the error message.
		 * However, if Kerberos is configured,  and the
		 * context init fails for some other reason, we need
		 * to issue a no tickets warning to the user when the
		 * login succeeds.
		 */
		if (kerror != ENXIO) {	/* XXX NetBSD-local Heimdal hack */
			syslog(LOG_NOTICE,
			    "%s when initializing Kerberos context",
			    error_message(kerror));
			krb5_configured = 1;
		}
		login_krb5_get_tickets = 0;
	}
#endif /* KERBEROS5 */

	for (cnt = 0;; ask = 1) {
#if defined(KERBEROS5)
		if (login_krb5_get_tickets)
			k5destroy();
#endif
		if (ask) {
			fflag = 0;
			loginname = getloginname();
		}
		rootlogin = 0;
#ifdef KERBEROS5
		if ((instance = strchr(loginname, '/')) != NULL)
			*instance++ = '\0';
		else
			instance = __UNCONST("");
#endif
		username = trimloginname(loginname);
		/*
		 * 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(tbuf, username)) {
			if (failures > (pwd ? 0 : 1))
				badlogin(tbuf);
			failures = 0;
		}
		(void)strlcpy(tbuf, username, sizeof(tbuf));

		pwd = getpwnam(username);

#ifdef LOGIN_CAP
		/*
		 * Establish the class now, before we might goto
		 * within the next block. pwd can be NULL since it
		 * falls back to the "default" class if it is.
		 */
		lc = login_getclass(pwd ? pwd->pw_class : NULL);
#endif
		/*
		 * if we have a valid account name, and it doesn't have a
		 * password, or the -f option was specified and the caller
		 * is root or the caller isn't changing their uid, don't
		 * authenticate.
		 */
		if (pwd) {
			if (pwd->pw_uid == 0)
				rootlogin = 1;

			if (fflag && (uid == 0 || uid == pwd->pw_uid)) {
				/* already authenticated */
#ifdef KERBEROS5
				if (login_krb5_get_tickets && Fflag)
					k5_read_creds(username);
#endif
				break;
			} else if (pwd->pw_passwd[0] == '\0') {
				/* pretend password okay */
				rval = 0;
				goto ttycheck;
			}
		}

		fflag = 0;

		(void)setpriority(PRIO_PROCESS, 0, -4);

#ifdef SKEY
		if (skey_haskey(username) == 0) {
			static char skprompt[80];
			const char *skinfo = skey_keyinfo(username);
				
			(void)snprintf(skprompt, sizeof(skprompt),
			    "Password [ %s ]:",
			    skinfo ? skinfo : "error getting challenge");
			pwprompt = skprompt;
		} else
#endif
			pwprompt = "Password:"******"Login incorrect or refused on this "
			    "terminal.\n");
			if (hostname)
				syslog(LOG_NOTICE,
				    "LOGIN %s REFUSED FROM %s ON TTY %s",
				    pwd->pw_name, hostname, tty);
			else
				syslog(LOG_NOTICE,
				    "LOGIN %s REFUSED ON TTY %s",
				     pwd->pw_name, tty);
			continue;
		}

		if (pwd && !rval)
			break;

		(void)printf("Login incorrect or refused on this "
		    "terminal.\n");
		failures++;
		cnt++;
		/*
		 * We allow login_retries tries, but after login_backoff
		 * we start backing off.  These default to 10 and 3
		 * respectively.
		 */
		if (cnt > login_backoff) {
			if (cnt >= login_retries) {
				badlogin(username);
				sleepexit(EXIT_FAILURE);
			}
			sleep((u_int)((cnt - login_backoff) * 5));
		}
	}

	/* committed to login -- turn off timeout */
	(void)alarm((u_int)0);

	endpwent();

	/* if user not super-user, check for disabled logins */
#ifdef LOGIN_CAP
	if (!login_getcapbool(lc, "ignorenologin", rootlogin))
		checknologin(login_getcapstr(lc, "nologin", NULL, NULL));
#else
	if (!rootlogin)
		checknologin(NULL);
#endif

#ifdef LOGIN_CAP
	quietlog = login_getcapbool(lc, "hushlogin", 0);
#else
	quietlog = 0;
#endif
	/* Temporarily give up special privileges so we can change */
	/* into NFS-mounted homes that are exported for non-root */
	/* access and have mode 7x0 */
	saved_uid = geteuid();
	saved_gid = getegid();
	nsaved_gids = getgroups(NGROUPS_MAX, saved_gids);
	
	(void)setegid(pwd->pw_gid);
	initgroups(username, pwd->pw_gid);
	(void)seteuid(pwd->pw_uid);
	
	if (chdir(pwd->pw_dir) < 0) {
#ifdef LOGIN_CAP
		if (login_getcapbool(lc, "requirehome", 0)) {
			(void)printf("Home directory %s required\n",
			    pwd->pw_dir);
			sleepexit(EXIT_FAILURE);
		}
#endif	
		(void)printf("No home directory %s!\n", pwd->pw_dir);
		if (chdir("/") == -1)
			exit(EXIT_FAILURE);
		pwd->pw_dir = __UNCONST("/");
		(void)printf("Logging in with home = \"/\".\n");
	}

	if (!quietlog)
		quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;

	/* regain special privileges */
	(void)seteuid(saved_uid);
	setgroups(nsaved_gids, saved_gids);
	(void)setegid(saved_gid);

#ifdef LOGIN_CAP
	pw_warntime = login_getcaptime(lc, "password-warn",
		_PASSWORD_WARNDAYS * SECSPERDAY,
		_PASSWORD_WARNDAYS * SECSPERDAY);
#endif

	(void)gettimeofday(&now, NULL);
	if (pwd->pw_expire) {
		if (now.tv_sec >= pwd->pw_expire) {
			(void)printf("Sorry -- your account has expired.\n");
			sleepexit(EXIT_FAILURE);
		} else if (pwd->pw_expire - now.tv_sec < pw_warntime && 
		    !quietlog)
			(void)printf("Warning: your account expires on %s",
			    ctime(&pwd->pw_expire));
	}
	if (pwd->pw_change) {
		if (pwd->pw_change == _PASSWORD_CHGNOW)
			need_chpass = 1;
		else if (now.tv_sec >= pwd->pw_change) {
			(void)printf("Sorry -- your password has expired.\n");
			sleepexit(EXIT_FAILURE);
		} else if (pwd->pw_change - now.tv_sec < pw_warntime && 
		    !quietlog)
			(void)printf("Warning: your password expires on %s",
			    ctime(&pwd->pw_change));

	}
	/* Nothing else left to fail -- really log in. */
	update_db(quietlog, rootlogin, fflag);

	(void)chown(ttyn, pwd->pw_uid,
	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);

	if (ttyaction(ttyn, "login", pwd->pw_name))
		(void)printf("Warning: ttyaction failed.\n");

#if defined(KERBEROS5)
	/* Fork so that we can call kdestroy */
	if (! login_krb5_retain_ccache && has_ccache)
		dofork();
#endif

	/* Destroy environment unless user has requested its preservation. */
	if (!pflag)
		environ = envinit;

#ifdef LOGIN_CAP
	if (nested == NULL && setusercontext(lc, pwd, pwd->pw_uid,
	    LOGIN_SETLOGIN) != 0) {
		syslog(LOG_ERR, "setusercontext failed");
		exit(EXIT_FAILURE);
	}
	if (setusercontext(lc, pwd, pwd->pw_uid,
	    (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETLOGIN))) != 0) {
		syslog(LOG_ERR, "setusercontext failed");
		exit(EXIT_FAILURE);
	}
#else
	(void)setgid(pwd->pw_gid);

	initgroups(username, pwd->pw_gid);
	
	if (nested == NULL && setlogin(pwd->pw_name) < 0)
		syslog(LOG_ERR, "setlogin() failure: %m");

	/* Discard permissions last so can't get killed and drop core. */
	if (rootlogin)
		(void)setuid(0);
	else
		(void)setuid(pwd->pw_uid);
#endif

	if (*pwd->pw_shell == '\0')
		pwd->pw_shell = __UNCONST(_PATH_BSHELL);
#ifdef LOGIN_CAP
	if ((shell = login_getcapstr(lc, "shell", NULL, NULL)) != NULL) {
		if ((shell = strdup(shell)) == NULL) {
			syslog(LOG_ERR, "Cannot alloc mem");
			sleepexit(EXIT_FAILURE);
		}
		pwd->pw_shell = shell;
	}
#endif
	
	(void)setenv("HOME", pwd->pw_dir, 1);
	(void)setenv("SHELL", pwd->pw_shell, 1);
	if (term[0] == '\0') {
		const char *tt = stypeof(tty);
#ifdef LOGIN_CAP
		if (tt == NULL)
			tt = login_getcapstr(lc, "term", NULL, NULL);
#endif
		/* unknown term -> "su" */
		(void)strlcpy(term, tt != NULL ? tt : "su", sizeof(term));
	}
	(void)setenv("TERM", term, 0);
	(void)setenv("LOGNAME", pwd->pw_name, 1);
	(void)setenv("USER", pwd->pw_name, 1);

#ifdef LOGIN_CAP
	setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH);
#else
	(void)setenv("PATH", _PATH_DEFPATH, 0);
#endif

#ifdef KERBEROS5
	if (krb5tkfile_env)
		(void)setenv("KRB5CCNAME", krb5tkfile_env, 1);
#endif

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

#if defined(KERBEROS5)
	if (KERBEROS_CONFIGURED && !quietlog && notickets == 1)
		(void)printf("Warning: no Kerberos tickets issued.\n");
#endif

	if (!quietlog) {
		const char *fname;
#ifdef LOGIN_CAP
		fname = login_getcapstr(lc, "copyright", NULL, NULL);
		if (fname != NULL && access(fname, F_OK) == 0)
			motd(fname);
		else
#endif
			(void)printf("%s", copyrightstr);

#ifdef LOGIN_CAP
		fname = login_getcapstr(lc, "welcome", NULL, NULL);
		if (fname == NULL || access(fname, F_OK) != 0)
#endif
			fname = _PATH_MOTDFILE;
		motd(fname);

		(void)snprintf(tbuf,
		    sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
		if (stat(tbuf, &st) == 0 && st.st_size != 0)
			(void)printf("You have %smail.\n",
			    (st.st_mtime > st.st_atime) ? "new " : "");
	}

#ifdef LOGIN_CAP
	login_close(lc);
#endif

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

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

	/* Wait to change password until we're unprivileged */
	if (need_chpass) {
		if (!require_chpass)
			(void)printf(
"Warning: your password has expired. Please change it as soon as possible.\n");
		else {
			int	status;

			(void)printf(
		    "Your password has expired. Please choose a new one.\n");
			switch (fork()) {
			case -1:
				warn("fork");
				sleepexit(EXIT_FAILURE);
			case 0:
				execl(_PATH_BINPASSWD, "passwd", NULL);
				_exit(EXIT_FAILURE);
			default:
				if (wait(&status) == -1 ||
				    WEXITSTATUS(status))
					sleepexit(EXIT_FAILURE);
			}
		}
	}

#ifdef KERBEROS5
	if (login_krb5_get_tickets)
		k5_write_creds();
#endif
	execlp(pwd->pw_shell, tbuf, NULL);
	err(EXIT_FAILURE, "%s", pwd->pw_shell);
}
Esempio n. 9
0
const struct conf *
conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
    struct conf *cr)
{
	int proto;
	socklen_t slen;
	struct sockaddr_storage lss;
	size_t i;
	char buf[BUFSIZ];

	memset(cr, 0, sizeof(*cr));
	slen = sizeof(lss);
	memset(&lss, 0, slen);
	if (getsockname(fd, (void *)&lss, &slen) == -1) {
		(*lfun)(LOG_ERR, "getsockname failed (%m)"); 
		return NULL;
	}

	slen = sizeof(proto);
	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) {
		(*lfun)(LOG_ERR, "getsockopt failed (%m)"); 
		return NULL;
	}

	if (debug) {
		sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&lss);
		(*lfun)(LOG_DEBUG, "listening socket: %s", buf);
	}

	switch (proto) {
	case SOCK_STREAM:
		cr->c_proto = IPPROTO_TCP;
		break;
	case SOCK_DGRAM:
		cr->c_proto = IPPROTO_UDP;
		break;
	default:
		(*lfun)(LOG_ERR, "unsupported protocol %d", proto); 
		return NULL;
	}

	switch (lss.ss_family) {
	case AF_INET:
		cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port);
		break;
	case AF_INET6:
		cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port);
		break;
	default:
		(*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family); 
		return NULL;
	}

	cr->c_ss = lss;
	cr->c_lmask = FSTAR;
	cr->c_uid = (int)uid;
	cr->c_family = lss.ss_family;
	cr->c_name[0] = '\0';
	cr->c_rmask = FSTAR;
	cr->c_nfail = FSTAR;
	cr->c_duration = FSTAR;

	if (debug)
		(*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
		    "look:\t", "", cr));

	/* match the local config */
	i = confset_match(&lconf, cr, conf_apply);
	if (i == lconf.cs_n) {
		if (debug)
			(*lfun)(LOG_DEBUG, "not found");
		return NULL;
	}

	conf_addr_set(cr, rss);
	/* match the remote config */
	confset_match(&rconf, cr, conf_merge);
	/* to apply the mask */
	conf_addr_set(cr, &cr->c_ss);

	return cr;
}
Esempio n. 10
0
void
update_db(int quietlog, int rootlogin, int fflag)
{
	struct sockaddr_storage ass;
	char assbuf[1024];
	socklen_t alen;
	const char *hname;
	int remote;

	hname = (hostname == NULL) ? "?" : hostname;
	if (getpeername(STDIN_FILENO, (struct sockaddr *)&ass, &alen) != -1) {
		(void)sockaddr_snprintf(assbuf,
		    sizeof(assbuf), "%A (%a)", (void *)&ass);
		if (have_ss) {
			char ssbuf[1024];
			(void)sockaddr_snprintf(ssbuf,
			    sizeof(ssbuf), "%A(%a)", (void *)&ss);
			 if (memcmp(&ass, &ss, alen) != 0)
				syslog(LOG_NOTICE,
				    "login %s on tty %s address mismatch "
				    "passed %s != actual %s", username, tty,
				    ssbuf, assbuf);
		} else
			ss = ass;
		remote = 1;
	} else if (have_ss) {
		(void)sockaddr_snprintf(assbuf,
		    sizeof(assbuf), "%A(%a)", (void *)&ss);
		remote = 1;
	} else if (hostname) {
		(void)snprintf(assbuf, sizeof(assbuf), "? ?");
		remote = 1;
	} else
		remote = 0;

	/* If fflag is on, assume caller/authenticator has logged root login. */
	if (rootlogin && fflag == 0) {
		if (remote)
			syslog(LOG_NOTICE, "ROOT LOGIN (%s) on tty %s from %s /"
			    " %s", username, tty, hname, assbuf);
		else
			syslog(LOG_NOTICE, "ROOT LOGIN (%s) on tty %s",
			    username, tty);
	} else if (nested != NULL) {
		if (remote)
			syslog(LOG_NOTICE, "%s to %s on tty %s from %s / "
			    "%s", nested, pwd->pw_name, tty, hname, assbuf);
		else
			syslog(LOG_NOTICE, "%s to %s on tty %s", nested,
			    pwd->pw_name, tty);
	} else {
		if (remote)
			syslog(LOG_NOTICE, "%s on tty %s from %s / %s",
			    pwd->pw_name, tty, hname, assbuf);
		else
			syslog(LOG_NOTICE, "%s on tty %s", 
			    pwd->pw_name, tty);
	}
	(void)gettimeofday(&now, NULL);
#ifdef SUPPORT_UTMPX
	doutmpx();
	dolastlogx(quietlog);
	quietlog = 1;
#endif	
#ifdef SUPPORT_UTMP
	doutmp();
	dolastlog(quietlog);
#endif
}