Re: Possible bug in NFSv4 with krb5p security?

From: Andrey Simonenko <simon_at_comsys.ntu-kpi.kiev.ua>
Date: Tue, 19 Feb 2013 11:31:42 +0200
On Tue, Feb 19, 2013 at 12:06:13AM +0800, Elias Martenson wrote:
> 
> You were right, the problem was in pname_to_uid.c. In it, the following
> code can be found:
> 
>         char lname[MAXLOGNAME + 1], buf[1024];
> 
>         /* some code snipped for brevity... */
> 
>         getpwnam_r(lname, &pwd, buf, sizeof(buf), &pw);
>         if (pw) {
>                 *uidp = pw->pw_uid;
>                 return (GSS_S_COMPLETE);
>         } else {
>                 return (GSS_S_FAILURE);
>         }
> 
> As it turns out, the getpwnam_r() call fails with ERANGE (I had to check
> the return value from getpwnam_r() in order to determine this, as pw is set
> to NULL both if there was an error or if the user name can't be found).
> 
> Now, increasing the size of buf to 1024 solved the problem, and now the
> lookup works correctly.
> 
> I wrote a small test program that issued the same call to getpwnam_r() and
> it worked. Until I su'ed to root, and then it failed.
> 
> It seems as though the buffer needs to be bigger if you're root. I have no
> idea why, but there you have it. Problem solved.

It can require bigger buffer, since root can get the pw_password field
in the struct passwd{}.

Since sysconf(_SC_GETPW_R_SIZE_MAX) does not work on FreeBSD, the buffer
for getpwnam_r() call should have at least (2 * MAXLOGNAME + 2 * MAXPATHLEN +
_PASSWORD_LEN + 1) bytes (it is unclear how much is required for pw_gecos).

This buffer can be dynamically reallocated until getpwnam_r() is not
return ERANGE error (the following code has not been compiled and verified):

#define PWBUF_SIZE_INI (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1)
#define PWBUF_SIZE_INC 128

	size = PWBUF_SIZE_INI;
	for (;;) {
		size += PWBUF_SIZE_INC;
		buf = malloc(size);
		if (buf == NULL)
			return (GSS_S_FAILURE);
		error = getpwnam_r(lname, &pwd, buf, size, &pw);
		free(buf);
		if (pw != NULL) {
			*uidp = pw->pw_uid;
			return (GSS_S_COMPLETE);
		} else {
			if (error == ERANGE &&
			    size <= SIZE_MAX - PWBUF_SIZE_INC)
				continue;
			return (GSS_S_FAILURE);
		}
	}
Received on Tue Feb 19 2013 - 08:31:47 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:35 UTC