Subject: Regular expressions in "noretrieve" directive.

From: [email-masked] (William L. Sebok)
Date: Tue, 22 Apr 1997 13:21:10 -0400 (EDT)

We have been bothered by software pirates lately who use our anonymous ftp
site to distribute pirated software.  We have had two publicly writable
directories in the anonymous ftp area /pub and /incoming, traditionally used
for downloading and uploading respectively.  To eject the software pirates I
would like to enforce that tradition and deny uploading into /pub and uploading
into /incoming.  The first is easy with the context of the ftp daemon.  However
there is no explicit command in wu-ftpd to deny downloading from a directory.
There is the noretrieve command but that only denied downloading of individual
files -- as "man ftpaccess" says "No globbing is done."  What I have now done
is to patch wu-ftpd-2.4.2-beta-13 to allow the use of globbing in the noretrieve
command.

I know that the traditional way to handle this is to make /incoming and the
files placed there unreadable by the ftp daemon. However I believe that using
this hack to ftpd is easier on legitimate users.  Making the directory
unreadable complicates life for the hackers but does not stop them -- they
still would know the name of the files they placed there and can report them
as such to their hacker bulletin boards.  Making the files themself unreadable
is a solution more appropriate for an institution where a single person with
appropriate privileges picks up the incoming files. I would like any user with
an account here to be able to pick up files for them with no special
arrangements.  On Unix is it easy to make file readable by only a person or a
group but hard to arrange permissions make it readable by everyone except by
the ftp daemon.  One could arrange to have a daemon move incoming files to an
area inaccessible by anonymous ftp and open up the permissions on the moved
files.  Still, I believe that handling the problem within the ftp daemon is
easier for the legitimate user to understand than such a scheme that moves the
files to who-knows-where.

I consider this patch a hack.  I believe that the proper fix would implement a
"download" command with the same syntax and options as the present "upload"
command.  Still, this patch did the job and was quick to implement.

Bill Sebok      Computer Software Manager, Univ. of Maryland, Astronomy
	Internet: [email-masked]	URL: http://www.astro.umd.edu/~wls/

Patch against wu-ftpd-2.4.2-beta-13:

*** src/extensions.c.ORIG	Mon Mar  3 04:39:54 1997
--- src/extensions.c	Mon Apr 21 16:51:06 1997
***************
*** 1113,1118 ****
--- 1113,1120 ----
  }
  
  /* The following is from the Debian add-ons. */
+ /* hacked by W. Sebok ([email-masked]) to support regex expressions in
+  * noretrieve expressions */
  
  #define lbasename(x) (strrchr(x,'/')?1+strrchr(x,'/'):x)
  
***************
*** 1125,1130 ****
--- 1127,1133 ----
  #endif
  {
    char cwd[MAXPATHLEN+1], realwd[MAXPATHLEN+1], realname[MAXPATHLEN+1];
+   char *p, *q;
    int i;
    struct aclmember *entry = NULL;
  
***************
*** 1144,1161 ****
          if (ARG0 == (char *)NULL)
              continue;
  	for (i = 0; i< MAXARGS && 
! 	     (entry->arg[i] != (char *)NULL) && (*(entry->arg[i]) !='\0'); i++)
! 	  if (strcmp (((*(entry->arg[i]) == '/') ? realname : 
! 			lbasename (realname)), entry->arg[i]) == 0)
  	  {
! 	    reply (550, "%s is marked unretrievable", entry->arg[i]);
  	    return 1;
  	  }
        }
     return 0;
  }

--- 1147,1209 ----
          if (ARG0 == (char *)NULL)
              continue;
  	for (i = 0; i< MAXARGS && 
! 	     ((q = entry->arg[i]) != (char *)NULL) && (*q !='\0'); i++) {
! 	  p = (*q == '/') ? realname : lbasename (realname);
! 	  if (strcmp (p , q) == 0 || regexmatch(p, q))
  	  {
! 	    reply (550, "%s is marked unretrievable", p);
  	    return 1;
  	  }
+ 	}
        }
     return 0;
  }
  
+ int
+ regexmatch(name, rgexp)
+ char *name, *rgexp;
+ {
  
+ #ifdef M_UNIX
+ # ifdef REGEX
+   char *regp;
+ # endif
+ #endif
  
+ #ifdef REGEXEC
+   regex_t regexbuf;
+   regmatch_t regmatchbuf;
+ #else
+   char *sp;
+ #endif
  
+ #if defined(REGEXEC)
+ 	if (regcomp(&regexbuf, rgexp, REG_EXTENDED) != 0) {
+ 	    reply(553, "REGEX error");
+ #elif defined(REGEX)
+ 	if ((sp = regcmp(rgexp, (char *) 0)) == NULL) {
+ 	    reply(553, "REGEX error");
+ #else
+ 	if ((sp = re_comp(rgexp)) != 0) {
+ 	    perror_reply(553, sp);
+ #endif
+ 	    return(0);
+ 	}
  
+ #if defined(REGEXEC)
+ 	if (regexec(&regexbuf, name, 1, &regmatchbuf, 0) != 0) {
+ #elif defined(REGEX)
+ # ifdef M_UNIX
+ 	regp = regex(sp, name);
+ 	free(sp);
+ 	if (regp == NULL) {
+ # else
+ 	if ((regex(sp, name)) == NULL) {
+ # endif
+ #else
+ 	if ((re_exec(name)) != 1) {
+ #endif
+ 		return(0);
+ 	}
+ 	return(1);
+ }

---

From: Mark Galbraith <[email-masked]>
Date: Tue, 22 Apr 1997 11:13:39 -0700 (PDT)

>>>>> "William" == William L Sebok <[email-masked]> writes:

William> We have been bothered by software pirates lately who use our anonymous ftp
William> site to distribute pirated software.  We have had two publicly writable
William> directories in the anonymous ftp area /pub and /incoming, traditionally used
William> for downloading and uploading respectively.  To eject the software pirates I
William> would like to enforce that tradition and deny uploading into /pub and uploading
William> into /incoming.  The first is easy with the context of the ftp daemon.  However
William> there is no explicit command in wu-ftpd to deny downloading from a directory.
William> There is the noretrieve command but that only denied downloading of individual
William> files -- as "man ftpaccess" says "No globbing is done."  What I have now done
William> is to patch wu-ftpd-2.4.2-beta-13 to allow the use of globbing in the noretrieve
William> command.

I do this using the following line in my ftpaccess file:

    upload /export/ftp /pub/incoming yes webmaster webmstrs 0660 nodirs

This sets all files loaded into the incoming directory to be owned by
'webmaster' and placed in the 'webmstrs' group.  The permissions on the
files are set to 660, which means that the webmasters can read the
files, but no one else can.  This prevents FTP from passing the file
back to anyone requesting it, even if they do know the name.

No hack was required.

-- 
Mark Galbraith                   Member of The HTML Writers Guild
Engineer, Internet Services	              http://www.hwg.org/
Triad Systems Corporation
(PGP Fingerprint=1CB9 7481 AD5C 5709  690B AC09 7F65 D6F6)

---

From: [email-masked] (Oskar Pearson)
Date: Wed, 23 Apr 1997 10:19:35 +0200

> there is no explicit command in wu-ftpd to deny downloading from a directory.
I did a similar patch a while ago when we split our ftp site into to parts.
(we found that our games section was being completely overloaded by people
downloading from overseas. We split the site into 2 sections, and although
they were mounted on one disk, people connecting to ftp.is.co.za couldn't
download from the directory and were sent a message to connect to
gamesdomain.is.co.za)

I also set so that you can't do transfers of files in /lib, /etc, /bin and
the rest. This could be useful, I spose.

Oskar

---

From: [email-masked] (Jay Schuster)
Date: Wed, 23 Apr 1997 08:39:37 -0400 (EDT)

William L. Sebok writes:
> On Unix is it easy to make file readable by only a person or a group
> but hard to arrange permissions make it readable by everyone except by
> the ftp daemon.

I would think you could use something like:

    upload  /ftp    /incoming    yes   ftp    ftp  0004    nodirs

Unreadable by user ftp or group ftp, readable by everyone else.

-- 
Jay Schuster <[email-masked]>
The People's Computer Company	`Revolutionary Programming'