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>