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