Hello community, here is the log from the commit of package tftp for openSUSE:Factory checked in at Fri Jun 24 09:56:51 CEST 2011.
-------- --- tftp/tftp.changes 2010-12-11 01:00:45.000000000 +0100 +++ /mounts/work_src_done/STABLE/tftp/tftp.changes 2011-06-24 09:14:08.000000000 +0200 @@ -1,0 +2,19 @@ +Fri Jun 24 07:09:50 UTC 2011 - [email protected] + +- unbreak tftp by changing to user to run as in tftpd itself, + not via xinetd (bnc#682340) + +------------------------------------------------------------------- +Thu Jun 23 12:17:37 UTC 2011 - [email protected] + +- update to version-5.1 + - Add -P option to write a PID file. Patch by Ferenc Wagner. + - Bounce the syslog socket in standalone mode, in case the + syslog daemon has been restarted. Patch by Ferenc Wagner. + - Build fixes. + - Fix handling of block number wraparound after a successful + options negotiation. + - Fix a buffer overflow in option parsing. +- fixes bnc#699714, CVE-2011-2199 + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- tftp-hpa-5.0.tar.bz2 New: ---- tftp-hpa-5.1.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tftp.spec ++++++ --- /var/tmp/diff_new_pack.LhGDcW/_old 2011-06-24 09:54:44.000000000 +0200 +++ /var/tmp/diff_new_pack.LhGDcW/_new 2011-06-24 09:54:44.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package tftp (Version 5.0) +# spec file for package tftp # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,13 +18,13 @@ Name: tftp -Version: 5.0 +Version: 5.1 Release: 1 License: BSD3c Summary: Trivial File Transfer Protocol (TFTP) Url: http://www.kernel.org/pub/software/network/tftp/ Group: Productivity/Networking/Ftp/Clients -Source: tftp-hpa-%{version}.tar.bz2 +Source: http://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{version}.tar.bz2 Source1: tftp.xinetd Patch0: tftp-hpa-0.43_include_sys_params.patch Patch1: tftp-hpa-0.46_colon_check.patch @@ -68,7 +68,7 @@ %install %makeinstall INSTALLROOT=%{buildroot} MANDIR="%{_mandir}" -install -D -m 0644 %{S:1} %{buildroot}%{_sysconfdir}/xinetd.d/tftp +install -D -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/xinetd.d/tftp install -d -m 0750 %{buildroot}/srv/tftpboot %pre ++++++ tftp-hpa-0.48-tzfix.patch ++++++ --- /var/tmp/diff_new_pack.LhGDcW/_old 2011-06-24 09:54:44.000000000 +0200 +++ /var/tmp/diff_new_pack.LhGDcW/_new 2011-06-24 09:54:44.000000000 +0200 @@ -1,9 +1,9 @@ -Index: tftp-hpa-git-0.48/tftpd/tftpd.c +Index: tftp-hpa-5.1/tftpd/tftpd.c =================================================================== ---- tftp-hpa-git-0.48.orig/tftpd/tftpd.c -+++ tftp-hpa-git-0.48/tftpd/tftpd.c -@@ -350,6 +350,14 @@ int main(int argc, char **argv) - #endif +--- tftp-hpa-5.1.orig/tftpd/tftpd.c ++++ tftp-hpa-5.1/tftpd/tftpd.c +@@ -384,6 +384,14 @@ int main(int argc, char **argv) + const char *pidfile = NULL; u_short tp_opcode; + time_t my_time = 0; ++++++ tftp-hpa-5.0.tar.bz2 -> tftp-hpa-5.1.tar.bz2 ++++++ ++++ 20789 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/CHANGES new/tftp-hpa-5.1/CHANGES --- old/tftp-hpa-5.0/CHANGES 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/CHANGES 2011-06-23 01:32:56.000000000 +0200 @@ -1,3 +1,17 @@ +Changes in 5.1: + Add -P option to write a PID file. Patch by Ferenc Wagner. + + Bounce the syslog socket in standalone mode, in case the + syslog daemon has been restarted. Patch by Ferenc Wagner. + + Build fixes. + + Fix handling of block number wraparound after a successful + options negotiation. + + Fix a buffer overflow in option parsing. + + Changes in 5.0: Try to on platforms with getaddrinfo() without AI_ADDRCONFIG or AI_CANONNAME. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/MCONFIG.in new/tftp-hpa-5.1/MCONFIG.in --- old/tftp-hpa-5.0/MCONFIG.in 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/MCONFIG.in 2011-06-23 01:32:56.000000000 +0200 @@ -32,7 +32,7 @@ SBINDIR = @sbindir@ # Data root directory -DATAROOTDIR = @datarootdir@ +datarootdir = @datarootdir@ # Binary suffixes O = @OBJEXT@ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/aconfig.h.in new/tftp-hpa-5.1/aconfig.h.in --- old/tftp-hpa-5.0/aconfig.h.in 2009-02-16 23:51:36.000000000 +0100 +++ new/tftp-hpa-5.1/aconfig.h.in 2011-06-23 01:33:28.000000000 +0200 @@ -21,6 +21,9 @@ /* Define to 1 if you have the `ftruncate' function. */ #undef HAVE_FTRUNCATE +/* Define if fcntl.h defines F_SETLK */ +#undef HAVE_F_SETLK_DEFINITION + /* Define if getaddrinfo function was found */ #undef HAVE_GETADDRINFO @@ -54,6 +57,12 @@ /* Define to 1 if you have the `wrap' library (-lwrap). */ #undef HAVE_LIBWRAP +/* Define if sys/file.h defines LOCK_EX */ +#undef HAVE_LOCK_EX_DEFINITION + +/* Define if sys/file.h defines LOCK_SH */ +#undef HAVE_LOCK_SH_DEFINITION + /* Define to 1 if the system has the type `long long'. */ #undef HAVE_LONG_LONG @@ -141,6 +150,9 @@ /* Define to 1 if you have the <sysexits.h> header file. */ #undef HAVE_SYSEXITS_H +/* Define to 1 if you have the <sys/file.h> header file. */ +#undef HAVE_SYS_FILE_H + /* Define to 1 if you have the <sys/filio.h> header file. */ #undef HAVE_SYS_FILIO_H @@ -204,6 +216,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/autogen.sh new/tftp-hpa-5.1/autogen.sh --- old/tftp-hpa-5.0/autogen.sh 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/autogen.sh 2011-06-23 01:32:56.000000000 +0200 @@ -1,3 +1,2 @@ #!/bin/sh -autoheader -autoconf +make autoconf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/configure.in new/tftp-hpa-5.1/configure.in --- old/tftp-hpa-5.0/configure.in 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/configure.in 2011-06-23 01:32:56.000000000 +0200 @@ -46,6 +46,7 @@ AC_CHECK_HEADERS(sysexits.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(unistd.h) +AC_CHECK_HEADERS(sys/file.h) AC_CHECK_HEADERS(sys/filio.h) AC_CHECK_HEADERS(sys/stat.h) AC_CHECK_HEADERS(sys/time.h) @@ -140,6 +141,11 @@ PA_HEADER_DEFINES(fcntl.h, int, O_BINARY) PA_HEADER_DEFINES(fcntl.h, int, O_TEXT) +PA_HEADER_DEFINES(fcntl.h, int, F_SETLK) + +PA_HEADER_DEFINES(sys/file.h, int, LOCK_SH) +PA_HEADER_DEFINES(sys/file.h, int, LOCK_EX) + AH_TEMPLATE([HAVE_SIGSETJMP], [Define if we have sigsetjmp, siglongjmp and sigjmp_buf.]) PA_SIGSETJMP([AC_DEFINE(HAVE_SIGSETJMP)]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftp.spec new/tftp-hpa-5.1/tftp.spec --- old/tftp-hpa-5.0/tftp.spec 2009-02-16 23:51:36.000000000 +0100 +++ new/tftp-hpa-5.1/tftp.spec 2011-06-23 01:33:28.000000000 +0200 @@ -1,11 +1,11 @@ Summary: The client for the Trivial File Transfer Protocol (TFTP). Name: tftp -Version: 5.0 +Version: 5.1 Release: 1 License: BSD Group: Applications/Internet Source0: http://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{version}.tar.gz -BuildPreReq: tcp_wrappers +BuildRequires: tcp_wrappers-devel BuildRoot: %{_tmppath}/%{name}-root %description diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftp.spec.in new/tftp-hpa-5.1/tftp.spec.in --- old/tftp-hpa-5.0/tftp.spec.in 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/tftp.spec.in 2011-06-23 01:32:56.000000000 +0200 @@ -5,7 +5,7 @@ License: BSD Group: Applications/Internet Source0: http://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{version}.tar.gz -BuildPreReq: tcp_wrappers +BuildRequires: tcp_wrappers-devel BuildRoot: %{_tmppath}/%{name}-root %description diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftpd/recvfrom.c new/tftp-hpa-5.1/tftpd/recvfrom.c --- old/tftp-hpa-5.0/tftpd/recvfrom.c 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/tftpd/recvfrom.c 2011-06-23 01:32:56.000000000 +0200 @@ -245,7 +245,8 @@ int myrecvfrom(int s, void *buf, int len, unsigned int flags, - struct sockaddr *from, int *fromlen, union sock_addr *myaddr) + struct sockaddr *from, socklen_t * fromlen, + union sock_addr *myaddr) { /* There is no way we can get the local address, fudge it */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftpd/remap.c new/tftp-hpa-5.1/tftpd/remap.c --- old/tftp-hpa-5.0/tftpd/remap.c 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/tftpd/remap.c 2011-06-23 01:32:56.000000000 +0200 @@ -30,14 +30,13 @@ #define RULE_EXIT 0x04 /* Exit after matching this rule */ #define RULE_RESTART 0x08 /* Restart at the top after matching this rule */ #define RULE_ABORT 0x10 /* Terminate processing with an error */ -#define RULE_GETONLY 0x20 /* Applicable to GET only */ -#define RULE_PUTONLY 0x40 /* Applicable to PUT only */ -#define RULE_INVERSE 0x80 /* Execute if regex *doesn't* match */ +#define RULE_INVERSE 0x20 /* Execute if regex *doesn't* match */ struct rule { struct rule *next; int nrule; int rule_flags; + char rule_mode; regex_t rx; const char *pattern; }; @@ -221,15 +220,13 @@ case 'i': rxflags |= REG_ICASE; break; - case 'G': - r->rule_flags |= RULE_GETONLY; - break; - case 'P': - r->rule_flags |= RULE_PUTONLY; - break; case '~': r->rule_flags |= RULE_INVERSE; break; + case 'G': + case 'P': + r->rule_mode = *p; + break; default: syslog(LOG_ERR, "Remap command \"%s\" on line %d contains invalid char \"%c\"", @@ -329,7 +326,7 @@ /* Execute a rule set on a string; returns a malloc'd new string. */ char *rewrite_string(const char *input, const struct rule *rules, - int is_put, match_pattern_callback macrosub, + char mode, match_pattern_callback macrosub, const char **errmsg) { char *current = tfstrdup(input); @@ -348,10 +345,8 @@ } for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) { - if (((ruleptr->rule_flags & RULE_GETONLY) && is_put) || - ((ruleptr->rule_flags & RULE_PUTONLY) && !is_put)) { + if (ruleptr->rule_mode && ruleptr->rule_mode != mode) continue; /* Rule not applicable, try next */ - } if (!deadman--) { syslog(LOG_WARNING, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftpd/remap.h new/tftp-hpa-5.1/tftpd/remap.h --- old/tftp-hpa-5.0/tftpd/remap.h 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/tftpd/remap.h 2011-06-23 01:32:56.000000000 +0200 @@ -35,7 +35,7 @@ void freerules(struct rule *); /* Execute a rule set on a string; returns a malloc'd new string. */ -char *rewrite_string(const char *, const struct rule *, int, +char *rewrite_string(const char *, const struct rule *, char, match_pattern_callback, const char **); #endif /* WITH_REGEX */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftpd/tftpd.8.in new/tftp-hpa-5.1/tftpd/tftpd.8.in --- old/tftp-hpa-5.0/tftpd/tftpd.8.in 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/tftpd/tftpd.8.in 2011-06-23 01:32:56.000000000 +0200 @@ -3,7 +3,7 @@ .\" Copyright (c) 1990, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" -.\" Copyright 2001-2008 H. Peter Anvin - All Rights Reserved +.\" Copyright 2001-2009 H. Peter Anvin - All Rights Reserved .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -30,10 +30,10 @@ .\" SUCH DAMAGE. .\" .\"----------------------------------------------------------------------- */ -.TH TFTPD 8 "30 July 2008" "tftp-hpa @@VERSION@@" "System Manager's Manual" +.TH TFTPD 8 "14 September 2009" "tftp-hpa @@VERSION@@" "System Manager's Manual" .SH NAME .B tftpd -\- IPv4 Trivial File Transfer Protocol server +\- Trivial File Transfer Protocol server .SH SYNOPSIS .B in.tftpd .RI [ options... ] @@ -133,6 +133,11 @@ .B \-\-user option. .TP +\fB\-\-pidfile\fP \fIpidfile\fP, \fB\-P\fP \fIpidfile\fP +When run in standalone mode, write the process ID of the listening +server into \fIpidfile\fP. On normal termination (SIGTERM or SIGINT) +the pid file is automatically removed. +.TP \fB\-\-timeout\fP \fItimeout\fP, \fB\-t\fP \fItimeout\fP When run from .B inetd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/tftpd/tftpd.c new/tftp-hpa-5.1/tftpd/tftpd.c --- old/tftp-hpa-5.0/tftpd/tftpd.c 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/tftpd/tftpd.c 2011-06-23 01:32:56.000000000 +0200 @@ -1,5 +1,7 @@ /* * Copyright (c) 1983 Regents of the University of California. + * Copyright (c) 1999-2009 H. Peter Anvin + * Copyright (c) 2011 Intel Corporation; author: H. Peter Anvin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -113,18 +115,18 @@ int tftp(struct tftphdr *, int); static void nak(int, const char *); static void timer(int); -static void do_opt(char *, char *, char **); +static void do_opt(const char *, const char *, char **); -static int set_blksize(char *, char **); -static int set_blksize2(char *, char **); -static int set_tsize(char *, char **); -static int set_timeout(char *, char **); -static int set_utimeout(char *, char **); -static int set_rollover(char *, char **); +static int set_blksize(uintmax_t *); +static int set_blksize2(uintmax_t *); +static int set_tsize(uintmax_t *); +static int set_timeout(uintmax_t *); +static int set_utimeout(uintmax_t *); +static int set_rollover(uintmax_t *); struct options { const char *o_opt; - int (*o_fnc) (char *, char **); + int (*o_fnc)(uintmax_t *); } options[] = { {"blksize", set_blksize}, {"blksize2", set_blksize2}, @@ -143,6 +145,13 @@ caught_sighup = 1; } +/* Handle exit requests by SIGTERM and SIGINT */ +static volatile sig_atomic_t exit_signal = 0; +static void handle_exit(int sig) +{ + exit_signal = sig; +} + /* Handle timeout signal or timeout event */ void timer(int sig) { @@ -171,6 +180,26 @@ } #endif +/* + * Rules for locking files; return 0 on success, -1 on failure + */ +static int lock_file(int fd, int lock_write) +{ +#if defined(HAVE_FCNTL) && defined(HAVE_F_SETLK_DEFINITION) + struct flock fl; + + fl.l_type = lock_write ? F_WRLCK : F_RDLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; /* Whole file */ + return fcntl(fd, F_SETLK, &fl); +#elif defined(HAVE_LOCK_SH_DEFINITION) + return flock(fd, lock_write ? LOCK_EX|LOCK_NB : LOCK_SH|LOCK_NB); +#else + return 0; /* Hope & pray... */ +#endif +} + static void set_socket_nonblock(int fd, int flag) { int err; @@ -317,9 +346,10 @@ { "retransmit", 1, NULL, 'T' }, { "port-range", 1, NULL, 'R' }, { "map-file", 1, NULL, 'm' }, + { "pidfile", 1, NULL, 'P' }, { NULL, 0, NULL, 0 } }; -static const char short_options[] = "46cspvVlLa:B:u:U:r:t:T:R:m:"; +static const char short_options[] = "46cspvVlLa:B:u:U:r:t:T:R:m:P:"; int main(int argc, char **argv) { @@ -351,6 +381,7 @@ #ifdef WITH_REGEX char *rewrite_file = NULL; #endif + const char *pidfile = NULL; u_short tp_opcode; /* basename() is way too much of a pain from a portability standpoint */ @@ -363,7 +394,7 @@ srand(time(NULL) ^ getpid()); while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) - != -1) + != -1) switch (c) { case '4': ai_fam = AF_INET; @@ -466,14 +497,17 @@ case 'v': verbosity++; break; - case OPT_VERBOSITY: - verbosity = atoi(optarg); - break; + case OPT_VERBOSITY: + verbosity = atoi(optarg); + break; case 'V': /* Print configuration to stdout and exit */ printf("%s\n", TFTPD_CONFIG_STR); exit(0); break; + case 'P': + pidfile = optarg; + break; default: syslog(LOG_ERR, "Unknown option: '%c'", optopt); break; @@ -506,16 +540,19 @@ exit(EX_NOUSER); } - if (spec_umask || !unixperms) - umask(my_umask); - #ifdef WITH_REGEX if (rewrite_file) rewrite_rules = read_remap_rules(rewrite_file); #endif + if (pidfile && !standalone) { + syslog(LOG_WARNING, "not in standalone mode, ignoring pid file"); + pidfile = NULL; + } + /* If we're running standalone, set up the input port */ if (standalone) { + FILE *pf; #ifdef HAVE_IPV6 if (ai_fam != AF_INET6) { #endif @@ -695,12 +732,26 @@ } #endif /* Daemonize this process */ - /* Note: when running in secure mode (-s), we must not chroot, since + /* Note: when running in secure mode (-s), we must not chdir, since we are already in the proper directory. */ if (!nodaemon && daemon(secure, 0) < 0) { syslog(LOG_ERR, "cannot daemonize: %m"); exit(EX_OSERR); } + set_signal(SIGTERM, handle_exit, 0); + set_signal(SIGINT, handle_exit, 0); + if (pidfile) { + pf = fopen (pidfile, "w"); + if (!pf) { + syslog(LOG_ERR, "cannot open pid file '%s' for writing: %m", pidfile); + pidfile = NULL; + } else { + if (fprintf(pf, "%d\n", getpid()) < 0) + syslog(LOG_ERR, "error writing pid file '%s': %m", pidfile); + if (fclose(pf)) + syslog(LOG_ERR, "error closing pid file '%s': %m", pidfile); + } + } if (fd6 > fd4) fdmax = fd6; else @@ -733,11 +784,23 @@ lose packets as a result. */ set_signal(SIGHUP, handle_sighup, 0); + if (spec_umask || !unixperms) + umask(my_umask); + while (1) { fd_set readset; struct timeval tv_waittime; int rv; + if (exit_signal) { /* happens in standalone mode only */ + if (pidfile && unlink(pidfile)) { + syslog(LOG_WARNING, "error removing pid file '%s': %m", pidfile); + exit(EX_OSERR); + } else { + exit(0); + } + } + if (caught_sighup) { caught_sighup = 0; if (standalone) { @@ -869,6 +932,15 @@ /* Ignore SIGHUP */ set_signal(SIGHUP, SIG_IGN, 0); + /* Make sure the log socket is still connected. This has to be + done before the chroot, while /dev/log is still accessible. + When not running standalone, there is little chance that the + syslog daemon gets restarted by the time we get here. */ + if (secure && standalone) { + closelog(); + openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); + } + #ifdef HAVE_TCPWRAPPERS /* Verify if this was a legal request for us. This has to be done before the chroot, while /etc is still accessible. */ @@ -972,18 +1044,19 @@ } static char *rewrite_access(char *, int, const char **); -static int validate_access(char *, int, struct formats *, const char **); -static void tftp_sendfile(struct formats *, struct tftphdr *, int); -static void tftp_recvfile(struct formats *, struct tftphdr *, int); +static int validate_access(char *, int, const struct formats *, const char **); +static void tftp_sendfile(const struct formats *, struct tftphdr *, int); +static void tftp_recvfile(const struct formats *, struct tftphdr *, int); struct formats { const char *f_mode; char *(*f_rewrite) (char *, int, const char **); - int (*f_validate) (char *, int, struct formats *, const char **); - void (*f_send) (struct formats *, struct tftphdr *, int); - void (*f_recv) (struct formats *, struct tftphdr *, int); + int (*f_validate) (char *, int, const struct formats *, const char **); + void (*f_send) (const struct formats *, struct tftphdr *, int); + void (*f_recv) (const struct formats *, struct tftphdr *, int); int f_convert; -} formats[] = { +}; +static const struct formats formats[] = { { "netascii", rewrite_access, validate_access, tftp_sendfile, tftp_recvfile, 1}, { @@ -999,7 +1072,7 @@ { char *cp, *end; int argn, ecode; - struct formats *pf = NULL; + const struct formats *pf = NULL; char *origfilename; char *filename, *mode = NULL; const char *errmsgptr; @@ -1103,48 +1176,38 @@ /* * Set a non-standard block size (c.f. RFC2348) */ -static int set_blksize(char *val, char **ret) +static int set_blksize(uintmax_t *vp) { - static char b_ret[6]; - unsigned int sz; - char *vend; - - sz = (unsigned int)strtoul(val, &vend, 10); + uintmax_t sz = *vp; - if (blksize_set || *vend) + if (blksize_set) return 0; if (sz < 8) - return (0); + return 0; else if (sz > max_blksize) sz = max_blksize; - segsize = sz; - sprintf(*ret = b_ret, "%u", sz); - + *vp = segsize = sz; blksize_set = 1; - - return (1); + return 1; } /* * Set a power-of-two block size (nonstandard) */ -static int set_blksize2(char *val, char **ret) +static int set_blksize2(uintmax_t *vp) { - static char b_ret[6]; - unsigned int sz; - char *vend; - - sz = (unsigned int)strtoul(val, &vend, 10); + uintmax_t sz = *vp; - if (blksize_set || *vend) + if (blksize_set) return 0; if (sz < 8) return (0); else if (sz > max_blksize) sz = max_blksize; + else /* Convert to a power of two */ if (sz & (sz - 1)) { @@ -1155,29 +1218,23 @@ sz = sz1; } - segsize = sz; - sprintf(*ret = b_ret, "%u", sz); - + *vp = segsize = sz; blksize_set = 1; - - return (1); + return 1; } /* * Set the block number rollover value */ -static int set_rollover(char *val, char **ret) +static int set_rollover(uintmax_t *vp) { - uintmax_t ro; - char *vend; + uintmax_t ro = *vp; + + if (ro > 65535) + return 0; - ro = strtoumax(val, &vend, 10); - if (ro > 65535 || *vend) - return 0; - - rollover_val = (uint16_t)ro; - *ret = val; - return 1; + rollover_val = (uint16_t)ro; + return 1; } /* @@ -1185,22 +1242,18 @@ * For netascii mode, we don't know the size ahead of time; * so reject the option. */ -static int set_tsize(char *val, char **ret) +static int set_tsize(uintmax_t *vp) { - static char b_ret[sizeof(uintmax_t) * CHAR_BIT / 3 + 2]; - uintmax_t sz; - char *vend; + uintmax_t sz = *vp; - sz = strtoumax(val, &vend, 10); - - if (!tsize_ok || *vend) + if (!tsize_ok) return 0; if (sz == 0) - sz = (uintmax_t) tsize; + sz = tsize; - sprintf(*ret = b_ret, "%" PRIuMAX, sz); - return (1); + *vp = sz; + return 1; } /* @@ -1208,74 +1261,86 @@ * to be the (default) retransmission timeout, but being an * integer in seconds it seems a bit limited. */ -static int set_timeout(char *val, char **ret) +static int set_timeout(uintmax_t *vp) { - static char b_ret[4]; - unsigned long to; - char *vend; + uintmax_t to = *vp; - to = strtoul(val, &vend, 10); - - if (to < 1 || to > 255 || *vend) + if (to < 1 || to > 255) return 0; rexmtval = timeout = to * 1000000UL; maxtimeout = rexmtval * TIMEOUT_LIMIT; - sprintf(*ret = b_ret, "%lu", to); - return (1); + return 1; } /* Similar, but in microseconds. We allow down to 10 ms. */ -static int set_utimeout(char *val, char **ret) +static int set_utimeout(uintmax_t *vp) { - static char b_ret[4]; - unsigned long to; - char *vend; + uintmax_t to = *vp; - to = strtoul(val, &vend, 10); - - if (to < 10000UL || to > 255000000UL || *vend) + if (to < 10000UL || to > 255000000UL) return 0; rexmtval = timeout = to; maxtimeout = rexmtval * TIMEOUT_LIMIT; - sprintf(*ret = b_ret, "%lu", to); - return (1); + return 1; } /* - * Parse RFC2347 style options + * Conservative calculation for the size of a buffer which can hold an + * arbitrary integer + */ +#define OPTBUFSIZE (sizeof(uintmax_t) * CHAR_BIT / 3 + 3) + +/* + * Parse RFC2347 style options; we limit the arguments to positive + * integers which matches all our current options. */ -static void do_opt(char *opt, char *val, char **ap) +static void do_opt(const char *opt, const char *val, char **ap) { struct options *po; - char *ret; + char retbuf[OPTBUFSIZE]; + char *p = *ap; + size_t optlen, retlen; + char *vend; + uintmax_t v; /* Global option-parsing variables initialization */ blksize_set = 0; - if (!*opt) + if (!*opt || !*val) return; + errno = 0; + v = strtoumax(val, &vend, 10); + if (*vend || errno == ERANGE) + return; + for (po = options; po->o_opt; po++) if (!strcasecmp(po->o_opt, opt)) { - if (po->o_fnc(val, &ret)) { - if (*ap + strlen(opt) + strlen(ret) + 2 >= - ackbuf + sizeof(ackbuf)) { + if (po->o_fnc(&v)) { + optlen = strlen(opt); + retlen = sprintf(retbuf, "%"PRIuMAX, v); + + if (p + optlen + retlen + 2 >= ackbuf + sizeof(ackbuf)) { nak(EOPTNEG, "Insufficient space for options"); exit(0); } - *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt), '\0') + 1, - ret), '\0') + 1; + + memcpy(p, opt, optlen+1); + p += optlen+1; + memcpy(p, retbuf, retlen+1); + p += retlen+1; } else { nak(EOPTNEG, "Unsupported option(s) requested"); exit(0); } break; } - return; + + *ap = p; } #ifdef WITH_REGEX @@ -1337,7 +1402,8 @@ { if (rewrite_rules) { char *newname = - rewrite_string(filename, rewrite_rules, mode != RRQ, + rewrite_string(filename, rewrite_rules, + mode != RRQ ? 'P' : 'G', rewrite_macros, msg); filename = newname; } @@ -1366,7 +1432,7 @@ * given as we have no login directory. */ static int validate_access(char *filename, int mode, - struct formats *pf, const char **errmsg) + const struct formats *pf, const char **errmsg) { struct stat stbuf; int i, len; @@ -1410,11 +1476,13 @@ * We use different a different permissions scheme if `cancreate' is * set. */ - wmode = O_WRONLY | - (cancreate ? O_CREAT : 0) | - (unixperms ? O_TRUNC : 0) | (pf->f_convert ? O_TEXT : O_BINARY); + wmode = O_WRONLY | (cancreate ? O_CREAT : 0) | (pf->f_convert ? O_TEXT : O_BINARY); rmode = O_RDONLY | (pf->f_convert ? O_TEXT : O_BINARY); +#ifndef HAVE_FTRUNCATE + wmode |= O_TRUNC; /* This really sucks on a dupe */ +#endif + fd = open(filename, mode == RRQ ? rmode : wmode, 0666); if (fd < 0) { switch (errno) { @@ -1433,6 +1501,10 @@ if (fstat(fd, &stbuf) < 0) exit(EX_OSERR); /* This shouldn't happen */ + /* A duplicate RRQ or (worse!) WRQ packet could really cause havoc... */ + if (lock_file(fd, mode != RRQ)) + exit(0); + if (mode == RRQ) { if (!unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0) { *errmsg = "File must have global read permissions"; @@ -1447,15 +1519,15 @@ *errmsg = "File must have global write permissions"; return (EACCESS); } + } - /* We didn't get to truncate the file at open() time */ #ifdef HAVE_FTRUNCATE - if (ftruncate(fd, (off_t) 0)) { - *errmsg = "Cannot reset file size"; - return (EACCESS); - } + /* We didn't get to truncate the file at open() time */ + if (ftruncate(fd, (off_t) 0)) { + *errmsg = "Cannot reset file size"; + return (EACCESS); + } #endif - } tsize = 0; tsize_ok = 1; } @@ -1474,7 +1546,7 @@ /* * Send the requested file. */ -static void tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen) +static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oacklen) { struct tftphdr *dp; struct tftphdr *ap; /* ack packet */ @@ -1572,7 +1644,7 @@ /* * Receive a file. */ -static void tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen) +static void tftp_recvfile(const struct formats *pf, struct tftphdr *oap, int oacklen) { struct tftphdr *dp; int n, size; @@ -1595,6 +1667,10 @@ ap->th_opcode = htons((u_short) ACK); ap->th_block = htons((u_short) block); acksize = 4; + /* If we're sending a regular ACK, that means we have successfully + * sent the OACK. Clear oap so that we won't try to send another + * OACK when the block number wraps back to 0. */ + oap = NULL; } if (!++block) block = rollover_val; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/tftp-hpa-5.0/version new/tftp-hpa-5.1/version --- old/tftp-hpa-5.0/version 2009-02-16 23:51:22.000000000 +0100 +++ new/tftp-hpa-5.1/version 2011-06-23 01:32:56.000000000 +0200 @@ -1 +1 @@ -5.0 +5.1 ++++++ tftp.xinetd ++++++ --- /var/tmp/diff_new_pack.LhGDcW/_old 2011-06-24 09:54:44.000000000 +0200 +++ /var/tmp/diff_new_pack.LhGDcW/_new 2011-06-24 09:54:44.000000000 +0200 @@ -11,9 +11,9 @@ protocol = udp wait = yes flags = IPv6 IPv4 - user = tftp + user = root server = /usr/sbin/in.tftpd - server_args = -s /srv/tftpboot + server_args = -u tftp -s /srv/tftpboot # per_source = 11 # cps = 100 2 disable = yes ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
