From owner-freebsd-current@FreeBSD.ORG Tue Feb 19 10:27:47 2013 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 19CB23A7 for ; Tue, 19 Feb 2013 10:27:47 +0000 (UTC) (envelope-from simon@comsys.ntu-kpi.kiev.ua) Received: from comsys.kpi.ua (comsys.kpi.ua [77.47.192.42]) by mx1.freebsd.org (Postfix) with ESMTP id C898C26C for ; Tue, 19 Feb 2013 10:27:46 +0000 (UTC) Received: from pm513-1.comsys.kpi.ua ([10.18.52.101] helo=pm513-1.comsys.ntu-kpi.kiev.ua) by comsys.kpi.ua with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1U7kQJ-0007Pa-SL; Tue, 19 Feb 2013 12:27:43 +0200 Received: by pm513-1.comsys.ntu-kpi.kiev.ua (Postfix, from userid 1001) id 3D5921CC1E; Tue, 19 Feb 2013 12:27:44 +0200 (EET) Date: Tue, 19 Feb 2013 12:27:44 +0200 From: Andrey Simonenko To: Elias Martenson Subject: Re: Possible bug in NFSv4 with krb5p security? Message-ID: <20130219102744.GA2426@pm513-1.comsys.ntu-kpi.kiev.ua> References: <477291850.3084864.1361113135205.JavaMail.root@erie.cs.uoguelph.ca> <20130219093142.GA1459@pm513-1.comsys.ntu-kpi.kiev.ua> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Authenticated-User: simon@comsys.ntu-kpi.kiev.ua X-Authenticator: plain X-Sender-Verify: SUCCEEDED (sender exists & accepts mail) X-Exim-Version: 4.63 (build at 28-Apr-2011 07:11:12) X-Date: 2013-02-19 12:27:43 X-Connected-IP: 10.18.52.101:19328 X-Message-Linecount: 90 X-Body-Linecount: 70 X-Message-Size: 3637 X-Body-Size: 2599 Cc: Rick Macklem , Benjamin Kaduk , freebsd-current@freebsd.org X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Feb 2013 10:27:47 -0000 On Tue, Feb 19, 2013 at 05:35:50PM +0800, Elias Martenson wrote: > On 19 February 2013 17:31, Andrey Simonenko wrote: > > 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): > > > > Is this really a better solution than to aim high right away? A series of > malloc() calls should certainly have much higher overhead than the previous > stack-allocated solution. > > A better compromise would be to do the lookup in a separate function, that > allocates the buffer using alloca() instead, yes? I cannot find how to get information about maximum buffer size for the getpwnam_r() function. This information should be returned by sysconf(_SC_GETPW_R_SIZE_MAX), but since it does not work on FreeBSD it is necessary to guess its size. Original value is 128 and it works for somebody, 1024 works for your environment, but it can fail for another environment. SUSv4 specifies "Storage referenced by the structure is allocated from the memory provided with the buffer parameter", but then tells about groups in EXAMPLE for getpwnam_r() "Note that sysconf(_SC_GETPW_R_SIZE_MAX) may return -1 if there is no hard limit on the size of the buffer needed to store all the groups returned". malloc() can give overhead, but that function can try to call getpwnam_r() with buffer allocated from stack and if getpwnam_r() failed with ERANGE use dynamically allocated buffer. #define PWBUF_SIZE_INI (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) #define PWBUF_SIZE_INC 128 char bufs[2 * MAXLOGNAME + MAXPATHLEN + PASSWORD_LEN + 1 + 32]; error = getpwnam_r(lname, &pwd, bufs, sizeof(bufs), &pw); if (pw != NULL) { *uidp = pw->pw_uid; return (GSS_S_COMPLETE); } else if (error != ERANGE) return (GSS_S_FAILURE); 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); } }