From nobody@FreeBSD.ORG Thu Oct  7 22:58:45 1999
Return-Path: <nobody@FreeBSD.ORG>
Received: by hub.freebsd.org (Postfix, from userid 32767)
	id 127E3157E8; Thu,  7 Oct 1999 22:58:45 -0700 (PDT)
Message-Id: <19991008055845.127E3157E8@hub.freebsd.org>
Date: Thu,  7 Oct 1999 22:58:45 -0700 (PDT)
From: robertw@wojo.com
Sender: nobody@FreeBSD.ORG
To: freebsd-gnats-submit@freebsd.org
Subject: setpassent() in libc does not function properly
X-Send-Pr-Version: www-1.0

>Number:         14201
>Category:       kern
>Synopsis:       setpassent() in libc does not function properly
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct  7 23:00:00 PDT 1999
>Closed-Date:    Sat Oct 16 04:53:39 PDT 1999
>Last-Modified:  Sat Oct 16 04:54:27 PDT 1999
>Originator:     Robert S. Wojciechowski Jr.
>Release:        FreeBSD 3.3-RELEASE i386
>Organization:
>Environment:
FreeBSD max.millenniumworks.com 3.3-RELEASE FreeBSD 3.3-RELEASE #9: Sun Oct  3 02:40:16 EDT 1999     root@max.millenniumworks.com:/usr/src/sys/compile/MYKERNEL  i386
>Description:
(This was taken from another post, just reposting this bug on 3.3-RELEASE)

The manual page for the setpassent(int stayopen) function says :

"The setpassent() function accomplishes two purposes.  First, it
causes getpwent() to ``rewind'' to the beginning of the database.
Additionally, if stayopen is non-zero, file descriptors are left open,
significantly speeding up subsequent accesses for all of the routines.
(This latter functionality is unnecessary for getpwent() as it doesn't
close its file descriptors by default.)"

The problem is that in the file getpwent.c which implements the
setpassent() function in the libc, the stayopen variable seems not
used. And then, code like setpassent(1) doesn't work as expected.

This problem is particularly annoying with ProFTPD
(/usr/ports/net/proftpd) which uses a such code.

>How-To-Repeat:
The problem is visible using ProFTPD (latest at the time of this bug report is 1.2.0pre8).
>Fix:
(Again taken from the previous post.  It's a quick one line fix!!)

A patch has been proposed by Adam Mackler
(mackler@barter.dewline.com). It adds a "if" to check the value of
"_pw_stayopen" BEFORE calling "endpwent()".

	
Adam Mackler writes:
 > > Date: Thu, 6 Aug 1998 17:50:08 -0400
 > > From: Floody <flood@evcom.net>
 > > Reply-To: proftpd-l@evcom.net
 > > To: Karl Pielorz <kpielorz@tdx.co.uk>
 > > Cc: proftpd-l@evcom.net
 > > Subject: Re: [proftpd-l] New ProFTPd user - Security, Incoming and pwd.db?
 > > 
 > > Ok.  I put up a test FreeBSD 2.2.7 system.  There appears to be a libc
 > > problem with the setpassent() function, which doesn't work on FreeBSD as
 > > documented in the man pages (or on any other BSD).  This is the heart of
 > > the problem.  There is no workaround until libc is fixed.
 > 
 > Hi:
 > 
 > I think the following patch may fix the problem, but I'm afraid
 > I don't know how to rebuild my c library.  If you find out if this
 > works can you let me know?  Thanks.
 > 
 > 
 > *** getpwent.c  Wed Aug 19 02:00:13 1998
 > --- getpwent.c.dist     Wed Aug 19 01:58:33 1998
 > ***************
 > *** 194,201 ****
 >         if (rval && (_pw_passwd.pw_name[0] == '+'||
 >                         _pw_passwd.pw_name[0] == '-')) rval = 0;
 >   
 > !       if (!_pw_stayopen)
 > !         endpwent();
 >         return(rval ? &_pw_passwd : (struct passwd *)NULL);
 >   }
 >   
 > --- 194,200 ----
 >         if (rval && (_pw_passwd.pw_name[0] == '+'||
 >                         _pw_passwd.pw_name[0] == '-')) rval = 0;
 >   
 > !       endpwent();
 >         return(rval ? &_pw_passwd : (struct passwd *)NULL);
 >   }
 >   
 > 
 > -- 
 > Adam Mackler
 > Dewline Communications, LLC
 > 212-505-9149
 > 



>Release-Note:
>Audit-Trail:

From: "Robert Wojciechowski Jr." <robertw@wojo.com>
To: "'freebsd-gnats-submit@freebsd.org'" <freebsd-gnats-submit@freebsd.org>,
	"Robert Wojciechowski Jr." <robertw@wojo.com>
Cc:  
Subject: Re: kern/14201: setpassent() in libc does not function properly
Date: Fri, 8 Oct 1999 02:56:48 -0400 

 The patch in this bug report does not work fully.  I patched the endpwent()
 function, and it works correctly now:
 
 244,246d243
 <     if (_pw_stayopen)
 <       return;
 <
 
 It will keep the fd open when setpassent(int stayopen) is passed 1.  It's
 now behaving the way it should ;)
 
 Thanks,
 
 Robert S. Wojciechowski Jr.
 robertw@wojo.com
 
 PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
 
 

From: Ruslan Ermilov <ru@ucb.crimea.ua>
To: "Robert Wojciechowski Jr." <robertw@wojo.com>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/14201: setpassent() in libc does not function properly
Date: Fri, 8 Oct 1999 10:20:06 +0300

 On Fri, Oct 08, 1999 at 12:00:01AM -0700, Robert Wojciechowski Jr. wrote:
 > 
 >  The patch in this bug report does not work fully.  I patched the endpwent()
 >  function, and it works correctly now:
 >  
 >  244,246d243
 >  <     if (_pw_stayopen)
 >  <       return;
 >  <
 >  
 >  It will keep the fd open when setpassent(int stayopen) is passed 1.  It's
 >  now behaving the way it should ;)
 >  
 And endpwent() will never close the file :-(
 
 -- 
 Ruslan Ermilov		Sysadmin and DBA of the
 ru@ucb.crimea.ua	United Commercial Bank,
 ru@FreeBSD.org		FreeBSD committer,
 +380.652.247.647	Simferopol, Ukraine
 
 http://www.FreeBSD.org	The Power To Serve
 http://www.oracle.com	Enabling The Information Age
 

From: Stephane Legrand <Stephane.Legrand@bigfoot.com>
To: robertw@wojo.com
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: kern/14201: setpassent() in libc does not function properly
Date: Fri, 8 Oct 1999 10:11:15 +0200 (CEST)

 robertw@wojo.com writes:
  > 
  > >Number:         14201
  > >Category:       kern
  > >Synopsis:       setpassent() in libc does not function properly
  > >Confidential:   no
  > >Severity:       serious
  > >Priority:       high
  > >Responsible:    freebsd-bugs
  > >State:          open
  > >Quarter:        
  > >Keywords:       
  > >Date-Required:
  > >Class:          sw-bug
  > >Submitter-Id:   current-users
  > >Arrival-Date:   Thu Oct  7 23:00:00 PDT 1999
  > >Closed-Date:
  > >Last-Modified:
  > >Originator:     Robert S. Wojciechowski Jr.
  > >Release:        FreeBSD 3.3-RELEASE i386
  > >Organization:
  > >Environment:
  > FreeBSD max.millenniumworks.com 3.3-RELEASE FreeBSD 3.3-RELEASE #9:
  > Sun Oct 3 02:40:16 EDT 1999
  > root@max.millenniumworks.com:/usr/src/sys/compile/MYKERNEL i386
  > >Description:
  > (This was taken from another post, just reposting this bug on 3.3-RELEASE)
  > 
 
 Yes, indeed :) . This is the same bug report than the kern/7781.
 
 
  > The manual page for the setpassent(int stayopen) function says :
  > 
  > "The setpassent() function accomplishes two purposes.  First, it
  > causes getpwent() to ``rewind'' to the beginning of the database.
  > Additionally, if stayopen is non-zero, file descriptors are left open,
  > significantly speeding up subsequent accesses for all of the routines.
  > (This latter functionality is unnecessary for getpwent() as it doesn't
  > close its file descriptors by default.)"
  > 
  > The problem is that in the file getpwent.c which implements the
  > setpassent() function in the libc, the stayopen variable seems not
  > used. And then, code like setpassent(1) doesn't work as expected.
  > 
  > This problem is particularly annoying with ProFTPD
  > (/usr/ports/net/proftpd) which uses a such code.
  > 
  > >How-To-Repeat:
  > The problem is visible using ProFTPD (latest at the time of this bug report is 1.2.0pre8).
  > >Fix:
  > (Again taken from the previous post.  It's a quick one line fix!!)
  > 
  > A patch has been proposed by Adam Mackler
  > (mackler@barter.dewline.com). It adds a "if" to check the value of
  > "_pw_stayopen" BEFORE calling "endpwent()".
  > 
  > 	
  > Adam Mackler writes:
  >  > > Date: Thu, 6 Aug 1998 17:50:08 -0400
  >  > > From: Floody <flood@evcom.net>
  >  > > Reply-To: proftpd-l@evcom.net
  >  > > To: Karl Pielorz <kpielorz@tdx.co.uk>
  >  > > Cc: proftpd-l@evcom.net
  >  > > Subject: Re: [proftpd-l] New ProFTPd user - Security, Incoming and pwd.db?
  >  > > 
  >  > > Ok.  I put up a test FreeBSD 2.2.7 system.  There appears to be a libc
  >  > > problem with the setpassent() function, which doesn't work on FreeBSD as
  >  > > documented in the man pages (or on any other BSD).  This is the heart of
  >  > > the problem.  There is no workaround until libc is fixed.
  >  > 
  >  > Hi:
  >  > 
  >  > I think the following patch may fix the problem, but I'm afraid
  >  > I don't know how to rebuild my c library.  If you find out if this
  >  > works can you let me know?  Thanks.
  >  > 
  >  > 
  >  > *** getpwent.c  Wed Aug 19 02:00:13 1998
  >  > --- getpwent.c.dist     Wed Aug 19 01:58:33 1998
  >  > ***************
  >  > *** 194,201 ****
  >  >         if (rval && (_pw_passwd.pw_name[0] == '+'||
  >  >                         _pw_passwd.pw_name[0] == '-')) rval = 0;
  >  >   
  >  > !       if (!_pw_stayopen)
  >  > !         endpwent();
  >  >         return(rval ? &_pw_passwd : (struct passwd *)NULL);
  >  >   }
  >  >   
  >  > --- 194,200 ----
  >  >         if (rval && (_pw_passwd.pw_name[0] == '+'||
  >  >                         _pw_passwd.pw_name[0] == '-')) rval = 0;
  >  >   
  >  > !       endpwent();
  >  >         return(rval ? &_pw_passwd : (struct passwd *)NULL);
  >  >   }
  >  >   
  >  > 
  >  > -- 
  >  > Adam Mackler
  >  > Dewline Communications, LLC
  >  > 212-505-9149
  >  > 
  > 
 
 -- 
 Stephane.Legrand@bigfoot.com
 FreeBSD Francophone : http://www.freebsd-fr.org/
 

From: "Robert Wojciechowski Jr." <robertw@wojo.com>
To: 'Ruslan Ermilov' <ru@ucb.crimea.ua>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: RE: kern/14201: setpassent() in libc does not function properly
Date: Fri, 8 Oct 1999 17:43:59 -0400 

 A test for this bug is:
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <pwd.h>
 
 int main()
 {
   setpassent(1);
   getpwent();
 
   chroot("/usr");
   chdir("/");
   if(!getpwuid(0)) {
     printf("setpassent doesn't appear to work\n");
   } else {
     if(!getpwuid(0))
       printf("second getpwuid(0) didn't work\n");
     else
       printf("setpassent works\n");
   }
   return 0;
 }
 
 Right now, the second getpwuid(0) call fails.  Adding the if (!_pw_stayopen)
 before the endpwent() in both getpwnam() and getpwuid() lets this test pass,
 but is it a sufficient fix?
 
 Is a closing call to endpwent() necessary for a program to correctly close
 the database?
 
 Robert S. Wojciechowski Jr.
 robertw@wojo.com
 
 PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
 
 

From: "Robert Wojciechowski Jr." <robertw@wojo.com>
To: 'Ruslan Ermilov' <ru@ucb.crimea.ua>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: RE: kern/14201: setpassent() in libc does not function properly
Date: Fri, 8 Oct 1999 22:31:04 -0400 

 Ruslan, 
 
 Looks like the original patch works the best.  It works well too.  If you
 look in getgrent.c, it contains the right code to handle the stayopen flag:
 
        /* correct, from getgrent.c */
        if (!_gr_stayopen)
                 endgrent();
         return(rval ? &_gr_group : NULL);
 
 instead of
 
         /* incorrect */
         endgrent();
         return(rval ? &_gr_group : NULL);
 
 The incorrect code is what getpwent.c contains.  A test for this
 functionality is the following program:
 
 --SNIP--
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <pwd.h>
 
 int main()
 {
   setpassent(1);
   getpwent();
 
   chroot("/usr");
   chdir("/");
   if(!getpwuid(0)) {
     printf("setpassent doesn't appear to work\n");
   } else {
     if(!getpwuid(0))
       printf("second getpwuid(0) didn't work\n");
     else
       printf("setpassent works\n");
   }
   return 0;
 }
 --SNIP--
 
 It passes with flying colors after the fix.  
 
 Best regards,
 
 Robert S. Wojciechowski Jr.
 robertw@wojo.com
 
 PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
 
 -----Original Message-----
 From: Ruslan Ermilov [mailto:ru@ucb.crimea.ua]
 Sent: Friday, October 08, 1999 3:20 AM
 To: Robert Wojciechowski Jr.
 Cc: freebsd-gnats-submit@FreeBSD.org
 Subject: Re: kern/14201: setpassent() in libc does not function properly
 
 On Fri, Oct 08, 1999 at 12:00:01AM -0700, Robert Wojciechowski Jr. wrote:
 >
 >  The patch in this bug report does not work fully.  I patched the
 endpwent()
 >  function, and it works correctly now:
 > 
 >  244,246d243
 >  <     if (_pw_stayopen)
 >  <       return;
 >  <
 > 
 >  It will keep the fd open when setpassent(int stayopen) is passed 1.  It's
 >  now behaving the way it should ;)
 > 
 And endpwent() will never close the file :-(
 
 --
 Ruslan Ermilov          Sysadmin and DBA of the
 ru@ucb.crimea.ua        United Commercial Bank,
 ru@FreeBSD.org          FreeBSD committer,
 +380.652.247.647        Simferopol, Ukraine
 
 http://www.FreeBSD.org  The Power To Serve
 http://www.oracle.com   Enabling The Information Age
 

From: "Robert Wojciechowski Jr." <robertw@wojo.com>
To: "'freebsd-gnats-submit@freebsd.org'" <freebsd-gnats-submit@freebsd.org>
Cc:  
Subject: Re: kern/14201: setpassent() in libc does not function properly
Date: Sat, 9 Oct 1999 02:02:42 -0400 

 Problem crept in on this update (1.11):
 
 http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/gen/getpwent.c.diff?r1=1.
 10&r2=1.11
 
 Robert S. Wojciechowski Jr.
 robertw@wojo.com
 
 PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
 
 

From: "Robert Wojciechowski Jr." <robertw@wojo.com>
To: "'freebsd-gnats-submit@freebsd.org'" <freebsd-gnats-submit@freebsd.org>
Cc:  
Subject: Re: kern/14201: setpassent() in libc does not function properly
Date: Mon, 11 Oct 1999 15:56:43 -0400

 Working and tested patch (adopted from OpenBSD and NetBSD):
 
 
 -- BEGIN PATCH --
 --- getpwent.c.orig     Mon Oct 11 15:34:56 1999
 +++ getpwent.c  Mon Oct 11 14:59:42 1999
 @@ -176,7 +176,10 @@
         if (rval && (_pw_passwd.pw_name[0] == '+'||
                         _pw_passwd.pw_name[0] == '-')) rval = 0;
 
 -       endpwent();
 +       if (!_pw_stayopen) {
 +         (void)(_pw_db->close)(_pw_db);
 +         _pw_db = (DB *)NULL;
 +       }
         return(rval ? &_pw_passwd : (struct passwd *)NULL);
  }
 
 @@ -216,7 +219,10 @@
         if (rval && (_pw_passwd.pw_name[0] == '+'||
                         _pw_passwd.pw_name[0] == '-')) rval = 0;
 
 -       endpwent();
 +       if (!_pw_stayopen) {
 +         (void)(_pw_db->close)(_pw_db);
 +         _pw_db = (DB *)NULL;
 +        }
         return(rval ? &_pw_passwd : (struct passwd *)NULL);
  }
 -- END PATCH --
 
 
 Robert S. Wojciechowski Jr.
 robertw@wojo.com
 
 PGP: 0xF2CA68F2 - http://www.wojo.com/pgpkeys/robertw.asc
 
 
State-Changed-From-To: open->closed 
State-Changed-By: ache 
State-Changed-When: Sat Oct 16 04:53:39 PDT 1999 
State-Changed-Why:  
Just fixed 
>Unformatted:
