Allow /etc/exports to contain usernames/groups with spaces in them.

If you are getting your users/groups from a directory service such
as LDAP or AD it's possible for those usernames or groupnames to
contain spaces.

Submitted by:	Sean E. Fagan
Reviewed by:	rmacklem
MFC after:	1 week
Sponsored by:	iXsystems
This commit is contained in:
Josh Paetzel 2016-01-07 05:34:39 +00:00
parent 6b53d1bc6f
commit b875c2e96d
2 changed files with 72 additions and 1 deletions

View File

@ -131,6 +131,7 @@ The credential includes all the groups to which the user is a member
on the local machine (see
.Xr id 1 ) .
The user may be specified by name or number.
The user string may be quoted, or use backslash escaping.
.Pp
.Sm off
.Fl maproot Li = Sy user:group1:group2:...
@ -140,6 +141,7 @@ to be used for remote access by root.
The elements of the list may be either names or numbers.
Note that user: should be used to distinguish a credential containing
no groups from a complete credential for that user.
The group names may be quoted, or use backslash escaping.
.Pp
.Sm off
.Fl mapall Li = Sy user

View File

@ -174,6 +174,7 @@ static int check_options(struct dirlist *);
static int checkmask(struct sockaddr *sa);
static int chk_host(struct dirlist *, struct sockaddr *, int *, int *,
int *, int **);
static char *strsep_quote(char **stringp, const char *delim);
static int create_service(struct netconfig *nconf);
static void complete_service(struct netconfig *nconf, char *port_str);
static void clearout_service(void);
@ -277,6 +278,73 @@ static void SYSLOG(int, const char *, ...) __printflike(2, 3);
static int debug = 0;
#endif
/*
* Similar to strsep(), but it allows for quoted strings
* and escaped characters.
*
* It returns the string (or NULL, if *stringp is NULL),
* which is a de-quoted version of the string if necessary.
*
* It modifies *stringp in place.
*/
static char *
strsep_quote(char **stringp, const char *delim)
{
char *srcptr, *dstptr, *retval;
char quot = 0;
if (stringp == NULL || *stringp == NULL)
return (NULL);
srcptr = dstptr = retval = *stringp;
while (*srcptr) {
/*
* We're looking for several edge cases here.
* First: if we're in quote state (quot != 0),
* then we ignore the delim characters, but otherwise
* process as normal, unless it is the quote character.
* Second: if the current character is a backslash,
* we take the next character as-is, without checking
* for delim, quote, or backslash. Exception: if the
* next character is a NUL, that's the end of the string.
* Third: if the character is a quote character, we toggle
* quote state.
* Otherwise: check the current character for NUL, or
* being in delim, and end the string if either is true.
*/
if (*srcptr == '\\') {
srcptr++;
/*
* The edge case here is if the next character
* is NUL, we want to stop processing. But if
* it's not NUL, then we simply want to copy it.
*/
if (*srcptr) {
*dstptr++ = *srcptr++;
}
continue;
}
if (quot == 0 && (*srcptr == '\'' || *srcptr == '"')) {
quot = *srcptr++;
continue;
}
if (quot && *srcptr == quot) {
/* End of the quoted part */
quot = 0;
srcptr++;
continue;
}
if (!quot && strchr(delim, *srcptr))
break;
*dstptr++ = *srcptr++;
}
*dstptr = 0; /* Terminate the string */
*stringp = (*srcptr == '\0') ? NULL : srcptr + 1;
return (retval);
}
/*
* Mountd server for NFS mount protocol as described in:
* NFS: Network File System Protocol Specification, RFC1094, Appendix A
@ -2831,8 +2899,9 @@ parsecred(char *namelist, struct xucred *cr)
/*
* Get the user's password table entry.
*/
names = strsep(&namelist, " \t\n");
names = strsep_quote(&namelist, " \t\n");
name = strsep(&names, ":");
/* Bug? name could be NULL here */
if (isdigit(*name) || *name == '-')
pw = getpwuid(atoi(name));
else