summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libshare/common/libshare.c3
-rw-r--r--usr/src/lib/libshare/common/libsharecore.c5
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.c237
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.h4
4 files changed, 204 insertions, 45 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 1d17d5fea7..320ff911d7 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -597,7 +598,7 @@ validpath(sa_handle_t handle, char *path, int strictness)
* check to see if group/share is persistent.
*
* "group" can be either an sa_group_t or an sa_share_t. (void *)
- * works since both thse types are also void *.
+ * works since both these types are also void *.
* If the share is a ZFS share, mark it as persistent.
*/
int
diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c
index 02b44052ca..ba2aa89fb6 100644
--- a/usr/src/lib/libshare/common/libsharecore.c
+++ b/usr/src/lib/libshare/common/libsharecore.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -772,7 +773,7 @@ add_syntax_comment(xmlNodePtr root, char *line, char *err, int todfstab)
/*
* sa_is_share(object)
*
- * returns true of the object is of type "share".
+ * returns true if the object is of type "share".
*/
int
@@ -787,7 +788,7 @@ sa_is_share(void *object)
/*
* sa_is_resource(object)
*
- * returns true of the object is of type "share".
+ * returns true if the object is of type "resource".
*/
int
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c
index a3b7305ac2..9e6124286d 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c
@@ -41,6 +41,7 @@
#include "libshare_impl.h"
#include <nfs/export.h>
#include <pwd.h>
+#include <grp.h>
#include <limits.h>
#include <libscf.h>
#include <syslog.h>
@@ -167,8 +168,12 @@ struct option_defs optdefs[] = {
{"", OPT_CHARSET_MAP, OPT_TYPE_ACCLIST},
#define OPT_NOACLFAB 17
{SHOPT_NOACLFAB, OPT_NOACLFAB, OPT_TYPE_BOOLEAN},
+#define OPT_UIDMAP 18
+ {SHOPT_UIDMAP, OPT_UIDMAP, OPT_TYPE_MAPPING},
+#define OPT_GIDMAP 19
+ {SHOPT_GIDMAP, OPT_GIDMAP, OPT_TYPE_MAPPING},
#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
-#define OPT_VOLFH 18
+#define OPT_VOLFH 20
{SHOPT_VOLFH, OPT_VOLFH},
#endif /* VOLATILE_FH_TEST */
NULL
@@ -211,6 +216,8 @@ static char *seclist[] = {
SHOPT_WINDOW,
SHOPT_NONE,
SHOPT_ROOT_MAPPING,
+ SHOPT_UIDMAP,
+ SHOPT_GIDMAP,
NULL
};
@@ -434,7 +441,7 @@ nfs_alistcat(char *str1, char *str2, char sep)
}
/*
- * add_security_prop(sec, name, value, persist)
+ * add_security_prop(sec, name, value, persist, iszfs)
*
* Add the property to the securities structure. This accumulates
* properties for as part of parsing legacy options.
@@ -472,21 +479,28 @@ add_security_prop(struct securities *sec, char *name, char *value,
char *newvalue;
/*
- * The security options of ro/rw/root might appear
- * multiple times. If they do, the values need to be
- * merged into an access list. If it was previously
- * empty, the new value alone is added.
+ * The security options of ro/rw/root/uidmap/gidmap
+ * might appear multiple times. If they do, the values
+ * need to be merged. If it was previously empty, the
+ * new value alone is added.
*/
oldvalue = sa_get_property_attr(prop, "value");
if (oldvalue != NULL) {
+ char sep = ':';
+
+ if (strcmp(name, SHOPT_UIDMAP) == 0 ||
+ strcmp(name, SHOPT_GIDMAP) == 0)
+ sep = '~';
+
/*
* The general case is to concatenate the new
* value onto the old value for multiple
- * rw(ro/root) properties. A special case
- * exists when either the old or new is the
- * "all" case. In the special case, if both
- * are "all", then it is "all", else if one is
- * an access-list, that replaces the "all".
+ * rw(ro/root/uidmap/gidmap) properties. For
+ * rw/ro/root a special case exists when either
+ * the old or new is the "all" case. In the
+ * special case, if both are "all", then it is
+ * "all", else if one is an access-list, that
+ * replaces the "all".
*/
if (strcmp(oldvalue, "*") == 0) {
/* Replace old value with new value. */
@@ -504,7 +518,7 @@ add_security_prop(struct securities *sec, char *name, char *value,
* access-list.
*/
newvalue = nfs_alistcat(oldvalue,
- value, ':');
+ value, sep);
}
if (newvalue != NULL) {
@@ -515,8 +529,8 @@ add_security_prop(struct securities *sec, char *name, char *value,
prop);
free(newvalue);
}
- if (oldvalue != NULL)
- sa_free_attr_string(oldvalue);
+
+ sa_free_attr_string(oldvalue);
}
} else {
prop = sa_create_property(name, value);
@@ -567,7 +581,7 @@ invalid_security(char *options)
value = strchr(token, '=');
if (value != NULL)
*value++ = '\0';
- if (strcmp(token, "sec") == 0) {
+ if (strcmp(token, SHOPT_SEC) == 0) {
/* HAVE security flavors so check them */
char *tok, *next;
for (next = NULL, tok = value; tok != NULL;
@@ -681,7 +695,6 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
token = dup;
lasts = NULL;
while (token != NULL && ret == SA_OK) {
- ret = SA_OK;
token = strtok_r(base, ",", &lasts);
base = NULL;
if (token != NULL) {
@@ -696,8 +709,8 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
if (value != NULL) {
*value++ = '\0';
}
- if (strcmp(token, "sec") == 0 ||
- strcmp(token, "secure") == 0) {
+ if (strcmp(token, SHOPT_SEC) == 0 ||
+ strcmp(token, SHOPT_SECURE) == 0) {
/*
* Once in security parsing, we only
* do security. We do need to move
@@ -713,7 +726,7 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
*/
free_security_list(security_list);
}
- if (strcmp(token, "secure") == 0) {
+ if (strcmp(token, SHOPT_SECURE) == 0) {
value = "dh";
} else {
if (value == NULL) {
@@ -726,7 +739,7 @@ nfs_parse_legacy_options(sa_group_t group, char *options)
} else {
/*
* Note that the "old" syntax allowed a
- * default security model This must be
+ * default security model. This must be
* accounted for and internally converted to
* "standard" security structure.
*/
@@ -1194,6 +1207,10 @@ fill_security_from_secopts(struct secinfo *sp, sa_security_t secopts)
}
sp->s_rootid = val;
break;
+ case OPT_UIDMAP:
+ case OPT_GIDMAP:
+ sp->s_flags |= M_MAP;
+ break;
default:
break;
}
@@ -1263,6 +1280,7 @@ printarg(char *path, struct exportdata *ep)
if (sp->s_flags & M_RW) (void) printf("M_RW ");
if (sp->s_flags & M_RWL) (void) printf("M_RWL ");
if (sp->s_flags & M_NONE) (void) printf("M_NONE ");
+ if (sp->s_flags & M_MAP) (void) printf("M_MAP ");
if (sp->s_flags == 0) (void) printf("(none)");
(void) printf("\n");
(void) printf("\t\ts_window = %d\n", sp->s_window);
@@ -1390,8 +1408,7 @@ nfs_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr,
if (value == NULL) {
(void) snprintf(buff + curlen, buffsize - curlen,
- "%s%s", sep ? "," : "",
- name, value != NULL ? value : "");
+ "%s%s", sep ? "," : "", name);
} else {
(void) snprintf(buff + curlen, buffsize - curlen,
"%s%s=%s", sep ? "," : "",
@@ -1697,7 +1714,7 @@ check_public(sa_group_t group, sa_share_t skipshare)
}
/*
- * public_exists(handle, share)
+ * public_exists(handle, skipshare)
*
* check to see if public option is set on any other share than the
* one specified. Need to check zfs sub-groups as well as the top
@@ -1871,7 +1888,7 @@ nfs_enable_share(sa_share_t share)
sp[i].s_window = DEF_WIN;
sp[i].s_rootcnt = 0;
sp[i].s_rootnames = NULL;
- (void) fill_security_from_secopts(&sp[i], sec);
+ (void) fill_security_from_secopts(&sp[i], sec);
if (sec != NULL)
sa_free_derived_security(sec);
if (sectype != NULL)
@@ -1880,7 +1897,7 @@ nfs_enable_share(sa_share_t share)
}
/*
* when we get here, we can do the exportfs system call and
- * initiate thinsg. We probably want to enable the nfs.server
+ * initiate things. We probably want to enable the nfs.server
* service first if it isn't running within SMF.
*/
/* check nfs.server status and start if needed */
@@ -2094,6 +2111,56 @@ nfs_disable_share(sa_share_t share, char *path)
return (ret);
}
+static int
+check_user(char *value)
+{
+ int ret = SA_OK;
+
+ if (!is_a_number(value)) {
+ struct passwd *pw;
+ /*
+ * in this case it would have to be a
+ * user name
+ */
+ pw = getpwnam(value);
+ if (pw == NULL)
+ ret = SA_BAD_VALUE;
+ endpwent();
+ } else {
+ uint64_t intval;
+ intval = strtoull(value, NULL, 0);
+ if (intval > UID_MAX && intval != -1)
+ ret = SA_BAD_VALUE;
+ }
+
+ return (ret);
+}
+
+static int
+check_group(char *value)
+{
+ int ret = SA_OK;
+
+ if (!is_a_number(value)) {
+ struct group *gr;
+ /*
+ * in this case it would have to be a
+ * group name
+ */
+ gr = getgrnam(value);
+ if (gr == NULL)
+ ret = SA_BAD_VALUE;
+ endgrent();
+ } else {
+ uint64_t intval;
+ intval = strtoull(value, NULL, 0);
+ if (intval > UID_MAX && intval != -1)
+ ret = SA_BAD_VALUE;
+ }
+
+ return (ret);
+}
+
/*
* check_rorwnone(v1, v2, v3)
*
@@ -2161,11 +2228,13 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
if (value != NULL) {
/* first basic type checking */
switch (optdefs[optindex].type) {
+
case OPT_TYPE_NUMBER:
/* check that the value is all digits */
if (!is_a_number(value))
ret = SA_BAD_VALUE;
break;
+
case OPT_TYPE_BOOLEAN:
if (strlen(value) == 0 ||
strcasecmp(value, "true") == 0 ||
@@ -2177,30 +2246,18 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
ret = SA_BAD_VALUE;
}
break;
+
case OPT_TYPE_USER:
- if (!is_a_number(value)) {
- struct passwd *pw;
- /*
- * in this case it would have to be a
- * user name
- */
- pw = getpwnam(value);
- if (pw == NULL)
- ret = SA_BAD_VALUE;
- endpwent();
- } else {
- uint64_t intval;
- intval = strtoull(value, NULL, 0);
- if (intval > UID_MAX && intval != ~0)
- ret = SA_BAD_VALUE;
- }
+ ret = check_user(value);
break;
+
case OPT_TYPE_FILE:
if (strcmp(value, "..") == 0 ||
strchr(value, '/') != NULL) {
ret = SA_BAD_VALUE;
}
break;
+
case OPT_TYPE_ACCLIST: {
sa_property_t oprop1;
sa_property_t oprop2;
@@ -2256,6 +2313,7 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
sa_free_attr_string(ovalue2);
break;
}
+
case OPT_TYPE_LOGTAG:
if (nfsl_getconfig_list(&configlist) == 0) {
int error;
@@ -2277,9 +2335,11 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
ret = SA_CONFIG_ERR;
}
break;
+
case OPT_TYPE_STRING:
/* whatever is here should be ok */
break;
+
case OPT_TYPE_SECURITY:
/*
* The "sec" property isn't used in the
@@ -2289,6 +2349,99 @@ nfs_validate_property(sa_handle_t handle, sa_property_t property,
*/
ret = SA_NO_SUCH_PROP;
break;
+
+ case OPT_TYPE_MAPPING: {
+ char *p;
+ char *n;
+ char *c;
+ int (*f)(char *);
+
+ sa_security_t security;
+
+ /*
+ * mapping is only supported for sec=sys
+ */
+ ret = SA_CONFIG_ERR;
+ if (parent_group == NULL)
+ break;
+
+ for (security = sa_get_security(parent_group,
+ NULL, NULL); security != NULL;
+ security = sa_get_next_security(security)) {
+ char *type;
+ char *sectype;
+
+ type = sa_get_security_attr(security,
+ "type");
+ if (type == NULL)
+ continue;
+
+ if (strcmp(type, "nfs") != 0) {
+ sa_free_attr_string(type);
+ continue;
+ }
+ sa_free_attr_string(type);
+
+ sectype = sa_get_security_attr(security,
+ "sectype");
+ if (sectype == NULL)
+ continue;
+
+ if (strcmp(sectype, "sys") != 0) {
+ sa_free_attr_string(sectype);
+ ret = SA_CONFIG_ERR;
+ break;
+ }
+ sa_free_attr_string(sectype);
+ ret = SA_OK;
+ }
+
+ if (ret != SA_OK)
+ break;
+
+ assert(optindex == OPT_UIDMAP ||
+ optindex == OPT_GIDMAP);
+ f = optindex == OPT_UIDMAP ? check_user :
+ check_group;
+
+
+ p = strdup(value);
+ if (p == NULL)
+ ret = SA_BAD_VALUE;
+
+ for (c = p; ret == SA_OK && c != NULL; c = n) {
+ char *s;
+ char *t;
+
+ n = strchr(c, '~');
+ if (n != NULL)
+ *n++ = '\0';
+
+ s = strchr(c, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ t = strchr(s, ':');
+ if (t != NULL)
+ *t = '\0';
+ }
+
+ if (s == NULL || t == NULL)
+ ret = SA_BAD_VALUE;
+
+ if (ret == SA_OK && *c != '\0' &&
+ strcmp(c, "*") != 0)
+ ret = f(c);
+
+ if (ret == SA_OK && *s != '\0' &&
+ strcmp(s, "-1") != 0)
+ ret = f(s);
+ }
+
+ free(p);
+
+ break;
+ }
+
default:
break;
}
@@ -3040,7 +3193,7 @@ nfs_space_alias(char *space)
* Only the space named "default" is special. If it is used,
* the default needs to be looked up and the real name used.
* This is normally "sys" but could be changed. We always
- * change defautl to the real name.
+ * change default to the real name.
*/
if (strcmp(space, "default") == 0 &&
nfs_getseconfig_default(&secconf) == 0) {
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.h b/usr/src/lib/libshare/nfs/libshare_nfs.h
index 5a079db653..ac608f2b52 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.h
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -53,6 +54,8 @@ extern "C" {
#define SHOPT_LOG "log"
#define SHOPT_CKSUM "cksum"
#define SHOPT_NOACLFAB "noaclfab"
+#define SHOPT_UIDMAP "uidmap"
+#define SHOPT_GIDMAP "gidmap"
/*
* defined options types. These should be in a file rather than
@@ -75,6 +78,7 @@ extern "C" {
#define OPT_TYPE_DOMAIN 13
#define OPT_TYPE_ONOFF 14
#define OPT_TYPE_PROTOCOL 15
+#define OPT_TYPE_MAPPING 16
#define OPT_SHARE_ONLY 1