add conditional support for getpwnam()

Some nfsv4 servers return a user/group name in the attributes instead
of a uid/gid number. At least for the "nobody" user.

For those, try to use getpwnam() where available to map the string back
to a uid/gid or return uid/gid==65534 (common value for nobody)
if not available or failing.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2018-02-16 08:24:26 +10:00
parent ca0291022a
commit c5eca214fc
2 changed files with 51 additions and 22 deletions

View File

@ -81,6 +81,19 @@ else
AC_MSG_NOTICE(Compiling without if= support.)
fi
AC_MSG_CHECKING(whether getpwnam() is available)
AC_TRY_COMPILE([#include <sys/types.h>, #include <pwd.h>], [
struct passwd *pwd = getpwnam("nobody");
], ac_cv_have_getpwnam=yes, ac_cv_have_getpwnam=no)
if test "$ac_cv_have_getpwnam" = yes ; then
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETPWNAM, 1, [Whether we have getpwnam()])
else
AC_MSG_RESULT(no)
AC_MSG_NOTICE(getpwnam() support is missing.)
AC_MSG_NOTICE(Compiling without getpwnam() support.)
fi
AC_ARG_ENABLE([werror], [AS_HELP_STRING([--disable-werror],
[Disables building with -Werror by default])])

View File

@ -76,6 +76,10 @@
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_GETPWNAM
#include <pwd.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
@ -399,6 +403,36 @@ nfs_pntoh64(const uint32_t *buf)
return val;
}
static int
nfs_get_ugid(struct nfs_context *nfs, const char *buf, int slen, int is_user)
{
int ugid = 0;
const char *name = buf;
while (slen) {
if (isdigit(*buf)) {
ugid *= 10;
ugid += *buf - '0';
} else {
#ifdef HAVE_GETPWNAM
struct passwd *pwd = getpwnam(name);
if (pwd) {
if (is_user) {
return pwd->pw_uid;
} else {
return pwd->pw_gid;
}
}
#endif
nfs_set_error(nfs, "Bad digit in fattr3 uid/gid");
return 65534;
}
buf++;
slen--;
}
return ugid;
}
#define CHECK_GETATTR_BUF_SPACE(len, size) \
if (len < size) { \
nfs_set_error(nfs, "Not enough data in fattr4"); \
@ -468,17 +502,8 @@ nfs_parse_attributes(struct nfs_context *nfs, struct nfs4_cb_data *data,
len -= 4;
pad = (4 - (slen & 0x03)) & 0x03;
CHECK_GETATTR_BUF_SPACE(len, slen);
while (slen) {
if (isdigit(*buf)) {
st->nfs_uid *= 10;
st->nfs_uid += *buf - '0';
} else {
nfs_set_error(nfs, "Bad digit in fattr3 uid");
return -1;
}
buf++;
slen--;
}
st->nfs_uid = nfs_get_ugid(nfs, buf, slen, 1);
buf += slen;
CHECK_GETATTR_BUF_SPACE(len, pad);
buf += pad;
len -= pad;
@ -489,17 +514,8 @@ nfs_parse_attributes(struct nfs_context *nfs, struct nfs4_cb_data *data,
len -= 4;
pad = (4 - (slen & 0x03)) & 0x03;
CHECK_GETATTR_BUF_SPACE(len, slen);
while (slen) {
if (isdigit(*buf)) {
st->nfs_gid *= 10;
st->nfs_gid += *buf - '0';
} else {
nfs_set_error(nfs, "Bad digit in fattr3 gid");
return -1;
}
buf++;
slen--;
}
st->nfs_gid = nfs_get_ugid(nfs, buf, slen, 0);
buf += slen;
CHECK_GETATTR_BUF_SPACE(len, pad);
buf += pad;
len -= pad;