Skip to content

Commit

Permalink
Allow leading digits in userquota/groupquota names
Browse files Browse the repository at this point in the history
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 <[email protected]>
Closes openzfs#428
schakrava authored and behlendorf committed Nov 22, 2011
1 parent ca5fd24 commit ada8ec1
Showing 1 changed file with 28 additions and 39 deletions.
67 changes: 28 additions & 39 deletions lib/libzfs/libzfs_dataset.c
Original file line number Diff line number Diff line change
@@ -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,54 +2314,29 @@ 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';
cp++;

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);
}

0 comments on commit ada8ec1

Please sign in to comment.