Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Feb 2013 11:31:42 +0200
From:      Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua>
To:        Elias Martenson <lokedhs@gmail.com>
Cc:        Rick Macklem <rmacklem@uoguelph.ca>, Benjamin Kaduk <kaduk@mit.edu>, freebsd-current@freebsd.org
Subject:   Re: Possible bug in NFSv4 with krb5p security?
Message-ID:  <20130219093142.GA1459@pm513-1.comsys.ntu-kpi.kiev.ua>
In-Reply-To: <CADtN0WKVzbKxhaLQw8y2KLhhRJC9n4ht9wyPmGQ%2BpHqSjQkVNw@mail.gmail.com>
References:  <CADtN0WLs%2B=EtM4VnHcvxdihbKx4kjaoMQZK61F%2BnKx%2BDpAqrfg@mail.gmail.com> <477291850.3084864.1361113135205.JavaMail.root@erie.cs.uoguelph.ca> <CADtN0WKVzbKxhaLQw8y2KLhhRJC9n4ht9wyPmGQ%2BpHqSjQkVNw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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);
		}
	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130219093142.GA1459>