aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGavin Atkinson <gavin@FreeBSD.org>2013-05-05 15:04:47 +0000
committerGavin Atkinson <gavin@FreeBSD.org>2013-05-05 15:04:47 +0000
commitf5acf0e0ffbf00e44c2e9848a62e0b6d402b31fa (patch)
tree53870232aa9935fe0a8870c674dcd78289ab1e2e /src
parent1d78dcfdf287769fef244c1c78eba60eade69bbb (diff)
downloadsrc-f5acf0e0ffbf00e44c2e9848a62e0b6d402b31fa.tar.gz
src-f5acf0e0ffbf00e44c2e9848a62e0b6d402b31fa.zip
Vendor import of tnftp-20130505.vendor/tnftp/20130505
Notes
Notes: svn path=/vendor/tnftp/dist/; revision=250274 svn path=/vendor/tnftp/20130505/; revision=250275; tag=vendor/tnftp/20130505
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am16
-rw-r--r--src/Makefile.in95
-rw-r--r--src/cmds.c25
-rw-r--r--src/cmdtab.c7
-rw-r--r--src/extern.h15
-rw-r--r--src/fetch.c187
-rw-r--r--src/ftp.176
-rw-r--r--src/ftp.c48
-rw-r--r--src/ftp_var.h8
-rw-r--r--src/main.c54
-rw-r--r--src/progressbar.c9
-rw-r--r--src/ssl.c615
-rw-r--r--src/ssl.h63
-rw-r--r--src/util.c126
-rw-r--r--src/version.h6
15 files changed, 1107 insertions, 243 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8ac32f98fe24..ee4d5d03f9ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-## $NetBSD: Makefile.am,v 1.2 2010/01/04 06:24:20 lukem Exp $
+## $NetBSD: Makefile.am,v 1.4 2013/05/05 13:29:19 lukem Exp $
bin_PROGRAMS = tnftp
@@ -35,6 +35,19 @@ tnftp_LDADD += \
endif
+if WITH_SSL
+tnftp_SOURCES += \
+ ssl.c
+
+tnftp_CPPFLAGS += \
+ $(OPENSSL_INCLUDES)
+
+tnftp_LDADD += \
+ $(OPENSSL_LDFLAGS) \
+ $(OPENSSL_LIBS)
+endif
+
+
man1_MANS = \
tnftp.1
@@ -49,4 +62,5 @@ EXTRA_DIST = \
ftp.1 \
ftp_var.h \
progressbar.h \
+ ssl.h \
version.h
diff --git a/src/Makefile.in b/src/Makefile.in
index e11a81add7ef..0c530d42c55f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -41,10 +41,26 @@ bin_PROGRAMS = tnftp$(EXEEXT)
@USE_LIBEDIT_TRUE@am__append_2 = \
@USE_LIBEDIT_TRUE@ ../libedit/libedit.la
+@WITH_SSL_TRUE@am__append_3 = \
+@WITH_SSL_TRUE@ ssl.c
+
+@WITH_SSL_TRUE@am__append_4 = \
+@WITH_SSL_TRUE@ $(OPENSSL_INCLUDES)
+
+@WITH_SSL_TRUE@am__append_5 = \
+@WITH_SSL_TRUE@ $(OPENSSL_LDFLAGS) \
+@WITH_SSL_TRUE@ $(OPENSSL_LIBS)
+
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__aclocal_m4_deps = $(top_srcdir)/buildaux/ax_check_openssl.m4 \
+ $(top_srcdir)/buildaux/libtool.m4 \
+ $(top_srcdir)/buildaux/ltoptions.m4 \
+ $(top_srcdir)/buildaux/ltsugar.m4 \
+ $(top_srcdir)/buildaux/ltversion.m4 \
+ $(top_srcdir)/buildaux/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -53,13 +69,20 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
PROGRAMS = $(bin_PROGRAMS)
+am__tnftp_SOURCES_DIST = cmds.c cmdtab.c complete.c domacro.c fetch.c \
+ ftp.c main.c progressbar.c ruserpass.c util.c ssl.c
+@WITH_SSL_TRUE@am__objects_1 = tnftp-ssl.$(OBJEXT)
am_tnftp_OBJECTS = tnftp-cmds.$(OBJEXT) tnftp-cmdtab.$(OBJEXT) \
tnftp-complete.$(OBJEXT) tnftp-domacro.$(OBJEXT) \
tnftp-fetch.$(OBJEXT) tnftp-ftp.$(OBJEXT) tnftp-main.$(OBJEXT) \
tnftp-progressbar.$(OBJEXT) tnftp-ruserpass.$(OBJEXT) \
- tnftp-util.$(OBJEXT)
+ tnftp-util.$(OBJEXT) $(am__objects_1)
tnftp_OBJECTS = $(am_tnftp_OBJECTS)
-tnftp_DEPENDENCIES = ../libnetbsd/libnetbsd.la $(am__append_2)
+am__DEPENDENCIES_1 =
+@WITH_SSL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
+@WITH_SSL_TRUE@ $(am__DEPENDENCIES_1)
+tnftp_DEPENDENCIES = ../libnetbsd/libnetbsd.la $(am__append_2) \
+ $(am__DEPENDENCIES_2)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
@@ -90,7 +113,7 @@ AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(tnftp_SOURCES)
-DIST_SOURCES = $(tnftp_SOURCES)
+DIST_SOURCES = $(am__tnftp_SOURCES_DIST)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -132,39 +155,45 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+NM = @NM@
NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -173,6 +202,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -183,9 +213,9 @@ abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -231,23 +261,14 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-tnftp_SOURCES = \
- cmds.c \
- cmdtab.c \
- complete.c \
- domacro.c \
- fetch.c \
- ftp.c \
- main.c \
- progressbar.c \
- ruserpass.c \
- util.c
-
+tnftp_SOURCES = cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c \
+ main.c progressbar.c ruserpass.c util.c $(am__append_3)
tnftp_CPPFLAGS = -DHAVE_TNFTPD_H=1 \
-D_DEFAULT_CONFDIR=\"${sysconfdir}\" -I$(srcdir) \
-I$(top_srcdir)/libnetbsd -I$(top_srcdir) -I$(top_builddir) \
- $(am__append_1)
-tnftp_LDADD = ../libnetbsd/libnetbsd.la $(am__append_2)
+ $(am__append_1) $(am__append_4)
+tnftp_LDADD = ../libnetbsd/libnetbsd.la $(am__append_2) \
+ $(am__append_5)
man1_MANS = \
tnftp.1
@@ -259,6 +280,7 @@ EXTRA_DIST = \
ftp.1 \
ftp_var.h \
progressbar.h \
+ ssl.h \
version.h
all: all-am
@@ -357,6 +379,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnftp-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnftp-progressbar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnftp-ruserpass.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnftp-ssl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnftp-util.Po@am__quote@
.c.o:
@@ -543,6 +566,22 @@ tnftp-util.obj: util.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tnftp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnftp-util.obj `if test -f 'util.c'; then $(CYGPATH_W) 'util.c'; else $(CYGPATH_W) '$(srcdir)/util.c'; fi`
+tnftp-ssl.o: ssl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tnftp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnftp-ssl.o -MD -MP -MF $(DEPDIR)/tnftp-ssl.Tpo -c -o tnftp-ssl.o `test -f 'ssl.c' || echo '$(srcdir)/'`ssl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tnftp-ssl.Tpo $(DEPDIR)/tnftp-ssl.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ssl.c' object='tnftp-ssl.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tnftp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnftp-ssl.o `test -f 'ssl.c' || echo '$(srcdir)/'`ssl.c
+
+tnftp-ssl.obj: ssl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tnftp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnftp-ssl.obj -MD -MP -MF $(DEPDIR)/tnftp-ssl.Tpo -c -o tnftp-ssl.obj `if test -f 'ssl.c'; then $(CYGPATH_W) 'ssl.c'; else $(CYGPATH_W) '$(srcdir)/ssl.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tnftp-ssl.Tpo $(DEPDIR)/tnftp-ssl.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ssl.c' object='tnftp-ssl.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tnftp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnftp-ssl.obj `if test -f 'ssl.c'; then $(CYGPATH_W) 'ssl.c'; else $(CYGPATH_W) '$(srcdir)/ssl.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/cmds.c b/src/cmds.c
index 7be3a7782a17..a8e33bdbc3f6 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -1,5 +1,5 @@
-/* $NetBSD: cmds.c,v 1.17 2010/01/12 06:55:47 lukem Exp $ */
-/* from NetBSD: cmds.c,v 1.130 2009/07/13 19:05:41 roy Exp */
+/* $NetBSD: cmds.c,v 1.18 2013/05/05 11:17:30 lukem Exp $ */
+/* from NetBSD: cmds.c,v 1.135 2012/12/22 16:57:09 christos Exp */
/*-
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
#if 0
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
#else
-__RCSID(" NetBSD: cmds.c,v 1.130 2009/07/13 19:05:41 roy Exp ");
+__RCSID(" NetBSD: cmds.c,v 1.135 2012/12/22 16:57:09 christos Exp ");
#endif
#endif /* not lint */
@@ -116,6 +116,7 @@ __RCSID(" NetBSD: cmds.c,v 1.130 2009/07/13 19:05:41 roy Exp ");
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <glob.h>
#include <limits.h>
#include <netdb.h>
@@ -149,7 +150,7 @@ static struct types {
static sigjmp_buf jabort;
static int confirm(const char *, const char *);
-static void mintr(int);
+__dead static void mintr(int);
static void mabort(const char *);
static void set_type(const char *);
@@ -563,14 +564,14 @@ void
reget(int argc, char *argv[])
{
- (void)getit(argc, argv, 1, "r+");
+ (void)getit(argc, argv, 1, restart_point ? "r+" : "a");
}
void
get(int argc, char *argv[])
{
- (void)getit(argc, argv, 0, restart_point ? "r+" : "w" );
+ (void)getit(argc, argv, 0, restart_point ? "r+" : "w");
}
/*
@@ -619,10 +620,14 @@ getit(int argc, char *argv[], int restartit, const char *gmode)
ret = stat(locfile, &stbuf);
if (restartit == 1) {
if (ret < 0) {
- warn("Can't stat `%s'", locfile);
- goto freegetit;
+ if (errno != ENOENT) {
+ warn("Can't stat `%s'", locfile);
+ goto freegetit;
+ }
+ restart_point = 0;
}
- restart_point = stbuf.st_size;
+ else
+ restart_point = stbuf.st_size;
} else {
if (ret == 0) {
time_t mtime;
@@ -2677,7 +2682,7 @@ setoption(int argc, char *argv[])
return;
}
-#define OPTIONINDENT ((int) sizeof("http_proxy"))
+#define OPTIONINDENT ((int) sizeof("https_proxy"))
if (argc == 1) {
for (o = optiontab; o->name != NULL; o++) {
fprintf(ttyout, "%-*s\t%s\n", OPTIONINDENT,
diff --git a/src/cmdtab.c b/src/cmdtab.c
index dec48e817abb..5a51bd4cf357 100644
--- a/src/cmdtab.c
+++ b/src/cmdtab.c
@@ -1,5 +1,5 @@
-/* $NetBSD: cmdtab.c,v 1.11 2009/05/20 12:53:47 lukem Exp $ */
-/* from NetBSD: cmdtab.c,v 1.51 2009/04/12 10:18:52 lukem Exp */
+/* $NetBSD: cmdtab.c,v 1.12 2013/05/05 11:17:30 lukem Exp $ */
+/* from NetBSD: cmdtab.c,v 1.52 2012/12/22 16:57:09 christos Exp */
/*-
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94";
#else
-__RCSID(" NetBSD: cmdtab.c,v 1.51 2009/04/12 10:18:52 lukem Exp ");
+__RCSID(" NetBSD: cmdtab.c,v 1.52 2012/12/22 16:57:09 christos Exp ");
#endif
#endif /* not lint */
@@ -306,6 +306,7 @@ struct option optiontab[] = {
{ "anonpass", NULL },
{ "ftp_proxy", NULL },
{ "http_proxy", NULL },
+ { "https_proxy",NULL },
{ "no_proxy", NULL },
{ "pager", NULL },
{ "prompt", NULL },
diff --git a/src/extern.h b/src/extern.h
index 9b6c6458c2ec..d9b7a50df13e 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -1,5 +1,5 @@
-/* $NetBSD: extern.h,v 1.12 2009/11/15 10:12:37 lukem Exp $ */
-/* from NetBSD: extern.h,v 1.77 2009/07/13 19:05:41 roy Exp */
+/* $NetBSD: extern.h,v 1.13 2013/05/05 11:17:30 lukem Exp $ */
+/* from NetBSD: extern.h,v 1.80 2012/07/04 06:09:37 is Exp */
/*-
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -95,9 +95,6 @@ struct tm;
struct addrinfo;
void abort_remote(FILE *);
-void abort_squared(int);
-void abortpt(int);
-void abortxfer(int);
void account(int, char **);
void ai_unmapped(struct addrinfo *);
int another(int *, char ***, const char *);
@@ -146,7 +143,7 @@ void help(int, char **);
char *hookup(const char *, const char *);
void idlecmd(int, char **);
int initconn(void);
-void intr(int);
+__dead void intr(int);
int isipv6addr(const char *);
void list_vertical(StringList *);
void lcd(int, char **);
@@ -167,9 +164,10 @@ const char *onoff(int);
void opts(int, char **);
void newer(int, char **);
void page(int, char **);
+const char *parse_rfc2616time(struct tm *, const char *);
int parserate(int, char **, int);
char *prompt(void);
-void proxabort(int);
+__dead void proxabort(int);
void proxtrans(const char *, const char *, const char *);
void psabort(int);
void pswitch(int);
@@ -241,9 +239,8 @@ int togglevar(int, char **, int *, const char *);
void unsetoption(int, char **);
void updatelocalcwd(void);
void updateremotecwd(void);
-void usage(void);
void user(int, char **);
-int ftp_connect(int, const struct sockaddr *, socklen_t);
+int ftp_connect(int, const struct sockaddr *, socklen_t, int);
int ftp_listen(int, int);
int ftp_poll(struct pollfd *, int, int);
void *ftp_malloc(size_t);
diff --git a/src/fetch.c b/src/fetch.c
index 91b49fd2435a..e9589e044ed1 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -1,5 +1,5 @@
-/* $NetBSD: fetch.c,v 1.18 2009/11/15 10:12:37 lukem Exp $ */
-/* from NetBSD: fetch.c,v 1.191 2009/08/17 09:08:16 christos Exp */
+/* $NetBSD: fetch.c,v 1.19 2013/05/05 11:17:30 lukem Exp $ */
+/* from NetBSD: fetch.c,v 1.202 2013/02/23 13:47:36 christos Exp */
/*-
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID(" NetBSD: fetch.c,v 1.191 2009/08/17 09:08:16 christos Exp ");
+__RCSID(" NetBSD: fetch.c,v 1.202 2013/02/23 13:47:36 christos Exp ");
#endif /* not lint */
/*
@@ -57,6 +57,7 @@ __RCSID(" NetBSD: fetch.c,v 1.191 2009/08/17 09:08:16 christos Exp ");
#include <arpa/ftp.h>
#include <arpa/inet.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -70,18 +71,22 @@ __RCSID(" NetBSD: fetch.c,v 1.191 2009/08/17 09:08:16 christos Exp ");
#endif /* tnftp */
+#include "ssl.h"
#include "ftp_var.h"
#include "version.h"
typedef enum {
UNKNOWN_URL_T=-1,
HTTP_URL_T,
+#ifdef WITH_SSL
+ HTTPS_URL_T,
+#endif
FTP_URL_T,
FILE_URL_T,
CLASSIC_URL_T
} url_t;
-void aborthttp(int);
+__dead static void aborthttp(int);
#ifndef NO_AUTH
static int auth_url(const char *, char **, const char *, const char *);
static void base64_encode(const unsigned char *, size_t, unsigned char *);
@@ -106,7 +111,15 @@ static int redirect_loop;
#define FILE_URL "file://" /* file URL prefix */
#define FTP_URL "ftp://" /* ftp URL prefix */
#define HTTP_URL "http://" /* http URL prefix */
+#ifdef WITH_SSL
+#define HTTPS_URL "https://" /* https URL prefix */
+#define IS_HTTP_TYPE(urltype) \
+ (((urltype) == HTTP_URL_T) || ((urltype) == HTTPS_URL_T))
+#else
+#define IS_HTTP_TYPE(urltype) \
+ ((urltype) == HTTP_URL_T)
+#endif
/*
* Determine if token is the next word in buf (case insensitive).
@@ -288,7 +301,7 @@ url_decode(char *url)
/*
- * Parse URL of form (per RFC3986):
+ * Parse URL of form (per RFC 3986):
* <type>://[<user>[:<password>]@]<host>[:<port>][/<path>]
* Returns -1 if a parse error occurred, otherwise 0.
* It's the caller's responsibility to url_decode() the returned
@@ -298,7 +311,7 @@ url_decode(char *url)
* malloc(3)ed strings of the relevant section, and port to
* the number given, or ftpport if ftp://, or httpport if http://.
*
- * XXX: this is not totally RFC3986 compliant; <path> will have the
+ * XXX: this is not totally RFC 3986 compliant; <path> will have the
* leading `/' unless it's an ftp:// URL, as this makes things easier
* for file:// and http:// URLs. ftp:// URLs have the `/' between the
* host and the URL-path removed, but any additional leading slashes
@@ -352,6 +365,13 @@ parse_url(const char *url, const char *desc, url_t *utype,
} else if (STRNEQUAL(url, FILE_URL)) {
url += sizeof(FILE_URL) - 1;
*utype = FILE_URL_T;
+#ifdef WITH_SSL
+ } else if (STRNEQUAL(url, HTTPS_URL)) {
+ url += sizeof(HTTPS_URL) - 1;
+ *utype = HTTPS_URL_T;
+ *portnum = HTTPS_PORT;
+ tport = httpsport;
+#endif
} else {
warnx("Invalid %s `%s'", desc, url);
cleanup_parse_url:
@@ -401,7 +421,7 @@ parse_url(const char *url, const char *desc, url_t *utype,
#ifdef INET6
/*
* Check if thost is an encoded IPv6 address, as per
- * RFC3986:
+ * RFC 3986:
* `[' ipv6-address ']'
*/
if (*thost == '[') {
@@ -469,7 +489,7 @@ sigjmp_buf httpabort;
/*
* Retrieve URL, via a proxy if necessary, using HTTP.
* If proxyenv is set, use that for the proxy, otherwise try ftp_proxy or
- * http_proxy as appropriate.
+ * http_proxy/https_proxy as appropriate.
* Supports HTTP redirects.
* Returns 1 on failure, 0 on completed xfer, -1 if ftp connection
* is still open (e.g, ftp xfer with trailing /)
@@ -504,17 +524,21 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
char *puser, *ppass, *useragent;
off_t hashbytes, rangestart, rangeend, entitylen;
int (*volatile closefunc)(FILE *);
- FILE *volatile fin;
+ FETCH *volatile fin;
FILE *volatile fout;
time_t mtime;
url_t urltype;
in_port_t portnum;
+#ifdef WITH_SSL
+ void *ssl;
+#endif
DPRINTF("fetch_url: `%s' proxyenv `%s'\n", url, STRorNULL(proxyenv));
oldintr = oldintp = NULL;
closefunc = NULL;
- fin = fout = NULL;
+ fin = NULL;
+ fout = NULL;
s = -1;
savefile = NULL;
auth = location = message = NULL;
@@ -537,7 +561,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
rval = fetch_ftp(url);
goto cleanup_fetch_url;
}
- if (urltype != HTTP_URL_T || outfile == NULL) {
+ if (!IS_HTTP_TYPE(urltype) || outfile == NULL) {
warnx("Invalid URL (no file after host) `%s'", url);
goto cleanup_fetch_url;
}
@@ -577,17 +601,17 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
}
if (urltype == FILE_URL_T) { /* file:// URLs */
direction = "copied";
- fin = fopen(decodedpath, "r");
+ fin = fetch_open(decodedpath, "r");
if (fin == NULL) {
warn("Can't open `%s'", decodedpath);
goto cleanup_fetch_url;
}
- if (fstat(fileno(fin), &sb) == 0) {
+ if (fstat(fetch_fileno(fin), &sb) == 0) {
mtime = sb.st_mtime;
filesize = sb.st_size;
}
if (restart_point) {
- if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
+ if (lseek(fetch_fileno(fin), restart_point, SEEK_SET) < 0) {
warn("Can't seek to restart `%s'",
decodedpath);
goto cleanup_fetch_url;
@@ -600,12 +624,19 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
(LLT)restart_point);
fputs("\n", ttyout);
}
+ if (0 == rcvbuf_size) {
+ rcvbuf_size = 8 * 1024; /* XXX */
+ }
} else { /* ftp:// or http:// URLs */
const char *leading;
int hasleading;
if (proxyenv == NULL) {
- if (urltype == HTTP_URL_T)
+#ifdef WITH_SSL
+ if (urltype == HTTPS_URL_T)
+ proxyenv = getoptionvalue("https_proxy");
+#endif
+ if (proxyenv == NULL && IS_HTTP_TYPE(urltype))
proxyenv = getoptionvalue("http_proxy");
else if (urltype == FTP_URL_T)
proxyenv = getoptionvalue("ftp_proxy");
@@ -666,7 +697,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
&ppath) == -1)
goto cleanup_fetch_url;
- if ((purltype != HTTP_URL_T
+ if ((!IS_HTTP_TYPE(purltype)
&& purltype != FTP_URL_T) ||
EMPTYSTRING(phost) ||
(! EMPTYSTRING(ppath)
@@ -696,6 +727,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
FREEPTR(path);
path = ftp_strdup(url);
FREEPTR(ppath);
+ urltype = purltype;
}
} /* ! EMPTYSTRING(proxyenv) */
@@ -706,7 +738,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
hints.ai_protocol = 0;
error = getaddrinfo(host, port, &hints, &res0);
if (error) {
- warnx("Can't lookup `%s:%s': %s", host, port,
+ warnx("Can't LOOKUP `%s:%s': %s", host, port,
(error == EAI_SYSTEM) ? strerror(errno)
: gai_strerror(error));
goto cleanup_fetch_url;
@@ -715,6 +747,9 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
host = res0->ai_canonname;
s = -1;
+#ifdef WITH_SSL
+ ssl = NULL;
+#endif
for (res = res0; res; res = res->ai_next) {
char hname[NI_MAXHOST], sname[NI_MAXSERV];
@@ -740,12 +775,23 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
continue;
}
- if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+ if (ftp_connect(s, res->ai_addr, res->ai_addrlen,
+ verbose || !res->ai_next) < 0) {
close(s);
s = -1;
continue;
}
+#ifdef WITH_SSL
+ if (urltype == HTTPS_URL_T) {
+ if ((ssl = fetch_start_ssl(s)) == NULL) {
+ close(s);
+ s = -1;
+ continue;
+ }
+ }
+#endif
+
/* success */
break;
}
@@ -755,7 +801,9 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
goto cleanup_fetch_url;
}
- fin = fdopen(s, "r+");
+ fin = fetch_fdopen(s, "r+");
+ fetch_set_ssl(fin, ssl);
+
/*
* Construct and send the request.
*/
@@ -770,11 +818,11 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
leading = ", ";
hasleading++;
}
- fprintf(fin, "GET %s HTTP/1.0\r\n", path);
+ fetch_printf(fin, "GET %s HTTP/1.0\r\n", path);
if (flushcache)
- fprintf(fin, "Pragma: no-cache\r\n");
+ fetch_printf(fin, "Pragma: no-cache\r\n");
} else {
- fprintf(fin, "GET %s HTTP/1.1\r\n", path);
+ fetch_printf(fin, "GET %s HTTP/1.1\r\n", path);
if (strchr(host, ':')) {
char *h, *p;
@@ -787,18 +835,23 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
(p = strchr(h, '%')) != NULL) {
*p = '\0';
}
- fprintf(fin, "Host: [%s]", h);
+ fetch_printf(fin, "Host: [%s]", h);
free(h);
} else
- fprintf(fin, "Host: %s", host);
+ fetch_printf(fin, "Host: %s", host);
+#ifdef WITH_SSL
+ if ((urltype == HTTP_URL_T && portnum != HTTP_PORT) ||
+ (urltype == HTTPS_URL_T && portnum != HTTPS_PORT))
+#else
if (portnum != HTTP_PORT)
- fprintf(fin, ":%u", portnum);
- fprintf(fin, "\r\n");
- fprintf(fin, "Accept: */*\r\n");
- fprintf(fin, "Connection: close\r\n");
+#endif
+ fetch_printf(fin, ":%u", portnum);
+ fetch_printf(fin, "\r\n");
+ fetch_printf(fin, "Accept: */*\r\n");
+ fetch_printf(fin, "Connection: close\r\n");
if (restart_point) {
fputs(leading, ttyout);
- fprintf(fin, "Range: bytes=" LLF "-\r\n",
+ fetch_printf(fin, "Range: bytes=" LLF "-\r\n",
(LLT)restart_point);
fprintf(ttyout, "restarting at " LLF,
(LLT)restart_point);
@@ -806,12 +859,12 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
hasleading++;
}
if (flushcache)
- fprintf(fin, "Cache-Control: no-cache\r\n");
+ fetch_printf(fin, "Cache-Control: no-cache\r\n");
}
if ((useragent=getenv("FTPUSERAGENT")) != NULL) {
- fprintf(fin, "User-Agent: %s\r\n", useragent);
+ fetch_printf(fin, "User-Agent: %s\r\n", useragent);
} else {
- fprintf(fin, "User-Agent: %s/%s\r\n",
+ fetch_printf(fin, "User-Agent: %s/%s\r\n",
FTP_PRODUCT, FTP_VERSION);
}
if (wwwauth) {
@@ -821,7 +874,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
leading = ", ";
hasleading++;
}
- fprintf(fin, "Authorization: %s\r\n", wwwauth);
+ fetch_printf(fin, "Authorization: %s\r\n", wwwauth);
}
if (proxyauth) {
if (verbose) {
@@ -830,18 +883,18 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
leading = ", ";
hasleading++;
}
- fprintf(fin, "Proxy-Authorization: %s\r\n", proxyauth);
+ fetch_printf(fin, "Proxy-Authorization: %s\r\n", proxyauth);
}
if (verbose && hasleading)
fputs(")\n", ttyout);
- fprintf(fin, "\r\n");
- if (fflush(fin) == EOF) {
+ fetch_printf(fin, "\r\n");
+ if (fetch_flush(fin) == EOF) {
warn("Writing HTTP request");
goto cleanup_fetch_url;
}
/* Read the response */
- len = get_line(fin, buf, sizeof(buf), &errormsg);
+ len = fetch_getline(fin, buf, sizeof(buf), &errormsg);
if (len < 0) {
if (*errormsg == '\n')
errormsg++;
@@ -865,7 +918,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
/* Read the rest of the header. */
while (1) {
- len = get_line(fin, buf, sizeof(buf), &errormsg);
+ len = fetch_getline(fin, buf, sizeof(buf), &errormsg);
if (len < 0) {
if (*errormsg == '\n')
errormsg++;
@@ -941,28 +994,18 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
} else if (match_token(&cp, "Last-Modified:")) {
struct tm parsed;
- char *t;
+ const char *t;
memset(&parsed, 0, sizeof(parsed));
- /* RFC1123 */
- if ((t = strptime(cp,
- "%a, %d %b %Y %H:%M:%S GMT",
- &parsed))
- /* RFC0850 */
- || (t = strptime(cp,
- "%a, %d-%b-%y %H:%M:%S GMT",
- &parsed))
- /* asctime */
- || (t = strptime(cp,
- "%a, %b %d %H:%M:%S %Y",
- &parsed))) {
+ t = parse_rfc2616time(&parsed, cp);
+ if (t != NULL) {
parsed.tm_isdst = -1;
if (*t == '\0')
mtime = timegm(&parsed);
#ifndef NO_DEBUG
if (ftp_debug && mtime != -1) {
fprintf(ttyout,
- "parsed date as: %s",
+ "parsed time as: %s",
rfc2822time(localtime(&mtime)));
}
#endif
@@ -1142,6 +1185,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
(void)xsignal(SIGQUIT, psummary);
oldintr = xsignal(SIGINT, aborthttp);
+ assert(rcvbuf_size > 0);
if ((size_t)rcvbuf_size > bufsize) {
if (xferbuf)
(void)free(xferbuf);
@@ -1162,7 +1206,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
lastchunk = 0;
/* read chunk-size */
if (ischunked) {
- if (fgets(xferbuf, bufsize, fin) == NULL) {
+ if (fetch_getln(xferbuf, bufsize, fin) == NULL) {
warnx("Unexpected EOF reading chunk-size");
goto cleanup_fetch_url;
}
@@ -1215,7 +1259,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
if (ischunked)
bufrem = MIN(chunksize, bufrem);
while (bufrem > 0) {
- flen = fread(xferbuf, sizeof(char),
+ flen = fetch_read(xferbuf, sizeof(char),
MIN((off_t)bufsize, bufrem), fin);
if (flen <= 0)
goto chunkdone;
@@ -1254,7 +1298,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
/* read CRLF after chunk*/
chunkdone:
if (ischunked) {
- if (fgets(xferbuf, bufsize, fin) == NULL) {
+ if (fetch_getln(xferbuf, bufsize, fin) == NULL) {
warnx("Unexpected EOF reading chunk CRLF");
goto cleanup_fetch_url;
}
@@ -1274,7 +1318,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
(void)putc('#', ttyout);
(void)putc('\n', ttyout);
}
- if (ferror(fin)) {
+ if (fetch_error(fin)) {
warn("Reading file");
goto cleanup_fetch_url;
}
@@ -1311,7 +1355,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
if (oldintp)
(void)xsignal(SIGPIPE, oldintp);
if (fin != NULL)
- fclose(fin);
+ fetch_close(fin);
else if (s != -1)
close(s);
if (closefunc != NULL && fout != NULL)
@@ -1340,7 +1384,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
/*
* Abort a HTTP retrieval
*/
-void
+static void
aborthttp(int notused)
{
char msgbuf[100];
@@ -1537,12 +1581,12 @@ fetch_ftp(const char *url)
* directories in one step.
*
* If we are dealing with an `ftp://host/path' URL
- * (urltype is FTP_URL_T), then RFC3986 says we need to
+ * (urltype is FTP_URL_T), then RFC 3986 says we need to
* send a separate CWD command for each unescaped "/"
* in the path, and we have to interpret %hex escaping
* *after* we find the slashes. It's possible to get
* empty components here, (from multiple adjacent
- * slashes in the path) and RFC3986 says that we should
+ * slashes in the path) and RFC 3986 says that we should
* still do `CWD ' (with a null argument) in such cases.
*
* Many ftp servers don't support `CWD ', so if there's an
@@ -1614,8 +1658,8 @@ fetch_ftp(const char *url)
fprintf(stderr,
"\n"
"ftp: The `CWD ' command (without a directory), which is required by\n"
-" RFC3986 to support the empty directory in the URL pathname (`//'),\n"
-" conflicts with the server's conformance to RFC0959.\n"
+" RFC 3986 to support the empty directory in the URL pathname (`//'),\n"
+" conflicts with the server's conformance to RFC 959.\n"
" Try the same URL without the `//' in the URL pathname.\n"
"\n");
goto cleanup_fetch_ftp;
@@ -1702,6 +1746,7 @@ static int
go_fetch(const char *url)
{
char *proxyenv;
+ char *p;
#ifndef NO_ABOUT
/*
@@ -1742,10 +1787,26 @@ go_fetch(const char *url)
/*
* Check for file:// and http:// URLs.
*/
- if (STRNEQUAL(url, HTTP_URL) || STRNEQUAL(url, FILE_URL))
+ if (STRNEQUAL(url, HTTP_URL)
+#ifdef WITH_SSL
+ || STRNEQUAL(url, HTTPS_URL)
+#endif
+ || STRNEQUAL(url, FILE_URL))
return (fetch_url(url, NULL, NULL, NULL));
/*
+ * If it contains "://" but does not begin with ftp://
+ * or something that was already handled, then it's
+ * unsupported.
+ *
+ * If it contains ":" but not "://" then we assume the
+ * part before the colon is a host name, not an URL scheme,
+ * so we don't try to match that here.
+ */
+ if ((p = strstr(url, "://")) != NULL && ! STRNEQUAL(url, FTP_URL))
+ errx(1, "Unsupported URL scheme `%.*s'", (int)(p - url), url);
+
+ /*
* Try FTP URL-style and host:file arguments next.
* If ftpproxy is set with an FTP URL, use fetch_url()
* Othewise, use fetch_ftp().
diff --git a/src/ftp.1 b/src/ftp.1
index 34a88c23520b..f6a3516d8b39 100644
--- a/src/ftp.1
+++ b/src/ftp.1
@@ -1,7 +1,7 @@
-.\" $NetBSD: ftp.1,v 1.13 2009/11/15 10:12:37 lukem Exp $
-.\" from NetBSD: ftp.1,v 1.130 2009/07/11 18:35:48 joerg Exp
+.\" $NetBSD: ftp.1,v 1.14 2013/05/05 11:17:30 lukem Exp $
+.\" from NetBSD: ftp.1,v 1.134 2012/12/22 16:57:10 christos Exp
.\"
-.\" Copyright (c) 1996-2008 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1996-2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
@@ -58,7 +58,7 @@
.\"
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
.\"
-.Dd May 10, 2008
+.Dd December 22, 2012
.Dt FTP 1
.Os
.Sh NAME
@@ -67,21 +67,11 @@
.Sh SYNOPSIS
.Nm
.Op Fl 46AadefginpRtVv
-.Bk -words
.Op Fl N Ar netrc
-.Ek
-.Bk -words
.Op Fl o Ar output
-.Ek
-.Bk -words
.Op Fl P Ar port
-.Ek
-.Bk -words
.Op Fl q Ar quittime
-.Ek
-.Bk -words
.Op Fl r Ar retry
-.Ek
.Op Fl s Ar srcaddr
.Bk -words
.\" [-T dir,max[,inc]]
@@ -778,7 +768,7 @@ mode is
.Dq stream .
.It Ic modtime Ar remote-file
Show the last modification time of the file on the remote machine, in
-.Li RFC2822
+.Li RFC 2822
format.
.It Ic more Ar file
A synonym for
@@ -999,7 +989,7 @@ traffic.
servers are required to support the
.Dv PASV
command by
-.Li RFC1123 ,
+.Li RFC 1123 ,
some do not.)
.It Ic pdir Op Ar remote-path
Perform
@@ -1336,7 +1326,7 @@ and
.Ar value
are not given, display all of the options and their values.
The currently supported options are:
-.Bl -tag -width "http_proxy" -offset indent
+.Bl -tag -width "https_proxy" -offset indent
.It Cm anonpass
Defaults to
.Ev $FTPANONPASS
@@ -1346,6 +1336,9 @@ Defaults to
.It Cm http_proxy
Defaults to
.Ev $http_proxy .
+.It Cm https_proxy
+Defaults to
+.Ev $https_proxy .
.It Cm no_proxy
Defaults to
.Ev $no_proxy .
@@ -1592,7 +1585,7 @@ ascii or binary (respectively).
The default transfer type is binary.
.Pp
In order to be compliant with
-.Li RFC3986 ,
+.Li RFC 3986 ,
.Nm
interprets the
.Ar path
@@ -1645,7 +1638,7 @@ Any
.Sq Li \&% Ns Ar XX
codes
(per
-.Li RFC3986 )
+.Li RFC 3986 )
within the path components are decoded, with
.Ar XX
representing a character code in hexadecimal.
@@ -1753,6 +1746,29 @@ and
(and optionally
.Sq password )
is in the URL, use them for the first attempt to authenticate.
+.\" https://[user[:password]@]host[:port]/path
+.It Li https:// Ns Oo Ar user Ns Oo Li \&: Ns Ar password Oc Ns Li \&@ Oc \
+Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns Li / Ns Ar path
+An
+.Tn HTTPS
+URL, retrieved using the
+.Tn HTTPS
+protocol.
+If
+.Ic "set https_proxy"
+is defined, it is used as a URL to an
+.Tn HTTPS
+proxy server.
+If
+.Tn HTTPS
+authorization is required to retrieve
+.Ar path ,
+and
+.Sq user
+(and optionally
+.Sq password )
+is in the URL, use them for the first attempt to authenticate.
+There is currently no certificate validation and verification.
.\" file:///path
.It Li file:/// Ns Ar path
A local URL, copied from
@@ -1902,7 +1918,7 @@ Failing the above checks, if
.Dq globbing
is enabled, local file names are expanded according to the rules
used in the
-.Xr csh 1 ;
+.Xr csh 1 ;
see the
.Ic glob
command.
@@ -2286,7 +2302,7 @@ URL characters are required in the username or password
or
.Sq / ) ,
encode them with
-.Li RFC3986
+.Li RFC 3986
.Sq Li \&% Ns Ar XX
encoding.
.Pp
@@ -2331,23 +2347,23 @@ for an example of how to make this automatic.
.Nm
attempts to be compliant with:
.Bl -tag -offset indent -width 8n
-.It Li RFC0959
+.It Li RFC 959
.Em File Transfer Protocol
-.It Li RFC1123
+.It Li RFC 1123
.Em Requirements for Internet Hosts - Application and Support
-.It Li RFC1635
+.It Li RFC 1635
.Em How to Use Anonymous FTP
-.It Li RFC2389
+.It Li RFC 2389
.Em Feature negotiation mechanism for the File Transfer Protocol
-.It Li RFC2428
+.It Li RFC 2428
.Em FTP Extensions for IPv6 and NATs
-.It Li RFC2616
+.It Li RFC 2616
.Em Hypertext Transfer Protocol -- HTTP/1.1
-.It Li RFC2822
+.It Li RFC 2822
.Em Internet Message Format
-.It Li RFC3659
+.It Li RFC 3659
.Em Extensions to FTP
-.It Li RFC3986
+.It Li RFC 3986
.Em Uniform Resource Identifier (URI)
.El
.Sh HISTORY
diff --git a/src/ftp.c b/src/ftp.c
index 4c4942f1bc1d..af236acac1d8 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1,5 +1,5 @@
-/* $NetBSD: ftp.c,v 1.18 2009/05/20 12:53:47 lukem Exp $ */
-/* from NetBSD: ftp.c,v 1.159 2009/04/15 03:42:33 jld Exp */
+/* $NetBSD: ftp.c,v 1.19 2013/05/05 11:17:31 lukem Exp $ */
+/* from NetBSD: ftp.c,v 1.164 2012/07/04 06:09:37 is Exp */
/*-
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -98,7 +98,7 @@
#if 0
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
#else
-__RCSID(" NetBSD: ftp.c,v 1.159 2009/04/15 03:42:33 jld Exp ");
+__RCSID(" NetBSD: ftp.c,v 1.164 2012/07/04 06:09:37 is Exp ");
#endif
#endif /* not lint */
@@ -114,6 +114,7 @@ __RCSID(" NetBSD: ftp.c,v 1.159 2009/04/15 03:42:33 jld Exp ");
#include <arpa/ftp.h>
#include <arpa/telnet.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -139,6 +140,7 @@ int ptflag = 0;
char pasv[BUFSIZ]; /* passive port for proxy data connection */
static int empty(FILE *, FILE *, int);
+__dead static void abort_squared(int);
struct sockinet {
union sockunion {
@@ -214,7 +216,8 @@ hookup(const char *host, const char *port)
hname, sname);
continue;
}
- if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+ if (ftp_connect(s, res->ai_addr, res->ai_addrlen,
+ verbose || !res->ai_next) < 0) {
close(s);
s = -1;
continue;
@@ -545,7 +548,7 @@ empty(FILE *ecin, FILE *din, int sec)
sigjmp_buf xferabort;
-void
+__dead static void
abortxfer(int notused)
{
char msgbuf[100];
@@ -772,6 +775,7 @@ sendrequest(const char *cmd, const char *local, const char *remote,
if (dout == NULL)
goto abort;
+ assert(sndbuf_size > 0);
if ((size_t)sndbuf_size > bufsize) {
if (buf)
(void)free(buf);
@@ -813,7 +817,7 @@ sendrequest(const char *cmd, const char *local, const char *remote,
}
(void)putc(c, dout);
bytes++;
-#if 0 /* this violates RFC0959 */
+#if 0 /* this violates RFC 959 */
if (c == '\r') {
(void)putc('\0', dout);
bytes++;
@@ -1033,6 +1037,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
progress = 0;
preserve = 0;
}
+ assert(rcvbuf_size > 0);
if ((size_t)rcvbuf_size > bufsize) {
if (buf)
(void)free(buf);
@@ -1160,7 +1165,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
abort:
/*
- * abort using RFC0959 recommended IP,SYNC sequence
+ * abort using RFC 959 recommended IP,SYNC sequence
*/
if (! sigsetjmp(xferabort, 1)) {
/* this is the first call */
@@ -1472,7 +1477,7 @@ initconn(void)
goto bad;
if (ftp_connect(data, (struct sockaddr *)&data_addr.si_su,
- data_addr.su_len) < 0) {
+ data_addr.su_len, 1) < 0) {
if (activefallback) {
(void)close(data);
data = -1;
@@ -1599,18 +1604,25 @@ initconn(void)
UC(p[0]), UC(p[1]));
break;
#ifdef INET6
- case AF_INET6:
- a = (char *)&data_addr.si_su.su_sin6.sin6_addr;
- p = (char *)&data_addr.su_port;
+ case AF_INET6: {
+ uint8_t ua[sizeof(data_addr.si_su.su_sin6.sin6_addr)];
+ uint8_t up[sizeof(data_addr.su_port)];
+
+ memcpy(ua, &data_addr.si_su.su_sin6.sin6_addr,
+ sizeof(ua));
+ memcpy(up, &data_addr.su_port, sizeof(up));
+
result = command(
"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
6, 16,
- UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
- UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
- UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
- UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
- 2, UC(p[0]), UC(p[1]));
+ ua[0], ua[1], ua[2], ua[3],
+ ua[4], ua[5], ua[6], ua[7],
+ ua[8], ua[9], ua[10], ua[11],
+ ua[12], ua[13], ua[14], ua[15],
+ 2,
+ up[0], up[1]);
break;
+ }
#endif
default:
result = COMPLETE + 1; /* xxx */
@@ -1820,7 +1832,7 @@ pswitch(int flag)
}
}
-void
+__dead static void
abortpt(int notused)
{
@@ -2032,7 +2044,7 @@ gunique(const char *local)
* too impatient to wait or there's another problem then ftp really
* needs to get back to a known state.
*/
-void
+static void
abort_squared(int dummy)
{
char msgbuf[100];
diff --git a/src/ftp_var.h b/src/ftp_var.h
index cd6dcbf2b5cf..79ac75decc61 100644
--- a/src/ftp_var.h
+++ b/src/ftp_var.h
@@ -1,5 +1,5 @@
-/* $NetBSD: ftp_var.h,v 1.10 2009/05/20 12:53:47 lukem Exp $ */
-/* from NetBSD: ftp_var.h,v 1.81 2009/04/12 10:18:52 lukem Exp */
+/* $NetBSD: ftp_var.h,v 1.11 2013/05/05 11:17:31 lukem Exp $ */
+/* from NetBSD: ftp_var.h,v 1.82 2012/12/21 18:07:36 christos Exp */
/*-
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -182,6 +182,7 @@ enum {
#define FTP_PORT 21 /* default if ! getservbyname("ftp/tcp") */
#define HTTP_PORT 80 /* default if ! getservbyname("http/tcp") */
+#define HTTPS_PORT 443 /* default if ! getservbyname("https/tcp") */
#ifndef GATE_PORT
#define GATE_PORT 21 /* default if ! getservbyname("ftpgate/tcp") */
#endif
@@ -278,6 +279,9 @@ GLOBAL char *username; /* name of user logged in as. (dynamic) */
GLOBAL sa_family_t family; /* address family to use for connections */
GLOBAL const char *ftpport; /* port number to use for FTP connections */
GLOBAL const char *httpport; /* port number to use for HTTP connections */
+#ifdef WITH_SSL
+GLOBAL const char *httpsport; /* port number to use for HTTPS connections */
+#endif
GLOBAL const char *gateport; /* port number to use for gateftp connections */
GLOBAL struct addrinfo *bindai; /* local address to bind as */
diff --git a/src/main.c b/src/main.c
index c2d922b93dbe..73390671ff37 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,5 @@
-/* $NetBSD: main.c,v 1.17 2009/11/15 10:12:37 lukem Exp $ */
-/* from NetBSD: main.c,v 1.117 2009/07/13 19:05:41 roy Exp */
+/* $NetBSD: main.c,v 1.19 2013/05/05 11:48:16 lukem Exp $ */
+/* from NetBSD: main.c,v 1.122 2012/12/22 16:57:10 christos Exp */
/*-
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -103,7 +103,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\
#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94";
#else
-__RCSID(" NetBSD: main.c,v 1.117 2009/07/13 19:05:41 roy Exp ");
+__RCSID(" NetBSD: main.c,v 1.122 2012/12/22 16:57:10 christos Exp ");
#endif
#endif /* not lint */
@@ -133,11 +133,12 @@ __RCSID(" NetBSD: main.c,v 1.117 2009/07/13 19:05:41 roy Exp ");
#define FTP_PROXY "ftp_proxy" /* env var with FTP proxy location */
#define HTTP_PROXY "http_proxy" /* env var with HTTP proxy location */
+#define HTTPS_PROXY "https_proxy" /* env var with HTTPS proxy location */
#define NO_PROXY "no_proxy" /* env var with list of non-proxied
* hosts, comma or space separated */
+__dead static void usage(void);
static void setupoption(const char *, const char *, const char *);
-int main(int, char *[]);
int
main(int volatile argc, char **volatile argv)
@@ -146,20 +147,22 @@ main(int volatile argc, char **volatile argv)
struct passwd *pw;
char *cp, *ep, *anonpass, *upload_path, *src_addr;
const char *anonuser;
- int dumbterm, s, isupload;
+ int dumbterm, isupload;
size_t len;
- socklen_t slen;
tzset();
-#if 0 /* tnftp */ /* XXX */
+#if defined(HAVE_SETLOCALE)
setlocale(LC_ALL, "");
-#endif /* tnftp */
+#endif
setprogname(argv[0]);
sigint_raised = 0;
ftpport = "ftp";
httpport = "http";
+#ifdef WITH_SSL
+ httpsport = "https";
+#endif
gateport = NULL;
cp = getenv("FTPSERVERPORT");
if (cp != NULL)
@@ -213,35 +216,6 @@ main(int volatile argc, char **volatile argv)
if (cp != NULL && strlcpy(netrc, cp, sizeof(netrc)) >= sizeof(netrc))
errx(1, "$NETRC `%s': %s", cp, strerror(ENAMETOOLONG));
- /*
- * Get the default socket buffer sizes if we don't already have them.
- * It doesn't matter which socket we do this to, because on the first
- * call no socket buffer sizes will have been modified, so we are
- * guaranteed to get the system defaults.
- */
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == -1)
- err(1, "Can't create socket to determine default socket sizes");
- slen = sizeof(rcvbuf_size);
- if (getsockopt(s, SOL_SOCKET, SO_RCVBUF,
- (void *)&rcvbuf_size, &slen) == -1)
- err(1, "Unable to get default rcvbuf size");
- slen = sizeof(sndbuf_size);
- if (getsockopt(s, SOL_SOCKET, SO_SNDBUF,
- (void *)&sndbuf_size, &slen) == -1)
- err(1, "Unable to get default sndbuf size");
- (void)close(s);
- /* sanity check returned buffer sizes */
- if (rcvbuf_size <= 0)
- rcvbuf_size = 8 * 1024;
- if (sndbuf_size <= 0)
- sndbuf_size = 8 * 1024;
-
- if (sndbuf_size > 8 * 1024 * 1024)
- sndbuf_size = 8 * 1024 * 1024;
- if (rcvbuf_size > 8 * 1024 * 1024)
- rcvbuf_size = 8 * 1024 * 1024;
-
marg_sl = ftp_sl_init();
if ((tmpdir = getenv("TMPDIR")) == NULL)
tmpdir = _PATH_TMP;
@@ -524,6 +498,7 @@ main(int volatile argc, char **volatile argv)
setupoption("anonpass", getenv("FTPANONPASS"), anonpass);
setupoption("ftp_proxy", getenv(FTP_PROXY), "");
setupoption("http_proxy", getenv(HTTP_PROXY), "");
+ setupoption("https_proxy", getenv(HTTPS_PROXY), "");
setupoption("no_proxy", getenv(NO_PROXY), "");
setupoption("pager", getenv("PAGER"), DEFAULTPAGER);
setupoption("prompt", getenv("FTPPROMPT"), DEFAULTPROMPT);
@@ -746,7 +721,7 @@ cmdscanner(void)
*/
if (strchr(margv[0], ':') != NULL ||
!editing ||
- el_parse(el, margc, (const char **)margv) != 0)
+ el_parse(el, margc, (void *)margv) != 0)
#endif /* !NO_EDITCOMPLETE */
fputs("?Invalid command.\n", ttyout);
continue;
@@ -1083,6 +1058,9 @@ usage(void)
" [[user@]host [port]] [host:path[/]] [file:///file]\n"
" [ftp://[user[:pass]@]host[:port]/path[/]]\n"
" [http://[user[:pass]@]host[:port]/path] [...]\n"
+#ifdef WITH_SSL
+" [https://[user[:pass]@]host[:port]/path] [...]\n"
+#endif
" %s -u URL file [...]\n", progname, progname);
exit(1);
}
diff --git a/src/progressbar.c b/src/progressbar.c
index bd4d76d46f15..11eae3aa38dd 100644
--- a/src/progressbar.c
+++ b/src/progressbar.c
@@ -1,5 +1,5 @@
-/* $NetBSD: progressbar.c,v 1.14 2009/05/20 12:53:47 lukem Exp $ */
-/* from NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp */
+/* $NetBSD: progressbar.c,v 1.15 2013/05/05 11:17:31 lukem Exp $ */
+/* from NetBSD: progressbar.c,v 1.22 2012/06/27 22:07:36 riastradh Exp */
/*-
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
@@ -36,14 +36,15 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID(" NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp ");
+__RCSID(" NetBSD: progressbar.c,v 1.22 2012/06/27 22:07:36 riastradh Exp ");
#endif /* not lint */
/*
* FTP User Program -- Misc support routines
*/
-#include <sys/types.h>
#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
#include <err.h>
#include <errno.h>
diff --git a/src/ssl.c b/src/ssl.c
new file mode 100644
index 000000000000..173db08ebbd2
--- /dev/null
+++ b/src/ssl.c
@@ -0,0 +1,615 @@
+/* $NetBSD: ssl.c,v 1.2 2013/05/05 13:17:06 lukem Exp $ */
+/* from NetBSD: ssl.c,v 1.2 2012/12/24 22:12:28 christos Exp */
+
+/*-
+ * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org>
+ * 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
+ * in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $
+ */
+
+#include "tnftp.h"
+
+#if 0 /* tnftp */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID(" NetBSD: ssl.c,v 1.2 2012/12/24 22:12:28 christos Exp ");
+#endif
+
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/uio.h>
+
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+#endif /* tnftp */
+
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "ssl.h"
+
+extern int quit_time, verbose, ftp_debug;
+extern FILE *ttyout;
+
+struct fetch_connect {
+ int sd; /* file/socket descriptor */
+ char *buf; /* buffer */
+ size_t bufsize; /* buffer size */
+ size_t bufpos; /* position of buffer */
+ size_t buflen; /* length of buffer contents */
+ struct { /* data cached after an
+ interrupted read */
+ char *buf;
+ size_t size;
+ size_t pos;
+ size_t len;
+ } cache;
+ int issock;
+ int iserr;
+ int iseof;
+ SSL *ssl; /* SSL handle */
+};
+
+/*
+ * Write a vector to a connection w/ timeout
+ * Note: can modify the iovec.
+ */
+static ssize_t
+fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
+{
+ struct timeval now, timeout, delta;
+ fd_set writefds;
+ ssize_t len, total;
+ int r;
+
+ if (quit_time > 0) {
+ FD_ZERO(&writefds);
+ gettimeofday(&timeout, NULL);
+ timeout.tv_sec += quit_time;
+ }
+
+ total = 0;
+ while (iovcnt > 0) {
+ while (quit_time > 0 && !FD_ISSET(conn->sd, &writefds)) {
+ FD_SET(conn->sd, &writefds);
+ gettimeofday(&now, NULL);
+ delta.tv_sec = timeout.tv_sec - now.tv_sec;
+ delta.tv_usec = timeout.tv_usec - now.tv_usec;
+ if (delta.tv_usec < 0) {
+ delta.tv_usec += 1000000;
+ delta.tv_sec--;
+ }
+ if (delta.tv_sec < 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ errno = 0;
+ r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
+ if (r == -1) {
+ if (errno == EINTR)
+ continue;
+ return -1;
+ }
+ }
+ errno = 0;
+ if (conn->ssl != NULL)
+ len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len);
+ else
+ len = writev(conn->sd, iov, iovcnt);
+ if (len == 0) {
+ /* we consider a short write a failure */
+ /* XXX perhaps we shouldn't in the SSL case */
+ errno = EPIPE;
+ return -1;
+ }
+ if (len < 0) {
+ if (errno == EINTR)
+ continue;
+ return -1;
+ }
+ total += len;
+ while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) {
+ len -= iov->iov_len;
+ iov++;
+ iovcnt--;
+ }
+ if (iovcnt > 0) {
+ iov->iov_len -= len;
+ iov->iov_base = (char *)iov->iov_base + len;
+ }
+ }
+ return total;
+}
+
+/*
+ * Write to a connection w/ timeout
+ */
+static int
+fetch_write(struct fetch_connect *conn, const char *str, size_t len)
+{
+ struct iovec iov[1];
+
+ iov[0].iov_base = (char *)__UNCONST(str);
+ iov[0].iov_len = len;
+ return fetch_writev(conn, iov, 1);
+}
+
+/*
+ * Send a formatted line; optionally echo to terminal
+ */
+int
+fetch_printf(struct fetch_connect *conn, const char *fmt, ...)
+{
+ va_list ap;
+ size_t len;
+ char *msg;
+ int r;
+
+ va_start(ap, fmt);
+ len = vasprintf(&msg, fmt, ap);
+ va_end(ap);
+
+ if (msg == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ r = fetch_write(conn, msg, len);
+ free(msg);
+ return r;
+}
+
+int
+fetch_fileno(struct fetch_connect *conn)
+{
+
+ return conn->sd;
+}
+
+int
+fetch_error(struct fetch_connect *conn)
+{
+
+ return conn->iserr;
+}
+
+static void
+fetch_clearerr(struct fetch_connect *conn)
+{
+
+ conn->iserr = 0;
+}
+
+int
+fetch_flush(struct fetch_connect *conn)
+{
+ int v;
+
+ if (conn->issock) {
+#ifdef TCP_NOPUSH
+ v = 0;
+ setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
+#endif
+ v = 1;
+ setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+ }
+ return 0;
+}
+
+/*ARGSUSED*/
+struct fetch_connect *
+fetch_open(const char *fname, const char *fmode)
+{
+ struct fetch_connect *conn;
+ int fd;
+
+ fd = open(fname, O_RDONLY); /* XXX: fmode */
+ if (fd < 0)
+ return NULL;
+
+ if ((conn = calloc(1, sizeof(*conn))) == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ conn->sd = fd;
+ conn->issock = 0;
+ return conn;
+}
+
+/*ARGSUSED*/
+struct fetch_connect *
+fetch_fdopen(int sd, const char *fmode)
+{
+ struct fetch_connect *conn;
+#if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH)
+ int opt = 1;
+#endif
+
+ if ((conn = calloc(1, sizeof(*conn))) == NULL)
+ return NULL;
+
+ conn->sd = sd;
+ conn->issock = 1;
+ fcntl(sd, F_SETFD, FD_CLOEXEC);
+#ifdef SO_NOSIGPIPE
+ setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
+#endif
+#ifdef TCP_NOPUSH
+ setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt));
+#endif
+ return conn;
+}
+
+int
+fetch_close(struct fetch_connect *conn)
+{
+ int rv = 0;
+
+ if (conn != NULL) {
+ fetch_flush(conn);
+ SSL_free(conn->ssl);
+ rv = close(conn->sd);
+ if (rv < 0) {
+ errno = rv;
+ rv = EOF;
+ }
+ free(conn->cache.buf);
+ free(conn->buf);
+ free(conn);
+ }
+ return rv;
+}
+
+#define FETCH_READ_WAIT -2
+#define FETCH_READ_ERROR -1
+
+static ssize_t
+fetch_ssl_read(SSL *ssl, void *buf, size_t len)
+{
+ ssize_t rlen;
+ int ssl_err;
+
+ rlen = SSL_read(ssl, buf, len);
+ if (rlen < 0) {
+ ssl_err = SSL_get_error(ssl, rlen);
+ if (ssl_err == SSL_ERROR_WANT_READ ||
+ ssl_err == SSL_ERROR_WANT_WRITE) {
+ return FETCH_READ_WAIT;
+ }
+ ERR_print_errors_fp(ttyout);
+ return FETCH_READ_ERROR;
+ }
+ return rlen;
+}
+
+static ssize_t
+fetch_nonssl_read(int sd, void *buf, size_t len)
+{
+ ssize_t rlen;
+
+ rlen = read(sd, buf, len);
+ if (rlen < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ return FETCH_READ_WAIT;
+ return FETCH_READ_ERROR;
+ }
+ return rlen;
+}
+
+/*
+ * Cache some data that was read from a socket but cannot be immediately
+ * returned because of an interrupted system call.
+ */
+static int
+fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes)
+{
+
+ if (conn->cache.size < nbytes) {
+ char *tmp = realloc(conn->cache.buf, nbytes);
+ if (tmp == NULL)
+ return -1;
+
+ conn->cache.buf = tmp;
+ conn->cache.size = nbytes;
+ }
+
+ memcpy(conn->cache.buf, src, nbytes);
+ conn->cache.len = nbytes;
+ conn->cache.pos = 0;
+ return 0;
+}
+
+ssize_t
+fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
+{
+ struct timeval now, timeout, delta;
+ fd_set readfds;
+ ssize_t rlen, total;
+ size_t len;
+ char *start, *buf;
+
+ if (quit_time > 0) {
+ gettimeofday(&timeout, NULL);
+ timeout.tv_sec += quit_time;
+ }
+
+ total = 0;
+ start = buf = ptr;
+ len = size * nmemb;
+
+ if (conn->cache.len > 0) {
+ /*
+ * The last invocation of fetch_read was interrupted by a
+ * signal after some data had been read from the socket. Copy
+ * the cached data into the supplied buffer before trying to
+ * read from the socket again.
+ */
+ total = (conn->cache.len < len) ? conn->cache.len : len;
+ memcpy(buf, conn->cache.buf, total);
+
+ conn->cache.len -= total;
+ conn->cache.pos += total;
+ len -= total;
+ buf += total;
+ }
+
+ while (len > 0) {
+ /*
+ * The socket is non-blocking. Instead of the canonical
+ * select() -> read(), we do the following:
+ *
+ * 1) call read() or SSL_read().
+ * 2) if an error occurred, return -1.
+ * 3) if we received data but we still expect more,
+ * update our counters and loop.
+ * 4) if read() or SSL_read() signaled EOF, return.
+ * 5) if we did not receive any data but we're not at EOF,
+ * call select().
+ *
+ * In the SSL case, this is necessary because if we
+ * receive a close notification, we have to call
+ * SSL_read() one additional time after we've read
+ * everything we received.
+ *
+ * In the non-SSL case, it may improve performance (very
+ * slightly) when reading small amounts of data.
+ */
+ if (conn->ssl != NULL)
+ rlen = fetch_ssl_read(conn->ssl, buf, len);
+ else
+ rlen = fetch_nonssl_read(conn->sd, buf, len);
+ if (rlen == 0) {
+ break;
+ } else if (rlen > 0) {
+ len -= rlen;
+ buf += rlen;
+ total += rlen;
+ continue;
+ } else if (rlen == FETCH_READ_ERROR) {
+ if (errno == EINTR)
+ fetch_cache_data(conn, start, total);
+ return -1;
+ }
+ FD_ZERO(&readfds);
+ while (!FD_ISSET(conn->sd, &readfds)) {
+ FD_SET(conn->sd, &readfds);
+ if (quit_time > 0) {
+ gettimeofday(&now, NULL);
+ if (!timercmp(&timeout, &now, >)) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ timersub(&timeout, &now, &delta);
+ }
+ errno = 0;
+ if (select(conn->sd + 1, &readfds, NULL, NULL,
+ quit_time > 0 ? &delta : NULL) < 0) {
+ if (errno == EINTR)
+ continue;
+ return -1;
+ }
+ }
+ }
+ return total;
+}
+
+#define MIN_BUF_SIZE 1024
+
+/*
+ * Read a line of text from a connection w/ timeout
+ */
+char *
+fetch_getln(char *str, int size, struct fetch_connect *conn)
+{
+ size_t tmpsize;
+ ssize_t len;
+ char c;
+
+ if (conn->buf == NULL) {
+ if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
+ errno = ENOMEM;
+ conn->iserr = 1;
+ return NULL;
+ }
+ conn->bufsize = MIN_BUF_SIZE;
+ }
+
+ if (conn->iserr || conn->iseof)
+ return NULL;
+
+ if (conn->buflen - conn->bufpos > 0)
+ goto done;
+
+ conn->buf[0] = '\0';
+ conn->bufpos = 0;
+ conn->buflen = 0;
+ do {
+ len = fetch_read(&c, sizeof(c), 1, conn);
+ if (len == -1) {
+ conn->iserr = 1;
+ return NULL;
+ }
+ if (len == 0) {
+ conn->iseof = 1;
+ break;
+ }
+ conn->buf[conn->buflen++] = c;
+ if (conn->buflen == conn->bufsize) {
+ char *tmp = conn->buf;
+ tmpsize = conn->bufsize * 2 + 1;
+ if ((tmp = realloc(tmp, tmpsize)) == NULL) {
+ errno = ENOMEM;
+ conn->iserr = 1;
+ return NULL;
+ }
+ conn->buf = tmp;
+ conn->bufsize = tmpsize;
+ }
+ } while (c != '\n');
+
+ if (conn->buflen == 0)
+ return NULL;
+ done:
+ tmpsize = MIN(size - 1, (int)(conn->buflen - conn->bufpos));
+ memcpy(str, conn->buf + conn->bufpos, tmpsize);
+ str[tmpsize] = '\0';
+ conn->bufpos += tmpsize;
+ return str;
+}
+
+int
+fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
+ const char **errormsg)
+{
+ size_t len;
+ int rv;
+
+ if (fetch_getln(buf, buflen, conn) == NULL) {
+ if (conn->iseof) { /* EOF */
+ rv = -2;
+ if (errormsg)
+ *errormsg = "\nEOF received";
+ } else { /* error */
+ rv = -1;
+ if (errormsg)
+ *errormsg = "Error encountered";
+ }
+ fetch_clearerr(conn);
+ return rv;
+ }
+ len = strlen(buf);
+ if (buf[len - 1] == '\n') { /* clear any trailing newline */
+ buf[--len] = '\0';
+ } else if (len == buflen - 1) { /* line too long */
+ while (1) {
+ char c;
+ ssize_t rlen = fetch_read(&c, sizeof(c), 1, conn);
+ if (rlen <= 0 || c == '\n')
+ break;
+ }
+ if (errormsg)
+ *errormsg = "Input line is too long";
+ fetch_clearerr(conn);
+ return -3;
+ }
+ if (errormsg)
+ *errormsg = NULL;
+ return len;
+}
+
+void *
+fetch_start_ssl(int sock)
+{
+ SSL *ssl;
+ SSL_CTX *ctx;
+ int ret, ssl_err;
+
+ /* Init the SSL library and context */
+ if (!SSL_library_init()){
+ fprintf(ttyout, "SSL library init failed\n");
+ return NULL;
+ }
+
+ SSL_load_error_strings();
+
+ ctx = SSL_CTX_new(SSLv23_client_method());
+ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+
+ ssl = SSL_new(ctx);
+ if (ssl == NULL){
+ fprintf(ttyout, "SSL context creation failed\n");
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
+ SSL_set_fd(ssl, sock);
+ while ((ret = SSL_connect(ssl)) == -1) {
+ ssl_err = SSL_get_error(ssl, ret);
+ if (ssl_err != SSL_ERROR_WANT_READ &&
+ ssl_err != SSL_ERROR_WANT_WRITE) {
+ ERR_print_errors_fp(ttyout);
+ SSL_free(ssl);
+ return NULL;
+ }
+ }
+
+ if (ftp_debug && verbose) {
+ X509 *cert;
+ X509_NAME *name;
+ char *str;
+
+ fprintf(ttyout, "SSL connection established using %s\n",
+ SSL_get_cipher(ssl));
+ cert = SSL_get_peer_certificate(ssl);
+ name = X509_get_subject_name(cert);
+ str = X509_NAME_oneline(name, 0, 0);
+ fprintf(ttyout, "Certificate subject: %s\n", str);
+ free(str);
+ name = X509_get_issuer_name(cert);
+ str = X509_NAME_oneline(name, 0, 0);
+ fprintf(ttyout, "Certificate issuer: %s\n", str);
+ free(str);
+ }
+
+ return ssl;
+}
+
+
+void
+fetch_set_ssl(struct fetch_connect *conn, void *ssl)
+{
+ conn->ssl = ssl;
+}
diff --git a/src/ssl.h b/src/ssl.h
new file mode 100644
index 000000000000..8e4f25082813
--- /dev/null
+++ b/src/ssl.h
@@ -0,0 +1,63 @@
+/* $NetBSD: ssl.h,v 1.1.1.1 2013/05/05 10:40:57 lukem Exp $ */
+/* from NetBSD: ssl.h,v 1.1 2012/12/21 18:07:36 christos Exp */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#ifdef WITH_SSL
+
+#define FETCH struct fetch_connect
+struct fetch_connect;
+
+int fetch_printf(struct fetch_connect *, const char *fmt, ...);
+int fetch_fileno(struct fetch_connect *);
+int fetch_error(struct fetch_connect *);
+int fetch_flush(struct fetch_connect *);
+struct fetch_connect *fetch_open(const char *, const char *);
+struct fetch_connect *fetch_fdopen(int, const char *);
+int fetch_close(struct fetch_connect *);
+ssize_t fetch_read(void *, size_t, size_t, struct fetch_connect *);
+char *fetch_getln(char *, int, struct fetch_connect *);
+int fetch_getline(struct fetch_connect *, char *, size_t, const char **);
+void fetch_set_ssl(struct fetch_connect *, void *);
+void *fetch_start_ssl(int);
+
+#else /* !WITH_SSL */
+
+#define FETCH FILE
+
+#define fetch_printf fprintf
+#define fetch_fileno fileno
+#define fetch_error ferror
+#define fetch_flush fflush
+#define fetch_open fopen
+#define fetch_fdopen fdopen
+#define fetch_close fclose
+#define fetch_read fread
+#define fetch_getln fgets
+#define fetch_getline get_line
+#define fetch_set_ssl(a, b)
+
+#endif /* !WITH_SSL */
diff --git a/src/util.c b/src/util.c
index 366b19450b84..531712c3ded1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,5 +1,5 @@
-/* $NetBSD: util.c,v 1.21 2009/11/15 10:12:37 lukem Exp $ */
-/* from NetBSD: util.c,v 1.152 2009/07/13 19:05:41 roy Exp */
+/* $NetBSD: util.c,v 1.23 2013/05/05 11:51:43 lukem Exp $ */
+/* from NetBSD: util.c,v 1.158 2013/02/19 23:29:15 dsl Exp */
/*-
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID(" NetBSD: util.c,v 1.152 2009/07/13 19:05:41 roy Exp ");
+__RCSID(" NetBSD: util.c,v 1.158 2013/02/19 23:29:15 dsl Exp ");
#endif /* not lint */
/*
@@ -90,6 +90,7 @@ __RCSID(" NetBSD: util.c,v 1.152 2009/07/13 19:05:41 roy Exp ");
#include <signal.h>
#include <libgen.h>
#include <limits.h>
+#include <locale.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
@@ -175,7 +176,7 @@ parse_feat(const char *fline)
/*
* work-around broken ProFTPd servers that can't
- * even obey RFC2389.
+ * even obey RFC 2389.
*/
while (*fline && isspace((int)*fline))
fline++;
@@ -208,25 +209,20 @@ getremoteinfo(void)
/* determine remote system type */
if (command("SYST") == COMPLETE) {
if (overbose) {
- char *cp, c;
-
- c = 0;
- cp = strchr(reply_string + 4, ' ');
- if (cp == NULL)
- cp = strchr(reply_string + 4, '\r');
- if (cp) {
- if (cp[-1] == '.')
- cp--;
- c = *cp;
- *cp = '\0';
- }
-
- fprintf(ttyout, "Remote system type is %s.\n",
- reply_string + 4);
- if (cp)
- *cp = c;
+ int os_len = strcspn(reply_string + 4, " \r\n\t");
+ if (os_len > 1 && reply_string[4 + os_len - 1] == '.')
+ os_len--;
+ fprintf(ttyout, "Remote system type is %.*s.\n",
+ os_len, reply_string + 4);
}
- if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
+ /*
+ * Decide whether we should default to bninary.
+ * Traditionally checked for "215 UNIX Type: L8", but
+ * some printers report "Linux" ! so be more forgiving.
+ * In reality we probably almost never want text any more.
+ */
+ if (!strncasecmp(reply_string + 4, "unix", 4) ||
+ !strncasecmp(reply_string + 4, "linux", 5)) {
if (proxy)
unix_proxy = 1;
else
@@ -399,7 +395,7 @@ ftp_login(const char *host, const char *luser, const char *lpass)
*/
if (anonftp) {
FREEPTR(fuser);
- fuser = ftp_strdup("anonymous"); /* as per RFC1635 */
+ fuser = ftp_strdup("anonymous"); /* as per RFC 1635 */
FREEPTR(pass);
pass = ftp_strdup(getoptionvalue("anonpass"));
}
@@ -763,7 +759,7 @@ remotemodtime(const char *file, int noisy)
else
goto cleanup_parse_time;
} else {
- DPRINTF("remotemodtime: parsed date `%s' as " LLF
+ DPRINTF("remotemodtime: parsed time `%s' as " LLF
", %s",
timestr, (LLT)rtime,
rfc2822time(localtime(&rtime)));
@@ -784,7 +780,7 @@ remotemodtime(const char *file, int noisy)
}
/*
- * Format tm in an RFC2822 compatible manner, with a trailing \n.
+ * Format tm in an RFC 2822 compatible manner, with a trailing \n.
* Returns a pointer to a static string containing the result.
*/
const char *
@@ -794,11 +790,41 @@ rfc2822time(const struct tm *tm)
if (strftime(result, sizeof(result),
"%a, %d %b %Y %H:%M:%S %z\n", tm) == 0)
- errx(1, "Can't convert RFC2822 time: buffer too small");
+ errx(1, "Can't convert RFC 2822 time: buffer too small");
return result;
}
/*
+ * Parse HTTP-date as per RFC 2616.
+ * Return a pointer to the next character of the consumed date string,
+ * or NULL if failed.
+ */
+const char *
+parse_rfc2616time(struct tm *parsed, const char *httpdate)
+{
+ const char *t;
+#if defined(HAVE_SETLOCALE)
+ const char *curlocale;
+
+ /* The representation of %a depends on the current locale. */
+ curlocale = setlocale(LC_TIME, NULL);
+ (void)setlocale(LC_TIME, "C");
+#endif
+ /* RFC 1123 */
+ if ((t = strptime(httpdate, "%a, %d %b %Y %H:%M:%S GMT", parsed)) ||
+ /* RFC 850 */
+ (t = strptime(httpdate, "%a, %d-%b-%y %H:%M:%S GMT", parsed)) ||
+ /* asctime */
+ (t = strptime(httpdate, "%a, %b %d %H:%M:%S %Y", parsed))) {
+ ; /* do nothing */
+ }
+#if defined(HAVE_SETLOCALE)
+ (void)setlocale(LC_TIME, curlocale);
+#endif
+ return t;
+}
+
+/*
* Update global `localcwd', which contains the state of the local cwd
*/
void
@@ -1060,6 +1086,32 @@ strsuftoi(const char *arg)
void
setupsockbufsize(int sock)
{
+ socklen_t slen;
+
+ if (0 == rcvbuf_size) {
+ slen = sizeof(rcvbuf_size);
+ if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ (void *)&rcvbuf_size, &slen) == -1)
+ err(1, "Unable to determine rcvbuf size");
+ if (rcvbuf_size <= 0)
+ rcvbuf_size = 8 * 1024;
+ if (rcvbuf_size > 8 * 1024 * 1024)
+ rcvbuf_size = 8 * 1024 * 1024;
+ DPRINTF("setupsockbufsize: rcvbuf_size determined as %d\n",
+ rcvbuf_size);
+ }
+ if (0 == sndbuf_size) {
+ slen = sizeof(sndbuf_size);
+ if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF,
+ (void *)&sndbuf_size, &slen) == -1)
+ err(1, "Unable to determine sndbuf size");
+ if (sndbuf_size <= 0)
+ sndbuf_size = 8 * 1024;
+ if (sndbuf_size > 8 * 1024 * 1024)
+ sndbuf_size = 8 * 1024 * 1024;
+ DPRINTF("setupsockbufsize: sndbuf_size determined as %d\n",
+ sndbuf_size);
+ }
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
(void *)&sndbuf_size, sizeof(sndbuf_size)) == -1)
@@ -1078,9 +1130,8 @@ ftpvis(char *dst, size_t dstlen, const char *src, size_t srclen)
{
size_t di, si;
- for (di = si = 0;
- src[si] != '\0' && di < dstlen && si < srclen;
- di++, si++) {
+ di = si = 0;
+ while (src[si] != '\0' && di < dstlen && si < srclen) {
switch (src[si]) {
case '\\':
case ' ':
@@ -1088,12 +1139,18 @@ ftpvis(char *dst, size_t dstlen, const char *src, size_t srclen)
case '\r':
case '\n':
case '"':
- dst[di++] = '\\';
- if (di >= dstlen)
+ /*
+ * Need room for two characters and NUL, avoiding
+ * incomplete escape sequences at end of dst.
+ */
+ if (di >= dstlen - 3)
break;
+ dst[di++] = '\\';
/* FALLTHROUGH */
default:
- dst[di] = src[si];
+ dst[di] = src[si++];
+ if (di < dstlen)
+ di++;
}
}
dst[di] = '\0';
@@ -1300,7 +1357,7 @@ get_line(FILE *stream, char *buf, size_t buflen, const char **errormsg)
* error message displayed.)
*/
int
-ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen)
+ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen, int pe)
{
int flags, rv, timeout, error;
socklen_t slen;
@@ -1366,8 +1423,9 @@ ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen)
rv = connect(sock, name, namelen); /* inititate the connection */
if (rv == -1) { /* connection error */
if (errno != EINPROGRESS) { /* error isn't "please wait" */
+ if (pe || (errno != EHOSTUNREACH))
connecterror:
- warn("Can't connect to `%s:%s'", hname, sname);
+ warn("Can't connect to `%s:%s'", hname, sname);
return -1;
}
diff --git a/src/version.h b/src/version.h
index 6bb363103071..6ae9f3f81f79 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,5 +1,5 @@
-/* $NetBSD: version.h,v 1.4 2009/11/15 10:12:37 lukem Exp $ */
-/* from NetBSD: version.h,v 1.80 2009/11/15 10:03:16 lukem Exp */
+/* $NetBSD: version.h,v 1.5 2013/05/05 11:17:31 lukem Exp $ */
+/* from NetBSD: version.h,v 1.84 2013/05/05 10:40:19 lukem Exp */
/*-
* Copyright (c) 1999-2009 The NetBSD Foundation, Inc.
@@ -35,5 +35,5 @@
#endif
#ifndef FTP_VERSION
-#define FTP_VERSION "20090915"
+#define FTP_VERSION "20130220"
#endif