diff options
Diffstat (limited to 'usr/src/lib')
-rw-r--r-- | usr/src/lib/libshare/common/libshare.c | 3 | ||||
-rw-r--r-- | usr/src/lib/libshare/common/libsharecore.c | 5 | ||||
-rw-r--r-- | usr/src/lib/libshare/nfs/libshare_nfs.c | 237 | ||||
-rw-r--r-- | usr/src/lib/libshare/nfs/libshare_nfs.h | 4 |
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 |