/*
* Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*/
/*
* From: @(#)ftpd.c 8.4 (Berkeley) 4/16/94
* From: NetBSD: ftpd.c,v 1.15 1995/06/03 22:46:47 mycroft Exp
* From: OpenBSD: ftpd.c,v 1.26 1996/12/07 09:00:22 bitblt Exp
* From: OpenBSD: ftpd.c,v 1.35 1997/05/01 14:45:37 deraadt Exp
* From: OpenBSD: ftpd.c,v 1.54 1999/04/29 21:38:43 downsj Exp
*/
char ftpd_rcsid[] =
"$Id: ftpd.c,v 1.20 2000/07/23 03:34:56 dholland Exp $";
char copyright[] =
"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n"
" The Regents of the University of California. All rights reserved.\n";
/*
* FTP server.
*/
#ifdef __linux__
#define _GNU_SOURCE
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define FTP_NAMES
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <limits.h> /* for CHAR_BIT */
#include <netdb.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <vis.h>
#include <unistd.h>
#include <utmp.h>
#ifndef __linux__
#include <util.h>
#include <err.h>
#else
#include <grp.h> /* for initgroups() */
/* #include <sys/file.h> * for L_SET et al. * <--- not used? */
/*typedef int64_t quad_t;*/
typedef unsigned int useconds_t;
#endif
#include "../version.h"
/* glibc 2.[01] does not have TCP_CORK, so define it here */
#if __GLIBC__ >= 2 && defined(__linux__) && !defined(TCP_CORK)
#define TCP_CORK 3
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
#endif
#ifdef USE_SHADOW
#include <shadow.h>
#include "isexpired.h"
#endif
#if defined(TCPWRAPPERS)
#include <tcpd.h>
#endif /* TCPWRAPPERS */
#if defined(SKEY)
#include <skey.h>
#endif
#include "pathnames.h"
#include "extern.h"
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
static char versionpre[] = "Version 6.4/OpenBSD/Linux";
static char version[sizeof(versionpre)+sizeof(pkg)];
extern off_t restart_point;
extern char cbuf[];
struct sockaddr_in server_addr;
struct sockaddr_in ctrl_addr;
struct sockaddr_in data_source;
struct sockaddr_in data_dest;
struct sockaddr_in his_addr;
struct sockaddr_in pasv_addr;
int daemon_mode = 0;
int data;
jmp_buf errcatch, urgcatch;
int logged_in;
struct passwd *pw;
#ifdef USE_SHADOW
struct spwd *spw = NULL;
#endif
int debug = 0;
int timeout = 900; /* timeout after 15 minutes of inactivity */
int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
int logging;
int high_data_ports = 0;
int anon_only = 0;
int multihome = 0;
int guest;
int stats;
int statfd = -1;
int portcheck = 1;
int dochroot;
int type;
int form;
int stru; /* avoid C keyword */
int mode;
int doutmp = 0; /* update utmp file */
int usedefault = 1; /* for data transfers */
int pdata = -1; /* for passive mode */
sig_atomic_t transflag;
off_t file_size;
off_t byte_count;
#if !defined(CMASK) || CMASK == 0
#undef CMASK
#define CMASK 027
#endif
int defumask = CMASK; /* default umask value */
char tmpline[7];
char hostname[MAXHOSTNAMELEN];
char remotehost[MAXHOSTNAMELEN];
char dhostname[MAXHOSTNAMELEN];
char *guestpw;
static char ttyline[20];
char *tty = ttyline; /* for klogin */
static struct utmp utmp; /* for utmp */
#if defined(TCPWRAPPERS)
int allow_severity = LOG_INFO;
int deny_severity = LOG_NOTICE;
#endif /* TCPWRAPPERS */
#if defined(KERBEROS)
int notickets = 1;
char *krbtkfile_env = NULL;
#endif
char *ident = NULL;
/*
* Timeout intervals for retrying connections
* to hosts that don't accept PORT cmds. This
* is a kludge, but given the problems with TCP...
*/
#define SWAITMAX 90 /* wait at most 90 seconds */
#define SWAITINT 5 /* interval between retries */
int swaitmax = SWAITMAX;
int swaitint = SWAITINT;
#ifdef HASSETPROCTITLE
char proctitle[BUFSIZ]; /* initial part of title */
#endif /* HASSETPROCTITLE */
#define LOGCMD(cmd, file) \
if (logging > 1) \
syslog(LOG_INFO,"%s %s%s", cmd, \
*(file) == '/' ? "" : curdir(), file);
#define LOGCMD2(cmd, file1, file2) \
if (logging > 1) \
syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
*(file1) == '/' ? "" : curdir(), file1, \
*(file2) == '/' ? "" : curdir(), file2);
#define LOGBYTES(cmd, file, cnt) \
if (logging > 1) { \
if (cnt == (off_t)-1) \
syslog(LOG_INFO,"%s %s%s", cmd, \
*(file) == '/' ? "" : curdir(), file); \
else \
syslog(LOG_INFO, "%s %s%s = %qd bytes", cmd, \
*(file) == '/' ? "" : curdir(), file, (quad_t)(cnt)); \
}
static void ack __P((const char *));
static void myoob __P((int));
static int checkuser __P((const char *, const char *));
static FILE *dataconn __P((const char *, off_t, const char *));
static void dolog __P((struct sockaddr_in *));
static const char *curdir __P((void));
static void end_login __P((void));
static FILE *getdatasock __P((const char *));
static int guniquefd __P((const char *, char **));
static void lostconn __P((int));
static void sigquit __P((int));
static int receive_data __P((FILE *, FILE *));
static void replydirname __P((const char *, const char *));
static void send_data __P((FILE *, FILE *, off_t, off_t, int));
static struct passwd *
sgetpwnam __P((const char *));
static char *sgetsave __P((char *));
static void reapchild __P((int));
#if defined(TCPWRAPPERS)
static int check_host __P((struct sockaddr_in *));
#endif
void logxfer __P((const char *, off_t, time_t));
#ifdef __linux__
static void warnx(const char *format, ...)
{
va_list ap;
va_start(ap, format);
fprintf(stderr, "ftpd: ");
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
va_end(ap);
}
#endif /* __linux__ */
static const char *
curdir(void)
{
static char path[MAXPATHLEN+1]; /* path + '/' */
if (getcwd(path, sizeof(path)-1) == NULL)
return ("");
if (path[1] != '\0') /* special case for root dir. */
strcat(path, "/");
/* For guest account, skip / since it's chrooted */
return (guest ? path+1 : path);
}
int
- 1
- 2
前往页