Ejemplo n.º 1
0
/*
 * XXX
 * Don't make static, used by lpd(8).
 *
 * Returns 0 if ok, -1 if not ok.
 */
int
__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser)
{
	struct sockaddr_in sin;

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_len = sizeof(struct sockaddr_in);
	memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
	return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
		luser, ruser);
}
Ejemplo n.º 2
0
/*
 * Returns 0 if ok, -1 if not ok.
 *
 * XXX obsolete API.
 */
int
__ivaliduser_af(FILE *hostf, const void *raddr, const char *luser,
		const char *ruser, int af, int len)
{
	struct sockaddr *sa = NULL;
	struct sockaddr_in *sin = NULL;
#ifdef INET6
	struct sockaddr_in6 *sin6 = NULL;
#endif
	struct sockaddr_storage ss;

	memset(&ss, 0, sizeof(ss));
	switch (af) {
	case AF_INET:
		if (len != sizeof(sin->sin_addr))
			return -1;
		sin = (struct sockaddr_in *)&ss;
		sin->sin_family = AF_INET;
		sin->sin_len = sizeof(struct sockaddr_in);
		memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr));
		break;
#ifdef INET6
	case AF_INET6:
		if (len != sizeof(sin6->sin6_addr))
			return -1;
		/* you will lose scope info */
		sin6 = (struct sockaddr_in6 *)&ss;
		sin6->sin6_family = AF_INET6;
		sin6->sin6_len = sizeof(struct sockaddr_in6);
		memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr));
		break;
#endif
	default:
		return -1;
	}

	sa = (struct sockaddr *)&ss;
	return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
}
Ejemplo n.º 3
0
int
iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
    const char *luser)
{
	struct sockaddr *sa;
	char *cp;
	struct stat sbuf;
	struct passwd pwstore, *pwd;
	FILE *hostf;
	uid_t uid;
	int first;
	char pbuf[PATH_MAX], pwbuf[_PW_BUF_LEN];

	sa = (struct sockaddr *)raddr;
	first = 1;
	hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "re");
again:
	if (hostf) {
		if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
			(void)fclose(hostf);
			return (0);
		}
		(void)fclose(hostf);
	}
	if (first == 1) {
		int len;

		first = 0;
		pwd = NULL;
		getpwnam_r(luser, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
		if (pwd == NULL)
			return (-1);
		len = snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
		if (len < 0 || len >= sizeof pbuf)
			return (-1);

		/*
		 * Change effective uid while opening .rhosts.  If root and
		 * reading an NFS mounted file system, can't read files that
		 * are protected read/write owner only.
		 */
		uid = geteuid();
		(void)seteuid(pwd->pw_uid);
		hostf = fopen(pbuf, "re");
		(void)seteuid(uid);

		if (hostf == NULL)
			return (-1);
		/*
		 * If not a regular file, or is owned by someone other than
		 * user or root or if writeable by anyone but the owner, quit.
		 */
		cp = NULL;
		if (lstat(pbuf, &sbuf) < 0)
			cp = ".rhosts lstat failed";
		else if (!S_ISREG(sbuf.st_mode))
			cp = ".rhosts not regular file";
		else if (fstat(fileno(hostf), &sbuf) < 0)
			cp = ".rhosts fstat failed";
		else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
			cp = "bad .rhosts owner";
		else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
			cp = ".rhosts writable by other than owner";
		/* If there were any problems, quit. */
		if (cp) {
			(void)fclose(hostf);
			return (-1);
		}
		goto again;
	}
	return (-1);
}
Ejemplo n.º 4
0
/*
 * AF independent extension of iruserok.
 *
 * Returns 0 if ok, -1 if not ok.
 */
int
iruserok_sa(const void *ra, int rlen, int superuser, const char *ruser,
	    const char *luser)
{
	char *cp;
	struct stat sbuf;
	struct passwd *pwd;
	FILE *hostf;
	uid_t uid;
	int first;
	char pbuf[MAXPATHLEN];
	const struct sockaddr *raddr;
	struct sockaddr_storage ss;

	/* avoid alignment issue */
	if (rlen > sizeof(ss)) 
		return(-1);
	memcpy(&ss, ra, rlen);
	raddr = (struct sockaddr *)&ss;

	first = 1;
	hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
again:
	if (hostf) {
		if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) {
			fclose(hostf);
			return (0);
		}
		fclose(hostf);
	}
	if (first == 1 && (__check_rhosts_file || superuser)) {
		first = 0;
		if ((pwd = getpwnam(luser)) == NULL)
			return (-1);
		strcpy(pbuf, pwd->pw_dir);
		strcat(pbuf, "/.rhosts");

		/*
		 * Change effective uid while opening .rhosts.  If root and
		 * reading an NFS mounted file system, can't read files that
		 * are protected read/write owner only.
		 */
		uid = geteuid();
		seteuid(pwd->pw_uid);
		hostf = fopen(pbuf, "r");
		seteuid(uid);

		if (hostf == NULL)
			return (-1);
		/*
		 * If not a regular file, or is owned by someone other than
		 * user or root or if writeable by anyone but the owner, quit.
		 */
		cp = NULL;
		if (lstat(pbuf, &sbuf) < 0)
			cp = ".rhosts lstat failed";
		else if (!S_ISREG(sbuf.st_mode))
			cp = ".rhosts not regular file";
		else if (_fstat(fileno(hostf), &sbuf) < 0)
			cp = ".rhosts fstat failed";
		else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
			cp = "bad .rhosts owner";
		else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
			cp = ".rhosts writeable by other than owner";
		/* If there were any problems, quit. */
		if (cp) {
			__rcmd_errstr = cp;
			fclose(hostf);
			return (-1);
		}
		goto again;
	}
	return (-1);
}
Ejemplo n.º 5
0
/*
 * Check to see if the host connecting to this host has access to any
 * lpd services on this host.
 */
static void
chkhost(struct sockaddr *f, int ch_opts)
{
	struct addrinfo hints, *res, *r;
	register FILE *hostf;
	char hostbuf[NI_MAXHOST], ip[NI_MAXHOST];
	char serv[NI_MAXSERV];
	char *syserr, *usererr;
	int error, errsav, fpass, good, wantsl;

	wantsl = 0;
	if (ch_opts & LPD_LOGCONNERR)
		wantsl = 1;			/* also syslog the errors */

	from_host = ".na.";

	/* Need real hostname for temporary filenames */
	error = getnameinfo(f, f->sa_len, hostbuf, sizeof(hostbuf), NULL, 0,
	    NI_NAMEREQD);
	if (error) {
		errsav = error;
		error = getnameinfo(f, f->sa_len, hostbuf, sizeof(hostbuf),
		    NULL, 0, NI_NUMERICHOST);
		if (error) {
			asprintf(&syserr,
			    "can not determine hostname for remote host (%d,%d)",
			    errsav, error);
			asprintf(&usererr,
			    "Host name for your address is not known");
			fhosterr(ch_opts, syserr, usererr);
			/* NOTREACHED */
		}
		asprintf(&syserr,
		    "Host name for remote host (%s) not known (%d)",
		    hostbuf, errsav);
		asprintf(&usererr,
		    "Host name for your address (%s) is not known",
		    hostbuf);
		fhosterr(ch_opts, syserr, usererr);
		/* NOTREACHED */
	}

	strlcpy(frombuf, hostbuf, sizeof(frombuf));
	from_host = frombuf;
	ch_opts |= LPD_ADDFROMLINE;

	/* Need address in stringform for comparison (no DNS lookup here) */
	error = getnameinfo(f, f->sa_len, hostbuf, sizeof(hostbuf), NULL, 0,
	    NI_NUMERICHOST);
	if (error) {
		asprintf(&syserr, "Cannot print IP address (error %d)",
		    error);
		asprintf(&usererr, "Cannot print IP address for your host");
		fhosterr(ch_opts, syserr, usererr);
		/* NOTREACHED */
	}
	from_ip = strdup(hostbuf);

	/* Reject numeric addresses */
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = family;
	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
	hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
	if (getaddrinfo(from_host, NULL, &hints, &res) == 0) {
		freeaddrinfo(res);
		/* This syslog message already includes from_host */
		ch_opts &= ~LPD_ADDFROMLINE;
		asprintf(&syserr, "reverse lookup results in non-FQDN %s",
		    from_host);
		/* same message to both syslog and remote user */
		fhosterr(ch_opts, syserr, syserr);
		/* NOTREACHED */
	}

	/* Check for spoof, ala rlogind */
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = family;
	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
	error = getaddrinfo(from_host, NULL, &hints, &res);
	if (error) {
		asprintf(&syserr, "dns lookup for address %s failed: %s",
		    from_ip, gai_strerror(error));
		asprintf(&usererr, "hostname for your address (%s) unknown: %s",
		    from_ip, gai_strerror(error));
		fhosterr(ch_opts, syserr, usererr);
		/* NOTREACHED */
	}
	good = 0;
	for (r = res; good == 0 && r; r = r->ai_next) {
		error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip),
		    NULL, 0, NI_NUMERICHOST);
		if (!error && !strcmp(from_ip, ip))
			good = 1;
	}
	if (res)
		freeaddrinfo(res);
	if (good == 0) {
		asprintf(&syserr, "address for remote host (%s) not matched",
		    from_ip);
		asprintf(&usererr,
		    "address for your hostname (%s) not matched", from_ip);
		fhosterr(ch_opts, syserr, usererr);
		/* NOTREACHED */
	}

	fpass = 1;
	hostf = fopen(_PATH_HOSTSEQUIV, "r");
again:
	if (hostf) {
		if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
			(void) fclose(hostf);
			goto foundhost;
		}
		(void) fclose(hostf);
	}
	if (fpass == 1) {
		fpass = 2;
		hostf = fopen(_PATH_HOSTSLPD, "r");
		goto again;
	}
	/* This syslog message already includes from_host */
	ch_opts &= ~LPD_ADDFROMLINE;
	asprintf(&syserr, "refused connection from %s, sip=%s", from_host,
	    from_ip);
	asprintf(&usererr,
	    "Print-services are not available to your host (%s).", from_host);
	fhosterr(ch_opts, syserr, usererr);
	/* NOTREACHED */

foundhost:
	if (ch_opts & LPD_NOPORTCHK)
		return;			/* skip the reserved-port check */

	error = getnameinfo(f, f->sa_len, NULL, 0, serv, sizeof(serv),
	    NI_NUMERICSERV);
	if (error) {
		/* same message to both syslog and remote user */
		asprintf(&syserr, "malformed from-address (%d)", error);
		fhosterr(ch_opts, syserr, syserr);
		/* NOTREACHED */
	}

	if (atoi(serv) >= IPPORT_RESERVED) {
		/* same message to both syslog and remote user */
		asprintf(&syserr, "connected from invalid port (%s)", serv);
		fhosterr(ch_opts, syserr, syserr);
		/* NOTREACHED */
	}
}