Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ftpd dual-stack ftpd. run this from inetd, like:



details:   https://anonhg.NetBSD.org/src/rev/0c15e2577c0a
branches:  trunk
changeset: 474240:0c15e2577c0a
user:      itojun <itojun%NetBSD.org@localhost>
date:      Fri Jul 02 05:52:14 1999 +0000

description:
dual-stack ftpd.  run this from inetd, like:
>>ftp  stream tcp6 nowait root /usr/libexec/ftpd ftpd -ll

diffstat:

 libexec/ftpd/Makefile |    3 +-
 libexec/ftpd/extern.h |   51 ++++++-
 libexec/ftpd/ftpcmd.y |  235 ++++++++++++++++++++++++++++-
 libexec/ftpd/ftpd.8   |   18 ++-
 libexec/ftpd/ftpd.c   |  392 +++++++++++++++++++++++++++++++++++++++++--------
 5 files changed, 617 insertions(+), 82 deletions(-)

diffs (truncated from 1075 to 300 lines):

diff -r b83bbc0e1cba -r 0c15e2577c0a libexec/ftpd/Makefile
--- a/libexec/ftpd/Makefile     Fri Jul 02 05:41:45 1999 +0000
+++ b/libexec/ftpd/Makefile     Fri Jul 02 05:52:14 1999 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.32 1999/06/26 20:01:55 danw Exp $
+#      $NetBSD: Makefile,v 1.33 1999/07/02 05:52:14 itojun Exp $
 #      @(#)Makefile    8.2 (Berkeley) 4/4/94
 
 PROG=  ftpd
@@ -13,6 +13,7 @@
 SRCS+= ls.c cmp.c print.c stat_flags.c util.c
 .PATH: ${.CURDIR}/../../bin/ls
 
+CPPFLAGS+=-DINET6
 .include <bsd.own.mk>
 
 .ifdef SKEY
diff -r b83bbc0e1cba -r 0c15e2577c0a libexec/ftpd/extern.h
--- a/libexec/ftpd/extern.h     Fri Jul 02 05:41:45 1999 +0000
+++ b/libexec/ftpd/extern.h     Fri Jul 02 05:52:14 1999 +0000
@@ -1,4 +1,33 @@
-/*     $NetBSD: extern.h,v 1.18 1999/05/24 21:54:42 ross Exp $ */
+/*     $NetBSD: extern.h,v 1.19 1999/07/02 05:52:14 itojun Exp $       */
+
+/*
+ * Copyright (C) 1997 and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -54,6 +83,7 @@
 void   parse_conf __P((char *));
 void   pass __P((const char *));
 void   passive __P((void));
+void   long_passive __P((char *, int));
 void   perror_reply __P((int, const char *));
 void   pwd __P((void));
 void   removedir __P((const char *));
@@ -98,16 +128,31 @@
        mode_t           umask;         /* Umask to use */
 };
 
+#include <netinet/in.h>
+
+union sockunion {
+       struct sockinet {
+               u_char si_len;
+               u_char si_family;
+               u_short si_port;
+       } su_si;
+       struct sockaddr_in  su_sin;
+       struct sockaddr_in6 su_sin6;
+};
+#define su_len         su_si.si_len
+#define su_family      su_si.si_family
+#define su_port                su_si.si_port
+
 extern  int yyparse __P((void));
 
 extern char            cbuf[];
 extern struct ftpclass curclass;
-extern struct sockaddr_in data_dest;
+extern union sockunion data_dest;
 extern int             debug;
 extern int             form;
 extern int             guest;
 extern int             hasyyerrored;
-extern struct sockaddr_in his_addr;
+extern union sockunion his_addr;
 extern char            hostname[];
 #ifdef KERBEROS5
 extern krb5_context    kcontext;
diff -r b83bbc0e1cba -r 0c15e2577c0a libexec/ftpd/ftpcmd.y
--- a/libexec/ftpd/ftpcmd.y     Fri Jul 02 05:41:45 1999 +0000
+++ b/libexec/ftpd/ftpcmd.y     Fri Jul 02 05:52:14 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ftpcmd.y,v 1.31 1999/05/26 13:30:10 lukem Exp $        */
+/*     $NetBSD: ftpcmd.y,v 1.32 1999/07/02 05:52:14 itojun Exp $       */
 
 /*
  * Copyright (c) 1985, 1988, 1993, 1994
@@ -47,7 +47,7 @@
 #if 0
 static char sccsid[] = "@(#)ftpcmd.y   8.3 (Berkeley) 4/6/94";
 #else
-__RCSID("$NetBSD: ftpcmd.y,v 1.31 1999/05/26 13:30:10 lukem Exp $");
+__RCSID("$NetBSD: ftpcmd.y,v 1.32 1999/07/02 05:52:14 itojun Exp $");
 #endif
 #endif /* not lint */
 
@@ -72,6 +72,7 @@
 #include <time.h>
 #include <tzfile.h>
 #include <unistd.h>
+#include <netdb.h>
 
 #ifdef KERBEROS5
 #include <krb5.h>
@@ -100,6 +101,7 @@
 %token
        A       B       C       E       F       I
        L       N       P       R       S       T
+       ALL
 
        SP      CRLF    COMMA
 
@@ -117,6 +119,8 @@
 
        SIZE    MDTM
 
+       LPRT    LPSV    EPRT    EPSV
+
        MAIL    MLFL    MRCP    MRSQ    MSAM    MSND
        MSOM
 
@@ -125,6 +129,7 @@
        LEXERR
 
 %token <s> STRING
+%token <s> ALL
 %token <i> NUMBER
 
 %type  <i> check_login check_modify octal_number byte_size
@@ -218,11 +223,14 @@
                        if ($2) {
                                        /* be paranoid, if told so */
                        if (curclass.checkportcmd &&
-                           ((ntohs(data_dest.sin_port) < IPPORT_RESERVED) ||
-                           memcmp(&data_dest.sin_addr, &his_addr.sin_addr,
-                           sizeof(data_dest.sin_addr)) != 0)) {
+                           ((ntohs(data_dest.su_port) < IPPORT_RESERVED) ||
+                           memcmp(&data_dest.su_sin.sin_addr,
+                           &his_addr.su_sin.sin_addr,
+                           sizeof(data_dest.su_sin.sin_addr)) != 0)) {
                                reply(500,
                                    "Illegal PORT command rejected");
+                       } else if (epsvall) {
+                               reply(501, "PORT disallowed after EPSV ALL");
                        } else {
                                usedefault = 0;
                                if (pdata >= 0) {
@@ -231,9 +239,142 @@
                                }
                                reply(200, "PORT command successful.");
                        }
+
                        }
                }
 
+       | LPRT check_login SP host_long_port CRLF
+               {
+                       /* be paranoid, if told so */
+                       if (curclass.checkportcmd &&
+                           ((ntohs(data_dest.su_port) <
+                             IPPORT_RESERVED) ||
+                           memcmp(&data_dest.su_sin6.sin6_addr,
+                                  &his_addr.su_sin6.sin6_addr,
+                           sizeof(data_dest.su_sin6.sin6_addr)) != 0)) {
+                               reply(500, "Illegal LPRT command rejected");
+                               return (NULL);
+                       }
+                       if (epsvall)
+                               reply(501, "LPRT disallowed after EPSV ALL");
+                       else {
+                               usedefault = 0;
+                               if (pdata >= 0) {
+                                       (void) close(pdata);
+                                       pdata = -1;
+                               }
+                               reply(200, "LPRT command successful.");
+                       }
+               }
+
+       | EPRT check_login SP STRING CRLF
+               {
+                       char *tmp = NULL;
+                       char *result[3];
+                       char *p, *q;
+                       char delim;
+                       struct addrinfo hints;
+                       struct addrinfo *res;
+                       int i;
+
+                       if (epsvall) {
+                               reply(501, "EPRT disallowed after EPSV ALL");
+                               goto eprt_done;
+                       }
+                       usedefault = 0;
+                       if (pdata >= 0) {
+                               (void) close(pdata);
+                               pdata = -1;
+                       }
+
+                       /*XXX checks for login */
+
+                       tmp = strdup($4);
+                       if (!tmp) {
+                               fatal("not enough core.");
+                               /*NOTREACHED*/
+                       }
+                       p = tmp;
+                       delim = p[0];
+                       p++;
+                       memset(result, 0, sizeof(result));
+                       for (i = 0; i < 3; i++) {
+                               q = strchr(p, delim);
+                               if (!q || *q != delim) {
+               parsefail:
+                                       reply(500, "Invalid argument, rejected.");
+                                       if (tmp)
+                                               free(tmp);
+                                       usedefault = 1;
+                                       goto eprt_done;
+                               }
+                               *q++ = '\0';
+                               result[i] = p;
+                               p = q;
+                       }
+
+                       /* some more sanity check */
+                       p = result[0];
+                       while (*p) {
+                               if (!isdigit(*p))
+                                       goto parsefail;
+                               p++;
+                       }
+                       p = result[2];
+                       while (*p) {
+                               if (!isdigit(*p))
+                                       goto parsefail;
+                               p++;
+                       }
+
+                       memset(&hints, 0, sizeof(hints));
+                       if (atoi(result[0]) == 1)
+                               hints.ai_family = PF_INET;
+                       if (atoi(result[0]) == 2)
+                               hints.ai_family = PF_INET6;
+                       else
+                               hints.ai_family = PF_UNSPEC;    /*XXX*/
+                       hints.ai_socktype = SOCK_STREAM;
+                       if (getaddrinfo(result[1], result[2], &hints, &res))
+                               goto parsefail;
+                       memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
+                       /* be paranoid, if told so */
+                       if (curclass.checkportcmd) {
+                               int fail;
+                               fail = 0;
+                               if (ntohs(data_dest.su_port) < IPPORT_RESERVED)
+                                       fail++;
+                               if (data_dest.su_family != his_addr.su_family)
+                                       fail++;
+                               if (data_dest.su_len != his_addr.su_len)
+                                       fail++;
+                               switch (data_dest.su_family) {
+                               case AF_INET:
+                                       fail += memcmp(&data_dest.su_sin.sin_addr,
+                                           &his_addr.su_sin.sin_addr,
+                                           sizeof(data_dest.su_sin.sin_addr));
+                                       break;
+                               case AF_INET6:
+                                       fail += memcmp(&data_dest.su_sin6.sin6_addr,
+                                           &his_addr.su_sin6.sin6_addr,
+                                           sizeof(data_dest.su_sin6.sin6_addr));
+                                       break;
+                               default:
+                                       fail++;
+                               }
+                               if (fail) {
+                                       reply(500,
+                                           "Illegal EPRT command rejected");
+                                       return (NULL);
+                               }
+                       }
+                       free(tmp);



Home | Main Index | Thread Index | Old Index