Ejemplo n.º 1
0
/*
 * Create the client des authentication object. Obsoleted by
 * authdes_seccreate().
 */
AUTH *
authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr,
	des_block *ckey)
{
	char *hostname = NULL;

	if (syncaddr) {
		/*
		 * Change addr to hostname, because that is the way
		 * new interface takes it.
		 */
		struct netconfig *nconf;
		struct netbuf nb_syncaddr;
		struct nd_hostservlist *hlist;
		AUTH *nauth;
		int fd;
		struct t_info tinfo;

		if ((nconf = __rpc_getconfip("udp")) == NULL &&
		    (nconf = __rpc_getconfip("tcp")) == NULL)
			goto fallback;

		/* Transform sockaddr_in to netbuf */
		if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) {
			(void) freenetconfigent(nconf);
			goto fallback;
		}
		(void) t_close(fd);
		nb_syncaddr.maxlen = nb_syncaddr.len =
			__rpc_get_a_size(tinfo.addr);
		nb_syncaddr.buf = (char *)syncaddr;
		if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) {
			(void) freenetconfigent(nconf);
			goto fallback;
		}
		if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs)
			hostname = hlist->h_hostservs->h_host;
		nauth = authdes_seccreate(servername, window, hostname, ckey);
		(void) netdir_free((char *)hlist, ND_HOSTSERVLIST);
		(void) freenetconfigent(nconf);
		return (nauth);
	}
fallback:
	return (authdes_seccreate(servername, window, hostname, ckey));
}
Ejemplo n.º 2
0
/*
 * __yp_all_cflookup() is a variant of the yp_all() code,
 * which adds a 'hardlookup' parameter. This parameter is passed
 * to __yp_dobind_cflookup(), and determines whether the server
 * binding attempt is hard (try forever) of soft (retry a compiled-
 * in number of times).
 */
int
__yp_all_cflookup(char *domain, char *map, struct ypall_callback *callback,
								int hardlookup)
{
	size_t domlen;
	size_t maplen;
	struct ypreq_nokey req;
	int reason;
	struct dom_binding *pdomb;
	enum clnt_stat s;
	CLIENT *allc;
	char server_name[MAXHOSTNAMELEN];
	char errbuf[BUFSIZ];

	if ((map == NULL) || (domain == NULL))
		return (YPERR_BADARGS);

	domlen = strlen(domain);
	maplen = strlen(map);

	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
	    (maplen == 0) || (maplen > YPMAXMAP) ||
	    (callback == NULL))
		return (YPERR_BADARGS);

	if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
		return (reason);

	if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) {
		__yp_rel_binding(pdomb);
		return (YPERR_VERS);
	}
	(void) mutex_lock(&pdomb->server_name_lock);
	if (!pdomb->dom_binding->ypbind_servername) {
		(void) mutex_unlock(&pdomb->server_name_lock);
		__yp_rel_binding(pdomb);
		syslog(LOG_ERR, "yp_all: failed to get server's name\n");
		return (YPERR_RPC);
	}
	(void) strcpy(server_name, pdomb->dom_binding->ypbind_servername);
	(void) mutex_unlock(&pdomb->server_name_lock);
	if (strcmp(server_name, nullstring) == 0) {
		/*
		 * This is the case where ypbind is running in broadcast mode,
		 * we have to do the jugglery to get the
		 * ypserv's address on COTS transport based
		 * on the CLTS address ypbind gave us !
		 */

		struct nd_hostservlist *nhs;

		if (netdir_getbyaddr(pdomb->dom_binding->ypbind_nconf,
			&nhs, pdomb->dom_binding->ypbind_svcaddr) != ND_OK) {
			syslog(LOG_ERR,
				"yp_all: failed to get server's name\n");
			__yp_rel_binding(pdomb);
			return (YPERR_RPC);
		}
		/* check server name again, some other thread may have set it */
		(void) mutex_lock(&pdomb->server_name_lock);
		if (strcmp(pdomb->dom_binding->ypbind_servername,
					nullstring) == 0) {
			pdomb->dom_binding->ypbind_servername =
				(char *)strdup(nhs->h_hostservs->h_host);
		}
		(void) strcpy(server_name,
		    pdomb->dom_binding->ypbind_servername);
		(void) mutex_unlock(&pdomb->server_name_lock);
		netdir_free((char *)nhs, ND_HOSTSERVLIST);
	}
	__yp_rel_binding(pdomb);
	if ((allc = clnt_create(server_name, YPPROG,
		YPVERS, "circuit_n")) == NULL) {
			(void) snprintf(errbuf, BUFSIZ, "yp_all \
- transport level create failure for domain %s / map %s", domain, map);
			syslog(LOG_ERR, "%s", clnt_spcreateerror(errbuf));
			return (YPERR_RPC);
	}
Ejemplo n.º 3
0
/*
 * Called to read and interpret the event on a connectionless descriptor.
 * Returns 0 if successful, or a UNIX error code if failure.
 */
static int
do_poll_clts_action(int fd, int conn_index)
{
	int error;
	int ret;
	int flags;
	struct netconfig *nconf = &conn_polled[conn_index].nc;
	static struct t_unitdata *unitdata = NULL;
	static struct t_uderr *uderr = NULL;
	static int oldfd = -1;
	struct nd_hostservlist *host = NULL;
	struct strbuf ctl[1], data[1];
	/*
	 * We just need to have some space to consume the
	 * message in the event we can't use the TLI interface to do the
	 * job.
	 *
	 * We flush the message using getmsg(). For the control part
	 * we allocate enough for any TPI header plus 32 bytes for address
	 * and options. For the data part, there is nothing magic about
	 * the size of the array, but 256 bytes is probably better than
	 * 1 byte, and we don't expect any data portion anyway.
	 *
	 * If the array sizes are too small, we handle this because getmsg()
	 * (called to consume the message) will return MOREDATA|MORECTL.
	 * Thus we just call getmsg() until it's read the message.
	 */
	char ctlbuf[sizeof (union T_primitives) + 32];
	char databuf[256];

	/*
	 * If this is the same descriptor as the last time
	 * do_poll_clts_action was called, we can save some
	 * de-allocation and allocation.
	 */
	if (oldfd != fd) {
		oldfd = fd;

		if (unitdata) {
			(void) t_free((char *)unitdata, T_UNITDATA);
			unitdata = NULL;
		}
		if (uderr) {
			(void) t_free((char *)uderr, T_UDERROR);
			uderr = NULL;
		}
	}

	/*
	 * Allocate a unitdata structure for receiving the event.
	 */
	if (unitdata == NULL) {
		/* LINTED pointer alignment */
		unitdata = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ALL);
		if (unitdata == NULL) {
			if (t_errno == TSYSERR) {
				/*
				 * Save the error code across
				 * syslog(), just in case
				 * syslog() gets its own error
				 * and therefore overwrites errno.
				 */
				error = errno;
				(void) syslog(LOG_ERR,
	"t_alloc(file descriptor %d/transport %s, T_UNITDATA) failed: %m",
				    fd, nconf->nc_proto);
				return (error);
			}
			(void) syslog(LOG_ERR,
"t_alloc(file descriptor %d/transport %s, T_UNITDATA) failed TLI error %d",
			    fd, nconf->nc_proto, t_errno);
			goto flush_it;
		}
	}

try_again:
	flags = 0;

	/*
	 * The idea is we wait for T_UNITDATA_IND's. Of course,
	 * we don't get any, because rpcmod filters them out.
	 * However, we need to call t_rcvudata() to let TLI
	 * tell us we have a T_UDERROR_IND.
	 *
	 * algorithm is:
	 * 	t_rcvudata(), expecting TLOOK.
	 * 	t_look(), expecting T_UDERR.
	 * 	t_rcvuderr(), expecting success (0).
	 * 	expand destination address into ASCII,
	 *	and dump it.
	 */

	ret = t_rcvudata(fd, unitdata, &flags);
	if (ret == 0 || t_errno == TBUFOVFLW) {
		(void) syslog(LOG_WARNING,
"t_rcvudata(file descriptor %d/transport %s) got unexpected data, %d bytes",
		    fd, nconf->nc_proto, unitdata->udata.len);

		/*
		 * Even though we don't expect any data, in case we do,
		 * keep reading until there is no more.
		 */
		if (flags & T_MORE)
			goto try_again;

		return (0);
	}

	switch (t_errno) {
	case TNODATA:
		return (0);
	case TSYSERR:
		/*
		 * System errors are returned to caller.
		 * Save the error code across
		 * syslog(), just in case
		 * syslog() gets its own error
		 * and therefore overwrites errno.
		 */
		error = errno;
		(void) syslog(LOG_ERR,
		    "t_rcvudata(file descriptor %d/transport %s) %m",
		    fd, nconf->nc_proto);
		return (error);
	case TLOOK:
		break;
	default:
		(void) syslog(LOG_ERR,
		"t_rcvudata(file descriptor %d/transport %s) TLI error %d",
		    fd, nconf->nc_proto, t_errno);
		goto flush_it;
	}

	ret = t_look(fd);
	switch (ret) {
	case 0:
		return (0);
	case -1:
		/*
		 * System errors are returned to caller.
		 */
		if (t_errno == TSYSERR) {
			/*
			 * Save the error code across
			 * syslog(), just in case
			 * syslog() gets its own error
			 * and therefore overwrites errno.
			 */
			error = errno;
			(void) syslog(LOG_ERR,
			    "t_look(file descriptor %d/transport %s) %m",
			    fd, nconf->nc_proto);
			return (error);
		}
		(void) syslog(LOG_ERR,
		    "t_look(file descriptor %d/transport %s) TLI error %d",
		    fd, nconf->nc_proto, t_errno);
		goto flush_it;
	case T_UDERR:
		break;
	default:
		(void) syslog(LOG_WARNING,
	"t_look(file descriptor %d/transport %s) returned %d not T_UDERR (%d)",
		    fd, nconf->nc_proto, ret, T_UDERR);
	}

	if (uderr == NULL) {
		/* LINTED pointer alignment */
		uderr = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ALL);
		if (uderr == NULL) {
			if (t_errno == TSYSERR) {
				/*
				 * Save the error code across
				 * syslog(), just in case
				 * syslog() gets its own error
				 * and therefore overwrites errno.
				 */
				error = errno;
				(void) syslog(LOG_ERR,
	"t_alloc(file descriptor %d/transport %s, T_UDERROR) failed: %m",
				    fd, nconf->nc_proto);
				return (error);
			}
			(void) syslog(LOG_ERR,
"t_alloc(file descriptor %d/transport %s, T_UDERROR) failed TLI error: %d",
			    fd, nconf->nc_proto, t_errno);
			goto flush_it;
		}
	}

	ret = t_rcvuderr(fd, uderr);
	if (ret == 0) {

		/*
		 * Save the datagram error in errno, so that the
		 * %m argument to syslog picks up the error string.
		 */
		errno = uderr->error;

		/*
		 * Log the datagram error, then log the host that
		 * probably triggerred. Cannot log both in the
		 * same transaction because of packet size limitations
		 * in /dev/log.
		 */
		(void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
"NFS response over <file descriptor %d/transport %s> generated error: %m",
		    fd, nconf->nc_proto);

		/*
		 * Try to map the client's address back to a
		 * name.
		 */
		ret = netdir_getbyaddr(nconf, &host, &uderr->addr);
		if (ret != -1 && host && host->h_cnt > 0 &&
		    host->h_hostservs) {
		(void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
"Bad NFS response was sent to client with host name: %s; service port: %s",
		    host->h_hostservs->h_host,
		    host->h_hostservs->h_serv);
		} else {
			int i, j;
			char *buf;
			char *hex = "0123456789abcdef";

			/*
			 * Mapping failed, print the whole thing
			 * in ASCII hex.
			 */
			buf = (char *)malloc(uderr->addr.len * 2 + 1);
			for (i = 0, j = 0; i < uderr->addr.len; i++, j += 2) {
				buf[j] = hex[((uderr->addr.buf[i]) >> 4) & 0xf];
				buf[j+1] = hex[uderr->addr.buf[i] & 0xf];
			}
			buf[j] = '\0';
		(void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
	"Bad NFS response was sent to client with transport address: 0x%s",
		    buf);
			free((void *)buf);
		}

		if (ret == 0 && host != NULL)
			netdir_free((void *)host, ND_HOSTSERVLIST);
		return (0);
	}
Ejemplo n.º 4
0
static void
nfsauth_access(auth_req *argp, auth_res *result)
{
	struct netconfig *nconf;
	struct nd_hostservlist *clnames = NULL;
	struct netbuf nbuf;
	struct share *sh;
	char tmp[MAXIPADDRLEN];
	char *host = NULL;

	result->auth_perm = NFSAUTH_DENIED;

	/*
	 * Convert the client's address to a hostname
	 */
	nconf = getnetconfigent(argp->req_netid);
	if (nconf == NULL) {
		syslog(LOG_ERR, "No netconfig entry for %s", argp->req_netid);
		return;
	}

	nbuf.len = argp->req_client.n_len;
	nbuf.buf = argp->req_client.n_bytes;

	if (netdir_getbyaddr(nconf, &clnames, &nbuf)) {
		host = &tmp[0];
		if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
			struct sockaddr_in *sa;

			/* LINTED pointer alignment */
			sa = (struct sockaddr_in *)nbuf.buf;
			(void) inet_ntoa_r(sa->sin_addr, tmp);
		} else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
			struct sockaddr_in6 *sa;
			/* LINTED pointer */
			sa = (struct sockaddr_in6 *)nbuf.buf;
			(void) inet_ntop(AF_INET6, sa->sin6_addr.s6_addr,
				    tmp, INET6_ADDRSTRLEN);
		}
		clnames = anon_client(host);
	}

	/*
	 * Now find the export
	 */
	sh = findentry(argp->req_path);
	if (sh == NULL) {
		syslog(LOG_ERR, "%s not exported", argp->req_path);
		goto done;
	}

	result->auth_perm = check_client(sh, &nbuf, clnames, argp->req_flavor);

	sharefree(sh);

	if (result->auth_perm == NFSAUTH_DENIED) {
		syslog(LOG_ERR, "%s denied access to %s",
			clnames->h_hostservs[0].h_host, argp->req_path);
	}

done:
	freenetconfigent(nconf);
	if (clnames)
		netdir_free(clnames, ND_HOSTSERVLIST);
}