示例#1
0
文件: mountd.c 项目: andreiw/polaris
/*
 * Given an export and the clients hostname(s)
 * determine the security flavors that this
 * client is permitted to use.
 *
 * This is somewhat more complicated than the "old"
 * routine because the options may contain multiple
 * security flavors (sec=) each with its own access
 * lists.  So a client could be granted access based
 * on a number of security flavors.  Note that the
 * type of access might not always be the same, the
 * client may get readonly access with one flavor
 * and readwrite with another, however the client
 * is not told this detail, it gets only the list
 * of flavors, and only if the client is using
 * version 3 of the mount protocol.
 */
static int
getclientsflavors_new(struct share *sh, struct netbuf *nb,
    struct nd_hostservlist *clnames, int *flavors)
{
	char *opts, *p, *val;
	char *lasts;
	char *f;
	int access_ok, count, c;

	opts = strdup(sh->sh_opts);
	if (opts == NULL) {
		syslog(LOG_ERR, "getclientsflavors: no memory");
		return (0);
	}

	p = opts;
	count = c = 0;
	/* default access is rw */
	access_ok = 1;

	while (*p) {
		switch (getsubopt(&p, optlist, &val)) {
		case OPT_SEC:
			/*
			 * Before a new sec=xxx option, check if we need
			 * to move the c index back to the previous count.
			 */
			if (!access_ok) {
				c = count;
			}

			/* get all the sec=f1[:f2] flavors */
			while ((f = strtok_r(val, ":", &lasts))
					!= NULL) {
				flavors[c++] = map_flavor(f);
				val = NULL;
			}
			/* for a new sec=xxx option, default is rw access */
			access_ok = 1;
			break;

		case OPT_RO:
		case OPT_RW:
			if (in_access_list(nb, clnames, val)) {
				count = c;
				access_ok = 1;
			} else {
				access_ok = 0;
			}
			break;
		}
	}

	if (!access_ok) {
		c = count;
	}
	free(opts);

	return (c);
}
示例#2
0
文件: mountd.c 项目: andreiw/polaris
/*
 * Given an export and the clients hostname(s)
 * determine the security flavors that this
 * client is permitted to use.
 *
 * This routine is called only for "old" syntax, i.e.
 * only one security flavor is allowed.  So we need
 * to determine two things: the particular flavor,
 * and whether the client is allowed to use this
 * flavor, i.e. is in the access list.
 *
 * Note that if there is no access list, then the
 * default is that access is granted.
 */
static int
getclientsflavors_old(struct share *sh, struct netbuf *nb,
    struct nd_hostservlist *clnames, int *flavors)
{
	char *opts, *p, *val;
	int ok = 0;
	int defaultaccess = 1;

	opts = strdup(sh->sh_opts);
	if (opts == NULL) {
		syslog(LOG_ERR, "getclientsflavors: no memory");
		return (0);
	}

	flavors[0] = AUTH_SYS;
	p = opts;

	while (*p) {

		switch (getsubopt(&p, optlist, &val)) {
		case OPT_SECURE:
			flavors[0] = AUTH_DES;
			break;

		case OPT_RO:
		case OPT_RW:
			defaultaccess = 0;
			if (in_access_list(nb, clnames, val))
				ok++;
			break;
		}
	}

	free(opts);

	return (defaultaccess || ok);
}
示例#3
0
文件: mountd.c 项目: andreiw/polaris
static int
check_client_new(struct share *sh, struct netbuf *nb,
    struct nd_hostservlist *clnames, int flavor)
{
	char *opts, *p, *val;
	char *lasts;
	char *f;
	int match = 0;	/* Set when a flavor is matched */
	int perm = 0;	/* Set when "ro", "rw" or "root" is matched */
	int list = 0;	/* Set when "ro", "rw" is found */
	int ro_val = 0;	/* Set if ro option is 'ro=' */
	int rw_val = 0;	/* Set if rw option is 'rw=' */

	opts = strdup(sh->sh_opts);
	if (opts == NULL) {
		syslog(LOG_ERR, "check_client: no memory");
		return (0);
	}

	p = opts;

	while (*p) {
		switch (getsubopt(&p, optlist, &val)) {

		case OPT_SEC:
			if (match)
				goto done;

			while ((f = strtok_r(val, ":", &lasts))
					!= NULL) {
				if (flavor == map_flavor(f)) {
					match = 1;
					break;
				}
				val = NULL;
			}
			break;

		case OPT_RO:
			if (!match)
				break;

			list++;
			if (val) ro_val++;
			if (in_access_list(nb, clnames, val))
				perm |= NFSAUTH_RO;
			break;

		case OPT_RW:
			if (!match)
				break;

			list++;
			if (val) rw_val++;
			if (in_access_list(nb, clnames, val))
				perm |= NFSAUTH_RW;
			break;

		case OPT_ROOT:
			/*
			 * Check if the client is in
			 * the root list. Only valid
			 * for AUTH_SYS.
			 */
			if (flavor != AUTH_SYS)
				break;

			if (!match)
				break;

			if (val == NULL || *val == '\0')
				break;

			if (in_access_list(nb, clnames, val))
				perm |= NFSAUTH_ROOT;
			break;
		}
	}

done:
	/*
	 * If no match then set the perm accordingly
	 */
	if (!match)
		return (NFSAUTH_DENIED);

	if (list) {
		/*
		 * If the client doesn't match an "ro" or "rw" list then
		 * check if it may have access by using a different flavor.
		 * If so, return NFSAUTH_WRONGSEC.
		 * If not, return NFSAUTH_DENIED.
		 */
		if ((perm & (NFSAUTH_RO | NFSAUTH_RW)) == 0) {
			if (is_wrongsec(sh, nb, clnames, flavor))
				perm |= NFSAUTH_WRONGSEC;
			else
				perm |= NFSAUTH_DENIED;
		}
	} else {
		/*
		 * The client matched a flavor entry that
		 * has no explicit "rw" or "ro" determination.
		 * Make sure it defaults to "rw".
		 */
		perm |= NFSAUTH_RW;
	}

	/*
	 * The client may show up in both ro= and rw=
	 * lists.  If so, then turn off the RO access
	 * bit leaving RW access.
	 */
	if (perm & NFSAUTH_RO && perm & NFSAUTH_RW) {
		/*
		 * Logically cover all permutations of rw=,ro=.
		 * In the case where, rw,ro=<host> we would like
		 * to remove RW access for the host.  In all other cases
		 * RW wins the precedence battle.
		 */
		if (!rw_val && ro_val) {
			perm &= ~(NFSAUTH_RW);
		} else {
			perm &= ~(NFSAUTH_RO);
		}
	}

	free(opts);

	return (perm);
}
示例#4
0
文件: mountd.c 项目: andreiw/polaris
static int
check_client_old(struct share *sh, struct netbuf *nb,
    struct nd_hostservlist *clnames, int flavor)
{
	char *opts, *p, *val;
	int match;	/* Set when a flavor is matched */
	int perm = 0;	/* Set when "ro", "rw" or "root" is matched */
	int list = 0;	/* Set when "ro", "rw" is found */
	int ro_val = 0;	/* Set if ro option is 'ro=' */
	int rw_val = 0;	/* Set if rw option is 'rw=' */

	opts = strdup(sh->sh_opts);
	if (opts == NULL) {
		syslog(LOG_ERR, "check_client: no memory");
		return (0);
	}

	p = opts;
	match = AUTH_UNIX;

	while (*p) {
		switch (getsubopt(&p, optlist, &val)) {

		case OPT_SECURE:
			match = AUTH_DES;
			break;

		case OPT_RO:
			list++;
			if (val) ro_val++;
			if (in_access_list(nb, clnames, val))
				perm |= NFSAUTH_RO;
			break;

		case OPT_RW:
			list++;
			if (val) rw_val++;
			if (in_access_list(nb, clnames, val))
				perm |= NFSAUTH_RW;
			break;

		case OPT_ROOT:
			/*
			 * Check if the client is in
			 * the root list. Only valid
			 * for AUTH_SYS.
			 */
			if (flavor != AUTH_SYS)
				break;

			if (val == NULL || *val == '\0')
				break;

			if (in_access_list(nb, clnames, val))
				perm |= NFSAUTH_ROOT;
			break;
		}
	}

	free(opts);

	if (flavor != match)
		return (NFSAUTH_DENIED);

	if (list) {
		/*
		 * If the client doesn't match an "ro" or "rw"
		 * list then set no access.
		 */
		if ((perm & (NFSAUTH_RO | NFSAUTH_RW)) == 0)
			perm |= NFSAUTH_DENIED;
	} else {
		/*
		 * The client matched a flavor entry that
		 * has no explicit "rw" or "ro" determination.
		 * Default it to "rw".
		 */
		perm |= NFSAUTH_RW;
	}


	/*
	 * The client may show up in both ro= and rw=
	 * lists.  If so, then turn off the RO access
	 * bit leaving RW access.
	 */
	if (perm & NFSAUTH_RO && perm & NFSAUTH_RW) {
		/*
		 * Logically cover all permutations of rw=,ro=.
		 * In the case where, rw,ro=<host> we would like
		 * to remove RW access for the host.  In all other cases
		 * RW wins the precedence battle.
		 */
		if (!rw_val && ro_val) {
			perm &= ~(NFSAUTH_RW);
		} else {
			perm &= ~(NFSAUTH_RO);
		}
	}

	return (perm);
}
示例#5
0
static char *
charmap_search(struct netbuf *nbuf, char *opts)
{
	char *copts;
	char *next;
	char *name;
	char *result = NULL;
	char *netid;
	struct netconfig *nconf;
	struct nd_hostservlist  *hl = NULL;
	struct sockaddr *sa;

	/* eventually charopts should be dynamically setup */
	if (charopts == NULL) {
		free(copts);
		return (NULL);
	}

	sa = (struct sockaddr *)nbuf->buf;

	switch (sa->sa_family) {
	case AF_INET:
		nconf = getnetconfigent("tcp");
		break;
	case AF_INET6:
		nconf = getnetconfigent("tcp6");
		break;
	default:
		return (NULL);
	}

	if (nconf == NULL) {
		return (NULL);
	}

	/*
	 * Use the this API instead of the netdir_getbyaddr()
	 * to avoid service lookup.
	 */
	if (__netdir_getbyaddr_nosrv(nconf, &hl, nbuf)) {
		syslog(LOG_ERR, "netdir: %s\n", netdir_sperror());
		freenetconfigent(nconf);
		return (NULL);
	}

	copts = strdup(opts);
	if (copts == NULL) {
		freenetconfigent(nconf);
		return (NULL);
	}

	next = copts;
	while (*next != '\0') {
		char *val;
		name = next;
		if (getsubopt(&next, charopts, &val) >= 0) {
			char *cp;
			/*
			 * name will have the whole opt and val the value. Set
			 * the '=' to '\0' and we have the charmap in name and
			 * the access list in val.
			 */
			cp = strchr(name, '=');
			if (cp != NULL)
				*cp = '\0';
			if (in_access_list(nbuf,  hl, val)) {
				result = name;
				break;
			}
		}
	}

	if (result != NULL)
		result = strdup(result);

	free(copts);
	freenetconfigent(nconf);

	return (result);
}