(file_nlst, file_list): Fixed the paranoia test for
authorWerner Koch <wk@gnupg.org>
Sat, 30 Apr 2005 14:28:26 +0000 (14:28 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 30 Apr 2005 14:28:26 +0000 (14:28 +0000)
overlong directories.

Ported patches from Shane Kerr's 0.3.7 release:

* configure.in: Disabled support for sendfile() on FreeBSD.  It
appears to me that there's a bug in the sendfile() user-level
library.  I would welcome advice from any FreeBSD developer
wishing to set me straight.

* src/ftp_session.c (do_size): Changed SIZE command to return
error for directories.
* src/file_list.c: #ifdef wrap GLOB_ABORTED for really old gcc
compilers (Slackware or older installations).
(skip_ls_options): Add code to skip command line options that are
intended for "ls".

AUTHORS
BUGS
ChangeLog
README
configure.in
src/config.h.in
src/file_list.c
src/ftp_session.c

diff --git a/AUTHORS b/AUTHORS
index 124a3c3..a7d3cc9 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -13,3 +13,6 @@ Matthew Danish <mdanish@andrew.cmu.edu> (Debian compile help,
 Eric Jensen (Red Hat 7.0 init script)
 Anders Nordby <anders@fix.no> (FreeBSD port)
 
+For this this version:
+
+Werner Koch <wk@g10code.com> (new options, minor fixes)
diff --git a/BUGS b/BUGS
index 6daec23..64b69d6 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -15,3 +15,14 @@ $Id$
   bizarre thread model.  This will also be fixed on 0.3.x, as I'll pay
   careful attention to cancel points.
 
+- Probable memory leak when pthread_cancel() operates on a thread that
+  has allocated memory (in glob() for instance).  Need to disable cancel 
+  for appropriate regions of code.
+
+- Doesn't handle permissions properly.  If a file is world-readable but 
+  not group-readable and someone in the group tries to read it they
+  should not be allowed, apparently.  :(
+
+- strerror() may not be thread safe (depends on implementation).  Write
+  a thread safe version.
+
index e65ab63..0296e0b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,33 @@
+2005-04-30  Werner Koch  <wk@g10code.de>
+
+       Bumped version to 0.3.7-wk1.
+
+       * src/file_list.c (file_nlst, file_list): Fixed the paranoia test for
+       overlong directories.
+
+2005-04-30  Werner Koch  <wk@g10code.de>
+
+       Ported patches from Shane Kerr's 0.3.7 release:
+       
+       * configure.in: Disabled support for sendfile() on FreeBSD.  It
+       appears to me that there's a bug in the sendfile() user-level
+       library.  I would welcome advice from any FreeBSD developer
+       wishing to set me straight.  
+
+       * src/ftp_session.c (do_size): Changed SIZE command to return
+       error for directories.
+       * src/file_list.c: #ifdef wrap GLOB_ABORTED for really old gcc
+       compilers (Slackware or older installations).
+       (skip_ls_options): Add code to skip command line options that are
+       intended for "ls".
+
 2004-01-12  Werner Koch  <wk@gnupg.org>
 
        * src/ftp_listener.c (connection_acceptor): Don't increase the
-       error counter for EMFILE conditions but a few seconds.
+       error counter for EMFILE conditions but sleep a few seconds.
 
 2003-08-13  Werner Koch  <wk@gnupg.org>
 
-       
        * src/oftpd.c (reopen_syslog_hack): Removed.
        (init_syslog_hack): Removed.  That was a whole stupid thing by me
        as I didn'd realized that we are running chroot and so the
diff --git a/README b/README
index e202f54..1e4d808 100644 (file)
--- a/README
+++ b/README
@@ -51,14 +51,28 @@ Portability
 
 oftpd currently runs on modern Linux systems, including Red Hat-derived
 (Mandrake, Trustix, etc.) and Debian systems.  oftpd has been ported to
-FreeBSD and is in the FreeBSD ports collection.  I expect to install
-FreeBSD and Solaris sometime in 2001 to properly support those
-environments.
+FreeBSD and is in the FreeBSD ports collection.
 
 
-Don't hesitate to e-mail if you have questions or suggestions.  
+While I have given up development of oftpd, it's small and reliable.  Don't
+hesitate to e-mail if you have questions or suggestions.  
 Good luck!
 
 
 Shane Kerr
 shane@time-travellers.org
+
+====== 
+
+Note: For my own purposes I maintain a separate CVS with a slightly
+changed version (well, the one you are currently reading).  As of
+today the Debian version is based upon this one.
+
+Werner Koch
+<wk@gnupg.org>
+
+
+
+
+
+
index 389f602..5eaca5d 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/file_list.c)
-AM_INIT_AUTOMAKE(oftpd, 0.3.6-wk1)
+AM_INIT_AUTOMAKE(oftpd, 0.3.7-wk1)
 AM_CONFIG_HEADER(src/config.h)
 
 dnl Checks for programs.
@@ -72,7 +72,8 @@ off_t offset;
 off_t sbytes;
 sendfile(0, 1, &offset, 0, NULL, &sbytes, 0);
 ],
-AC_DEFINE(HAVE_FREEBSD_SENDFILE) AC_DEFINE(HAVE_SENDFILE) have_sendfile=yes
+dnl sendfile() seems broken on FreeBSD, so for now we'll just omit it
+dnl AC_DEFINE(HAVE_FREEBSD_SENDFILE) AC_DEFINE(HAVE_SENDFILE) have_sendfile=yes
 )
 fi
 
@@ -87,14 +88,14 @@ LDFLAGS="-pthread $LDFLAGS"
 AC_TRY_LINK([ 
 #include <pthread.h>
 ], [
-pthread_create();
+pthread_self();
 ],
 ,
-LIBS="$save_LDFLAGS"
+LDFLAGS="$save_LDFLAGS"
 )
 
 dnl then, try looking in various libraries, which will work on other systems
-AC_SEARCH_LIBS(pthread_create, [ pthread pthreads thread threads ])
+AC_SEARCH_LIBS(pthread_self, [ pthread pthreads thread threads ])
 
 dnl add reentrant flags
 CFLAGS="$CFLAGS -D_REENTRANT -D_THREAD_SAFE"
index 6f5daae..cc00db2 100644 (file)
 /* If using the C implementation of alloca, define if you know the
    direction of stack growth for your system; otherwise it will be
    automatically deduced at run-time.
-        STACK_DIRECTION > 0 => grows toward higher addresses
-        STACK_DIRECTION < 0 => grows toward lower addresses
-        STACK_DIRECTION = 0 => direction of growth unknown */
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
 #undef STACK_DIRECTION
 
 /* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
index 01bcc2e..54e8dfb 100644 (file)
@@ -13,6 +13,7 @@
 #include <glob.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
@@ -50,11 +51,14 @@ char *alloca ();
 
 /* GLOB_ABORTED is defined in Linux but not on FreeBSD */
 #ifndef GLOB_ABORTED
+#ifdef GLOB_ABEND
 #define GLOB_ABORTED GLOB_ABEND
 #endif
+#endif
 
 static int is_valid_dir(const char *dir);
 static void fdprintf(int fd, const char *fmt, ...);
+static const char *skip_ls_options(const char *filespec);
 
 /* if no localtime_r() is available, provide one */
 #ifndef HAVE_LOCALTIME_R
@@ -79,6 +83,7 @@ int file_nlst(int out, const char *cur_dir, const char *filespec)
     glob_t glob_buf;
     int i;
     char *file_name;
+    int hidden;
 
     daemon_assert(out >= 0);
     daemon_assert(is_valid_dir(cur_dir));
@@ -88,18 +93,20 @@ int file_nlst(int out, const char *cur_dir, const char *filespec)
         cur_dir = "";
         dir_len = 0;
     } else {
-        strcpy(pattern, cur_dir);
-        dir_len = strlen(pattern);
+        dir_len = strlen(cur_dir);
         if ((dir_len + 1) > PATH_MAX) {
             fdprintf(out, "Error; Directory name too long\r\n");
             return 0;
         }
+        strcpy(pattern, cur_dir);
        if ((cur_dir[0] != '/') || (cur_dir[1] != '\0')) {
             strcat(pattern, "/");
             dir_len++;
        }
     }
 
+    /* FIXME: Stat the directory to see whether something is hidden.  */
+
     /* make sure we have enough space */
     if ((dir_len + 1 + strlen(filespec)) > PATH_MAX) {
         fdprintf(out, "Error; Path name too long\r\n");
@@ -123,9 +130,11 @@ int file_nlst(int out, const char *cur_dir, const char *filespec)
     } else if (glob_ret == GLOB_NOMATCH) {
         return 1;
 #endif /* GLOB_NOMATCH */
+#ifdef GLOB_ABORTED  /* not present in older gcc */
     } else if (glob_ret == GLOB_ABORTED) {
         fdprintf(out, "Error; Read error\r\n");
        return 0;
+#endif /*GLOB_ABORTED*/
     } else if (glob_ret != 0) {
         fdprintf(out, "Error; Unknown glob() error %d\r\n", glob_ret);
        return 0;
@@ -178,11 +187,13 @@ int file_list(int out, const char *cur_dir, const char *filespec)
     daemon_assert(is_valid_dir(cur_dir));
     daemon_assert(filespec != NULL);
 
+    filespec = skip_ls_options(filespec);
+
     if (filespec[0] == '/') {
         cur_dir = "";
         dir_len = 0;
     } else {
-        dir_len = strlen(pattern);
+        dir_len = strlen(cur_dir);
         if ((dir_len + 1) > PATH_MAX) {
             fdprintf(out, "Error; Directory name too long\r\n");
             return 0;
@@ -194,6 +205,8 @@ int file_list(int out, const char *cur_dir, const char *filespec)
        }
     }
 
+    /* FIXME: Stat the directory to see whether something is hidden.  */
+
     /* make sure we have enough space */
     if ((dir_len + 1 + strlen(filespec)) > PATH_MAX) {
         fdprintf(out, "Error; Path name too long\r\n");
@@ -218,9 +231,11 @@ int file_list(int out, const char *cur_dir, const char *filespec)
     } else if (glob_ret == GLOB_NOSPACE) {
         fdprintf(out, "Error; Out of memory\r\n");
        return 0;
+#ifdef GLOB_ABORTED  /* Not present in older gcc. */
     } else if (glob_ret == GLOB_ABORTED) {
         fdprintf(out, "Error; Read error\r\n");
        return 0;
+#endif /*GLOB_ABORTED*/
     } else if (glob_ret != 0) {
         fdprintf(out, "Error; Unknown glob() error %d\r\n", glob_ret);
        return 0;
@@ -242,7 +257,15 @@ int file_list(int out, const char *cur_dir, const char *filespec)
     num_files = 0;
     total_blocks = 0;
     for (i=0; i<glob_buf.gl_pathc; i++) {
+        size_t n;
+
         file_name = glob_buf.gl_pathv[i];
+        n = strlen (file_name);
+        if (n >= 7 && !strcmp (file_name+n-7, ".hidden")) {
+            num_files = 0;
+            total_blocks = 0;
+            break;
+        }
         if ( !strncmp (file_name, "/dev", 4)
              && (!file_name[4] || file_name[4] == '/'))
           continue;
@@ -407,3 +430,46 @@ static void fdprintf(int fd, const char *fmt, ...)
        amt_written += write_ret;
     }
 }
+
+
+/* 
+  hack workaround clients like Midnight Commander that send:
+      LIST -al /dirname 
+*/
+static const char *
+skip_ls_options(const char *filespec)
+{
+    daemon_assert(filespec != NULL);
+
+    for (;;) {
+        /* end when we've passed all options */
+        if (*filespec != '-') {
+            break;
+        }
+        filespec++;
+
+        /* if we find "--", eat it and any following whitespace then return */
+        if ((filespec[0] == '-') && (filespec[1] == ' ')) {
+            filespec += 2;
+            while (isspace(*filespec)) {
+                filespec++;
+            }
+            break;
+        }
+
+        /* otherwise, skip this option */
+        while ((*filespec != '\0') && !isspace(*filespec)) {
+            filespec++;
+        }
+
+        /* and skip any whitespace */
+        while (isspace(*filespec)) {
+            filespec++;
+        }
+    }
+
+    daemon_assert(filespec != NULL);
+
+    return filespec;
+}
+
index e54a7b3..1bf780a 100644 (file)
@@ -1650,6 +1650,9 @@ static void do_size(ftp_session_t *f, const ftp_command_t *cmd)
         }
         else if (stat(full_path, &stat_buf) != 0) {
             reply(f, 550, "Error getting file status; %s.", strerror(errno));
+        }
+        else if (S_ISDIR(stat_buf.st_mode)) {
+            reply(f, 550, "File is a directory, SIZE command not valid.");
         } else {
             /* output the size */
             if (sizeof(off_t) == 8) {