Subject: [496] changes for wu-ftpd-2.4

From: [email-masked]
Date: Thu, 29 Sep 1994 16:36:29 +0100

Hi folks,

following changes I had make in my downloaded wu-ftpd-2.4.

Fixes or add on:

 o check execute permission in ftpd_popen() for better performance/errorhandling
 o added optional dirmode permissions for upload
 o change home directory to / if chrooted anonymous ftp
 o if /path1/./path2 syntax in guestgroup - change home directory to /path2
 
Comments or corrections are welcome. 

Note: It's not recommendable to make this changes w/o to know what you do. ;-)

Wolfgang Peinel
[email-masked]

***************************** popen.c *****************************************
.
.
.
>#include <sys/errno.h>
.
.
.

in ftpd_popen()
	.
	.
	.
 	for (argc = 0, cp = program;; cp = NULL)
>		/* let's hope nobody use direct or indirect ftpd_popen() in a 
>	   	   strtok() loop in the calling functions */
		if (!(argv[argc++] = strtok(cp, " \t\n")))
            break;

>	if (argv[0] == NULL || access(argv[0], X_OK) != 0)
>	{   errno = EACCES;
>           return NULL;
>       }
	.
	.
	.

****************************** ftpd.c *****************************************
in function makedir()
    .
>   int d_mode;
    .
    .

    /*
     * check the directory, can we mkdir here?
     */
!   if ( (dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0 )
	return;

     /*
     * check the filename, is it legal?
     */
    if ( (fn_check(name)) <= 0 )
        return;

> #ifdef UPLOAD
>     if (d_mode >= 0)
>     {   mode_t oldmask = umask(0);
>         if (mkdir(name, d_mode) < 0) {
>             umask(oldmask);
>             perror_reply(550, name);
>             return;
>         }
>         umask(oldmask);
>         if (valid > 0)
>         {   uid_t olduid = getuid();
>             (void)seteuid((uid_t) 0);
>             if (chown(name, uid, gid) != 0)
>             {   (void)seteuid(olduid);
>                 perror_reply(550, "chown");
>                 return;
>             }
>             (void)seteuid(olduid);
>         }
>     }
>     else
> #endif
    if (mkdir(name, 0777) < 0) {
        perror_reply(550, name);
        return;
    }

    .
    .
    .
------------------------------------------------------------------------------
in function pass()
    .
    .
    .
    if (anonymous || guest) {
> #ifdef AIX
>       /* setegid() don't work on my AIX Machine, why? */
>       (void)setgid(pw->pw_gid);
> #endif
        /* We MUST do a chdir() after the chroot. Otherwise the old current
         * directory will be accessible as "." outside the new root! */
	 if (anonymous) {
            if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
                reply(550, "Can't set guest privileges.");
                goto bad;
            }
>	    pw->pw_dir = "/";
	 } else if (guest) {
            char *sp;

            /* determine root and home directory */

            if ((sp = strstr(pw->pw_dir, "/./")) == NULL) {
                if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
                    reply(550, "Can't set guest privileges.");
                    goto bad;
                }
            } else {
                *sp++ = '\0';

                if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
                    reply(550, "Can't set guest privileges.");
                    goto bad;
                }
>		/* work on all unix platforms w/o const array! */
>               pw->pw_dir = sp;
            }
        }
    .
    .
    .
-------------------------------------------------------------------------------
in removedir()
    .
    .
    .
!   if ( (dir_check(name, &c, &d, (int*)0, &valid)) <= 0 )
        return;
    .
    .
    .
------------------------------------------------------------------------------
in statfilecmd()
    .
    .
    .
    (void) sprintf(line, ls_short, filename);
!   if ((fin = ftpd_popen(line, "r", 0)) == NULL)
>   {   perror_reply(551, filename);
>       return;
>   }
    lreply(211, "status of %s:", filename);
    .
    .
    .
******************************* extensions.c **********************************
in dir_check()

int
!dir_check(char *name, uid_t *uid, gid_t *gid, int *d_mode, int *valid)
{
    .
    .
    .
	*ap4 = NULL,
>       *ap5 = NULL,
        *ap6 = NULL;
    .
    .
    .
	if (ARG4)  ap4 = ARG4;
        else       ap4 = NULL;
>       if (ARG5)  ap5 = ARG5;
>       else       ap5 = NULL;
        if (ARG6)  ap6 = ARG6;
        else       ap6 = NULL;
    .
    .
    .
    if (ap4) {
     *gid = atoi(ap4);    /* the gid  */
     *valid = 1;
    }
>   if (ap5 && d_mode != (int*)0)
>   {   *d_mode = -1;
> 	/* optional syntax: upload ... filemode/dirmode ... */
>       sscanf(ap5,"%*o/%o", d_mode);
>   }
    .
    .
    .
*******************************************************************************