Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Jan 2001 08:10:02 -0800 (PST)
From:      Daniel Hagan <dhagan@colltech.com>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/23944: Proposed modification to ftpd
Message-ID:  <200101041610.f04GA2276727@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/23944; it has been noted by GNATS.

From: Daniel Hagan <dhagan@colltech.com>
To: freebsd-audit@freebsd.org
Cc: freebsd-gnats-submit@freebsd.org,
	fschapachnik@vianetworks.com.ar, greid@dogma.freebsd-uk.eu.org
Subject: Re: bin/23944: Proposed modification to ftpd
Date: Thu, 4 Jan 2001 11:05:58 -0500 (EST)

 I've rewritten some of your patch to not use dangling pointers.  I also 
 added the cd_dir functionality to the ftp guest account, not because I
 think it's a great idea, but because it will be consistent behavior.
 (If someone had specified /info/ftp/./pub as HOME for ftp, your patch would
 have chroot'd ftp into /info/ftp/pub, instead of /info/ftp.  And this 'bug'
 would only appear for the ftp account.  ;-))
 
 In the event that this mail doesn't get munged the way I'd like, please 
 respond to dhagan@colltech.com
 
 Thanks,
 
 Daniel
 
 
 Index: ftpcmd.y
 ===================================================================
 RCS file: /raid/ncvs/src/libexec/ftpd/ftpcmd.y,v
 retrieving revision 1.19
 diff -u -r1.19 ftpcmd.y
 --- ftpcmd.y	2000/12/16 19:19:19	1.19
 +++ ftpcmd.y	2001/01/04 15:55:42
 @@ -92,6 +92,8 @@
  extern  char tmpline[];
  extern	int readonly;
  extern	int noepsv;
 +extern	int dochroot;
 +extern	char *cd_dir, *chroot_dir;
  
  off_t	restart_point;
  
 @@ -505,8 +507,11 @@
  	| CWD check_login CRLF
  		{
  			if ($2) {
 -				if (guest)
 -					cwd("/");
 +				if (guest || dochroot)
 +					if (cd_dir != NULL) 
 +						cwd(cd_dir);
 +					else
 +						cwd("/");
  				else
  					cwd(pw->pw_dir);
  			}
 Index: ftpd.8
 ===================================================================
 RCS file: /raid/ncvs/src/libexec/ftpd/ftpd.8,v
 retrieving revision 1.36
 diff -u -r1.36 ftpd.8
 --- ftpd.8	2000/12/18 08:33:25	1.36
 +++ ftpd.8	2001/01/04 15:46:24
 @@ -311,13 +311,14 @@
  or the user is a member of a group with a group entry in this file,
  i.e. one prefixed with
  .Ql \&@ ,
 -the session's root will be changed to the user's login directory by
 +the session's root will be changed to the user's login directory (up to the first /./) by
  .Xr chroot 2
  as for an
  .Dq anonymous
  or
  .Dq ftp
  account (see next item).
 +The user is placed into the directory that remainds after stripping the former from the user's login directory.
  This facility may also be triggered by enabling the boolean "ftp-chroot"
  capability in
  .Xr login.conf 5 .
 Index: ftpd.c
 ===================================================================
 RCS file: /raid/ncvs/src/libexec/ftpd/ftpd.c,v
 retrieving revision 1.72
 diff -u -r1.72 ftpd.c
 --- ftpd.c	2000/12/20 03:34:54	1.72
 +++ ftpd.c	2001/01/04 15:56:59
 @@ -140,6 +140,7 @@
  int	anon_only = 0;    /* Only anonymous ftp allowed */
  int	guest;
  int	dochroot;
 +char   *cd_dir = NULL, *chroot_dir = NULL;
  int	stats;
  int	statfd = -1;
  int	type;
 @@ -188,6 +189,9 @@
  
  char	*pid_file = NULL;
  
 +/* WARNING: FTP_CHROOT_SEPARATOR *MUST* end in / */
 +#define FTP_CHROOT_SEPARATOR   "/./"
 +
  /*
   * Timeout intervals for retrying connections
   * to hosts that don't accept PORT cmds.  This
 @@ -251,6 +255,7 @@
  static char	*sgetsave __P((char *));
  static void	 reapchild __P((int));
  static void      logxfer __P((char *, long, long));
 +static void      get_chroot_and_cd_dirs __P((char *, char **, char **));
  
  static char *
  curdir()
 @@ -1038,6 +1043,8 @@
  	logged_in = 0;
  	guest = 0;
  	dochroot = 0;
 +       free(chroot_dir);
 +       free(cd_dir);
  }
  
  #if !defined(NOPAM)
 @@ -1291,19 +1298,20 @@
  		login_getcapbool(lc, "ftp-chroot", 0) ||
  #endif
  		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
 -	if (guest) {
 +	if (guest || dochroot) {
  		/*
  		 * We MUST do a chdir() after the chroot. Otherwise
  		 * the old current directory will be accessible as "."
  		 * outside the new root!
  		 */
 -		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
 -			reply(550, "Can't set guest privileges.");
 -			goto bad;
 -		}
 -	} else if (dochroot) {
 -		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
 -			reply(550, "Can't change root.");
 +		get_chroot_and_cd_dirs(pw->pw_dir, &chroot_dir, &cd_dir);
 +		/*
 +		 * Do not free chroot_dir & cd_dir b/c they are used in
 +		 * processing CWD commands from client.  They should be 
 +		 * free'd during a user logout.
 +		 */
 +		if (chroot(chroot_dir) < 0 || chdir(cd_dir) < 0) {
 +			reply(550, guest ? "Can't set guest privileges." : "Can't change root.");
  			goto bad;
  		}
  	} else if (chdir(pw->pw_dir) < 0) {
 @@ -2802,5 +2810,50 @@
  			ctime(&now)+4, ident, remotehost,
  			path, name, size, now - start + (now == start));
  		write(statfd, buf, strlen(buf));
 +       }
 +}
 +
 +/*
 + * Make a pointer to the chroot dir and another to the cd dir.
 + * The first is all the path up to the first FTP_CHROOT_SEPARATOR.
 + * The later is the remaining chars, not including the FTP_CHROOT_SEPARATOR,
 + * but prepending a '/', if FTP_CHROOT_SEPARATOR is found.
 + * Otherwise, return user_home_dir as chroot_dir and "/" as cd_dir.
 + */
 +static void
 +get_chroot_and_cd_dirs(user_home_dir, chroot_dir, cd_dir)
 +       char *user_home_dir;
 +       char **chroot_dir;
 +       char **cd_dir;
 +{
 +       char *p;
 +
 +       /* Make a pointer to first character of string FTP_CHROOT_SEPARATOR
 +          inside user_home_dir. */
 +       p = (char *) strstr(user_home_dir, FTP_CHROOT_SEPARATOR);
 +       if (p == NULL) {
 +                /*
 +                 * There is not FTP_CHROOT_SEPARATOR string inside
 +                 * user_home_dir. Return user_home_dir as chroot_dir,
 +                 * and "/" as cd_dir.
 +                 */
 +                if ((*chroot_dir = (char *) strdup(user_home_dir)) == NULL)
 +                       fatal("Ran out of memory.");
 +                if ((*cd_dir = (char *) strdup("/")) == NULL)
 +                       fatal("Ran out of memory.");
 +       } else {
 +                /*
 +                 * Use strlen(user_home_dir) as maximun length for
 +                 * both cd_dir and chroot_dir, as both are substrings of
 +                 * user_home_dir.
 +                 */
 +                if ((*chroot_dir = malloc(strlen(user_home_dir))) == NULL)
 +                       fatal("Ran out of memory.");
 +                if ((*cd_dir = malloc(strlen(user_home_dir))) == NULL)
 +                       fatal("Ran out of memory.");
 +                (void) strncpy(*chroot_dir, user_home_dir, p-user_home_dir);
 +                /* Skip FTP_CHROOT_SEPARATOR (except the last /). */
 +                p += strlen(FTP_CHROOT_SEPARATOR)-1;
 +                (void) strncpy(*cd_dir, p, strlen(p));
  	}
  }
 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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