Allow leading digits in userquota/groupquota names
While setting/getting userquota and groupquota properties, the input was not treated as a possible username or groupname if it had a leading digit. While useradd in linux recommends the regexp [a-z_][a-z0-9_-]*[$]? , it is not enforced. This causes problem for usernames with leading digits in them. We need to be able to support getting and setting properties for this unconventional but possible input category I've updated the code to validate the username or groupname directly via the API. Also, note that I moved this validation to the beginning before the check for SID names with @. This also supports usernames with @ character in them which are valid. Only when input with @ is not a valid username, it is interpreted as a potential SID name. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #428
This commit is contained in:
parent
ca5fd24984
commit
ada8ec1ec5
@ -2249,15 +2249,19 @@ idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
|
||||
* convert the propname into parameters needed by kernel
|
||||
* Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
|
||||
* Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
|
||||
* Eg: groupquota@staff -> ZFS_PROP_GROUPQUOTA, "", 1234
|
||||
* Eg: groupused@staff -> ZFS_PROP_GROUPUSED, "", 1234
|
||||
*/
|
||||
static int
|
||||
userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
|
||||
{
|
||||
zfs_userquota_prop_t type;
|
||||
char *cp, *end;
|
||||
char *numericsid = NULL;
|
||||
char *cp;
|
||||
boolean_t isuser;
|
||||
boolean_t isgroup;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
|
||||
domain[0] = '\0';
|
||||
|
||||
@ -2271,18 +2275,29 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
return (EINVAL);
|
||||
*typep = type;
|
||||
|
||||
isuser = (type == ZFS_PROP_USERQUOTA ||
|
||||
type == ZFS_PROP_USERUSED);
|
||||
isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED);
|
||||
isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED);
|
||||
|
||||
cp = strchr(propname, '@') + 1;
|
||||
|
||||
if (strchr(cp, '@')) {
|
||||
if (isuser && (pw = getpwnam(cp)) != NULL) {
|
||||
if (zoned && getzoneid() == GLOBAL_ZONEID)
|
||||
return (ENOENT);
|
||||
*ridp = pw->pw_uid;
|
||||
} else if (isgroup && (gr = getgrnam(cp)) != NULL) {
|
||||
if (zoned && getzoneid() == GLOBAL_ZONEID)
|
||||
return (ENOENT);
|
||||
*ridp = gr->gr_gid;
|
||||
} else if (strchr(cp, '@')) {
|
||||
#ifdef HAVE_IDMAP
|
||||
/*
|
||||
* It's a SID name (eg "user@domain") that needs to be
|
||||
* turned into S-1-domainID-RID.
|
||||
*/
|
||||
directory_error_t e;
|
||||
char *numericsid = NULL;
|
||||
char *end;
|
||||
|
||||
if (zoned && getzoneid() == GLOBAL_ZONEID)
|
||||
return (ENOENT);
|
||||
if (isuser) {
|
||||
@ -2299,14 +2314,6 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
if (numericsid == NULL)
|
||||
return (ENOENT);
|
||||
cp = numericsid;
|
||||
/* will be further decoded below */
|
||||
#else
|
||||
return (ENOSYS);
|
||||
#endif /* HAVE_IDMAP */
|
||||
}
|
||||
|
||||
if (strncmp(cp, "S-1-", 4) == 0) {
|
||||
/* It's a numeric SID (eg "S-1-234-567-89") */
|
||||
(void) strlcpy(domain, cp, domainlen);
|
||||
cp = strrchr(domain, '-');
|
||||
*cp = '\0';
|
||||
@ -2314,39 +2321,22 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
|
||||
errno = 0;
|
||||
*ridp = strtoull(cp, &end, 10);
|
||||
if (numericsid) {
|
||||
free(numericsid);
|
||||
numericsid = NULL;
|
||||
}
|
||||
free(numericsid);
|
||||
|
||||
if (errno != 0 || *end != '\0')
|
||||
return (EINVAL);
|
||||
} else if (!isdigit(*cp)) {
|
||||
/*
|
||||
* It's a user/group name (eg "user") that needs to be
|
||||
* turned into a uid/gid
|
||||
*/
|
||||
if (zoned && getzoneid() == GLOBAL_ZONEID)
|
||||
return (ENOENT);
|
||||
if (isuser) {
|
||||
struct passwd *pw;
|
||||
pw = getpwnam(cp);
|
||||
if (pw == NULL)
|
||||
return (ENOENT);
|
||||
*ridp = pw->pw_uid;
|
||||
} else {
|
||||
struct group *gr;
|
||||
gr = getgrnam(cp);
|
||||
if (gr == NULL)
|
||||
return (ENOENT);
|
||||
*ridp = gr->gr_gid;
|
||||
}
|
||||
#else
|
||||
return (ENOSYS);
|
||||
#endif /* HAVE_IDMAP */
|
||||
} else {
|
||||
#ifdef HAVE_IDMAP
|
||||
/* It's a user/group ID (eg "12345"). */
|
||||
uid_t id = strtoul(cp, &end, 10);
|
||||
uid_t id;
|
||||
idmap_rid_t rid;
|
||||
char *mapdomain;
|
||||
char *end;
|
||||
|
||||
id = strtoul(cp, &end, 10);
|
||||
if (*end != '\0')
|
||||
return (EINVAL);
|
||||
if (id > MAXUID) {
|
||||
@ -2364,7 +2354,6 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
|
||||
#endif /* HAVE_IDMAP */
|
||||
}
|
||||
|
||||
ASSERT3P(numericsid, ==, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user