diff options
author | Rick Macklem <rmacklem@FreeBSD.org> | 2013-05-02 12:43:56 +0000 |
---|---|---|
committer | Rick Macklem <rmacklem@FreeBSD.org> | 2013-05-02 12:43:56 +0000 |
commit | d1e9aa46c5148e4e3f77d8754e95b0bde6e4d76b (patch) | |
tree | 99128a35654f214145980883b8431f9d301cd229 /usr.sbin/gssd | |
parent | f5efbffe5292589f2bb0d6ae56b22aca707ae46c (diff) | |
download | src-d1e9aa46c5148e4e3f77d8754e95b0bde6e4d76b.tar.gz src-d1e9aa46c5148e4e3f77d8754e95b0bde6e4d76b.zip |
Fix the getpwuid_r() call in the gssd daemon so that it handles
the ERANGE error return case. Without this fix, authentication
of users for certain system setups could fail unexpectedly.
Reported by: Elias Martenson (lokedhs@gmail.com)
Tested by: Elias Martenson (earlier version)
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=250176
Diffstat (limited to 'usr.sbin/gssd')
-rw-r--r-- | usr.sbin/gssd/gssd.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/usr.sbin/gssd/gssd.c b/usr.sbin/gssd/gssd.c index 977794366c00..a50e09742951 100644 --- a/usr.sbin/gssd/gssd.c +++ b/usr.sbin/gssd/gssd.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <ctype.h> #include <dirent.h> #include <err.h> +#include <errno.h> #ifndef WITHOUT_KERBEROS #include <krb5.h> #endif @@ -557,8 +558,11 @@ gssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struc { gss_name_t name = gssd_find_resource(argp->pname); uid_t uid; - char buf[128]; + char buf[1024], *bufp; struct passwd pwd, *pw; + size_t buflen; + int error; + static size_t buflen_hint = 1024; memset(result, 0, sizeof(*result)); if (name) { @@ -567,7 +571,24 @@ gssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struc name, argp->mech, &uid); if (result->major_status == GSS_S_COMPLETE) { result->uid = uid; - getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw); + buflen = buflen_hint; + for (;;) { + pw = NULL; + bufp = buf; + if (buflen > sizeof(buf)) + bufp = malloc(buflen); + if (bufp == NULL) + break; + error = getpwuid_r(uid, &pwd, bufp, buflen, + &pw); + if (error != ERANGE) + break; + if (buflen > sizeof(buf)) + free(bufp); + buflen += 1024; + if (buflen > buflen_hint) + buflen_hint = buflen; + } if (pw) { int len = NGRPS; int groups[NGRPS]; @@ -584,6 +605,8 @@ gssd_pname_to_uid_1_svc(pname_to_uid_args *argp, pname_to_uid_res *result, struc result->gidlist.gidlist_len = 0; result->gidlist.gidlist_val = NULL; } + if (bufp != NULL && buflen > sizeof(buf)) + free(bufp); } } else { result->major_status = GSS_S_BAD_NAME; |