1/*	$NetBSD: tftpd.c,v 1.38 2010/04/29 20:13:46 hubertf Exp $	*/
2
3/*
4 * Copyright (c) 1983, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33#ifndef lint
34__COPYRIGHT("@(#) Copyright (c) 1983, 1993\
35 The Regents of the University of California.  All rights reserved.");
36#if 0
37static char sccsid[] = "@(#)tftpd.c	8.1 (Berkeley) 6/4/93";
38#else
39__RCSID("$NetBSD: tftpd.c,v 1.38 2010/04/29 20:13:46 hubertf Exp $");
40#endif
41#endif /* not lint */
42
43/*
44 * Trivial file transfer protocol server.
45 *
46 * This version includes many modifications by Jim Guyton
47 * <guyton@rand-unix>.
48 */
49
50#include <sys/param.h>
51#include <sys/ioctl.h>
52#include <sys/stat.h>
53#include <sys/socket.h>
54
55#include <netinet/in.h>
56#include <arpa/tftp.h>
57#include <arpa/inet.h>
58
59#include <ctype.h>
60#include <errno.h>
61#include <fcntl.h>
62#include <grp.h>
63#include <netdb.h>
64#include <pwd.h>
65#include <setjmp.h>
66#include <signal.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <syslog.h>
71#include <time.h>
72#include <unistd.h>
73
74#include "tftpsubs.h"
75
76#define	DEFAULTUSER	"nobody"
77
78#define	TIMEOUT		5
79
80static int	peer;
81static int	rexmtval = TIMEOUT;
82static int	maxtimeout = 5*TIMEOUT;
83
84static char	buf[MAXPKTSIZE];
85static char	ackbuf[PKTSIZE];
86static char	oackbuf[PKTSIZE];
87static struct	sockaddr_storage from;
88static socklen_t	fromlen;
89static int	debug;
90
91static int	tftp_opt_tsize = 0;
92static int	tftp_blksize = SEGSIZE;
93static int	tftp_tsize = 0;
94
95/*
96 * Null-terminated directory prefix list for absolute pathname requests and
97 * search list for relative pathname requests.
98 *
99 * MAXDIRS should be at least as large as the number of arguments that
100 * inetd allows (currently 20).
101 */
102#define MAXDIRS	20
103static struct dirlist {
104	char	*name;
105	int	len;
106} dirs[MAXDIRS+1];
107static int	suppress_naks;
108static int	logging;
109static int	secure;
110static char	pathsep = '\0';
111static char	*securedir;
112static int	unrestricted_writes;    /* uploaded files don't have to exist */
113
114struct formats;
115
116static const char *errtomsg(int);
117static void	nak(int);
118__dead static void	tftp(struct tftphdr *, int);
119__dead static void	usage(void);
120static char	*verifyhost(struct sockaddr *);
121__dead static void	justquit(int);
122static void	recvfile(struct formats *, int, int);
123static void	sendfile(struct formats *, int, int);
124__dead static void	timer(int);
125static const char *opcode(int);
126static int	validate_access(char **, int);
127
128static struct formats {
129	const char	*f_mode;
130	int		(*f_validate)(char **, int);
131	void		(*f_send)(struct formats *, int, int);
132	void		(*f_recv)(struct formats *, int, int);
133	int		f_convert;
134} formats[] = {
135	{ "netascii",	validate_access,	sendfile,	recvfile, 1 },
136	{ "octet",	validate_access,	sendfile,	recvfile, 0 },
137	{ .f_mode = NULL }
138};
139
140static void
141usage(void)
142{
143
144	syslog(LOG_ERR,
145    "Usage: %s [-dln] [-g group] [-p pathsep] [-s directory] [-u user] [directory ...]",
146		    getprogname());
147	exit(1);
148}
149
150int
151main(int argc, char *argv[])
152{
153	struct sockaddr_storage me;
154	struct passwd	*pwent;
155	struct group	*grent;
156	struct tftphdr	*tp;
157	const char	*tgtuser, *tgtgroup;
158	char *ep;
159	int	n, ch, on, fd;
160	int	soopt;
161	socklen_t len;
162	uid_t	curuid, tgtuid;
163	gid_t	curgid, tgtgid;
164	long	nid;
165
166	n = 0;
167	fd = 0;
168	tzset();
169	openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
170	tgtuser = DEFAULTUSER;
171	tgtgroup = NULL;
172	curuid = getuid();
173	curgid = getgid();
174
175	while ((ch = getopt(argc, argv, "cdg:lnp:s:u:")) != -1)
176		switch (ch) {
177		case 'w':
178			unrestricted_writes = 1;
179			break;
180
181		case 'd':
182			debug++;
183			break;
184
185		case 'g':
186			tgtgroup = optarg;
187			break;
188
189		case 'l':
190			logging = 1;
191			break;
192
193		case 'n':
194			suppress_naks = 1;
195			break;
196
197		case 'p':
198			if (optarg[0] == '\0' || optarg[1] != '\0')
199				usage();
200			pathsep = optarg[0];
201			break;
202
203		case 's':
204			secure = 1;
205			securedir = optarg;
206			break;
207
208		case 'u':
209			tgtuser = optarg;
210			break;
211
212		default:
213			usage();
214			break;
215		}
216
217	if (optind < argc) {
218		struct dirlist *dirp;
219
220		/* Get list of directory prefixes. Skip relative pathnames. */
221		for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];
222		     optind++) {
223			if (argv[optind][0] == '/') {
224				dirp->name = argv[optind];
225				dirp->len  = strlen(dirp->name);
226				dirp++;
227			}
228		}
229	}
230
231	if (*tgtuser == '\0' || (tgtgroup != NULL && *tgtgroup == '\0'))
232		usage();
233
234	nid = (strtol(tgtuser, &ep, 10));
235	if (*ep == '\0') {
236		if ((uid_t)nid > UID_MAX) {
237			syslog(LOG_ERR, "uid %ld is too large", nid);
238			exit(1);
239		}
240		pwent = getpwuid((uid_t)nid);
241	} else
242		pwent = getpwnam(tgtuser);
243	if (pwent == NULL) {
244		syslog(LOG_ERR, "unknown user `%s'", tgtuser);
245		exit(1);
246	}
247	tgtuid = pwent->pw_uid;
248	tgtgid = pwent->pw_gid;
249
250	if (tgtgroup != NULL) {
251		nid = (strtol(tgtgroup, &ep, 10));
252		if (*ep == '\0') {
253			if ((uid_t)nid > GID_MAX) {
254				syslog(LOG_ERR, "gid %ld is too large", nid);
255				exit(1);
256			}
257			grent = getgrgid((gid_t)nid);
258		} else
259			grent = getgrnam(tgtgroup);
260		if (grent != NULL)
261			tgtgid = grent->gr_gid;
262		else {
263			syslog(LOG_ERR, "unknown group `%s'", tgtgroup);
264			exit(1);
265		}
266	}
267
268	if (secure) {
269		if (chdir(securedir) < 0) {
270			syslog(LOG_ERR, "chdir %s: %m", securedir);
271			exit(1);
272		}
273		if (chroot(".")) {
274			syslog(LOG_ERR, "chroot: %m");
275			exit(1);
276		}
277	}
278
279	if (logging)
280		syslog(LOG_DEBUG, "running as user `%s' (%d), group `%s' (%d)",
281		    tgtuser, tgtuid, tgtgroup ? tgtgroup : "(unspecified)",
282		    tgtgid);
283	if (curgid != tgtgid) {
284		if (setgid(tgtgid)) {
285			syslog(LOG_ERR, "setgid to %d: %m", (int)tgtgid);
286			exit(1);
287		}
288		if (setgroups(0, NULL)) {
289			syslog(LOG_ERR, "setgroups: %m");
290			exit(1);
291		}
292	}
293
294	if (curuid != tgtuid) {
295		if (setuid(tgtuid)) {
296			syslog(LOG_ERR, "setuid to %d: %m", (int)tgtuid);
297			exit(1);
298		}
299	}
300
301	on = 1;
302	if (ioctl(fd, FIONBIO, &on) < 0) {
303		syslog(LOG_ERR, "ioctl(FIONBIO): %m");
304		exit(1);
305	}
306	fromlen = sizeof (from);
307	n = recvfrom(fd, buf, sizeof (buf), 0,
308	    (struct sockaddr *)&from, &fromlen);
309	if (n < 0) {
310		syslog(LOG_ERR, "recvfrom: %m");
311		exit(1);
312	}
313	/*
314	 * Now that we have read the message out of the UDP
315	 * socket, we fork and exit.  Thus, inetd will go back
316	 * to listening to the tftp port, and the next request
317	 * to come in will start up a new instance of tftpd.
318	 *
319	 * We do this so that inetd can run tftpd in "wait" mode.
320	 * The problem with tftpd running in "nowait" mode is that
321	 * inetd may get one or more successful "selects" on the
322	 * tftp port before we do our receive, so more than one
323	 * instance of tftpd may be started up.  Worse, if tftpd
324	 * break before doing the above "recvfrom", inetd would
325	 * spawn endless instances, clogging the system.
326	 */
327	{
328		int pid;
329		int i;
330		socklen_t j;
331
332		for (i = 1; i < 20; i++) {
333		    pid = fork();
334		    if (pid < 0) {
335				sleep(i);
336				/*
337				 * flush out to most recently sent request.
338				 *
339				 * This may drop some request, but those
340				 * will be resent by the clients when
341				 * they timeout.  The positive effect of
342				 * this flush is to (try to) prevent more
343				 * than one tftpd being started up to service
344				 * a single request from a single client.
345				 */
346				j = sizeof from;
347				i = recvfrom(fd, buf, sizeof (buf), 0,
348				    (struct sockaddr *)&from, &j);
349				if (i > 0) {
350					n = i;
351					fromlen = j;
352				}
353		    } else {
354				break;
355		    }
356		}
357		if (pid < 0) {
358			syslog(LOG_ERR, "fork: %m");
359			exit(1);
360		} else if (pid != 0) {
361			exit(0);
362		}
363	}
364
365	/*
366	 * remember what address this was sent to, so we can respond on the
367	 * same interface
368	 */
369	len = sizeof(me);
370	if (getsockname(fd, (struct sockaddr *)&me, &len) == 0) {
371		switch (me.ss_family) {
372		case AF_INET:
373			((struct sockaddr_in *)&me)->sin_port = 0;
374			break;
375		case AF_INET6:
376			((struct sockaddr_in6 *)&me)->sin6_port = 0;
377			break;
378		default:
379			/* unsupported */
380			break;
381		}
382	} else {
383		memset(&me, 0, sizeof(me));
384		me.ss_family = from.ss_family;
385		me.ss_len = from.ss_len;
386	}
387
388	alarm(0);
389	close(fd);
390	close(1);
391	peer = socket(from.ss_family, SOCK_DGRAM, 0);
392	if (peer < 0) {
393		syslog(LOG_ERR, "socket: %m");
394		exit(1);
395	}
396	if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) {
397		syslog(LOG_ERR, "bind: %m");
398		exit(1);
399	}
400	if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) {
401		syslog(LOG_ERR, "connect: %m");
402		exit(1);
403	}
404	soopt = 65536;	/* larger than we'll ever need */
405	if (setsockopt(peer, SOL_SOCKET, SO_SNDBUF, (void *) &soopt, sizeof(soopt)) < 0) {
406		syslog(LOG_ERR, "set SNDBUF: %m");
407		exit(1);
408	}
409	if (setsockopt(peer, SOL_SOCKET, SO_RCVBUF, (void *) &soopt, sizeof(soopt)) < 0) {
410		syslog(LOG_ERR, "set RCVBUF: %m");
411		exit(1);
412	}
413
414	tp = (struct tftphdr *)buf;
415	tp->th_opcode = ntohs(tp->th_opcode);
416	if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
417		tftp(tp, n);
418	exit(1);
419}
420
421static int
422blk_handler(struct tftphdr *tp, char *opt, char *val, char *ack,
423	    int *ackl, int *ec)
424{
425	unsigned long bsize;
426	char *endp;
427	int l;
428
429	/*
430	 * On these failures, we could just ignore the blocksize option.
431	 * Perhaps that should be a command-line option.
432	 */
433	errno = 0;
434	bsize = strtoul(val, &endp, 10);
435	if ((bsize == ULONG_MAX && errno == ERANGE) || *endp) {
436		syslog(LOG_NOTICE, "%s: %s request for %s: "
437			"illegal value %s for blksize option",
438			verifyhost((struct sockaddr *)&from),
439			tp->th_opcode == WRQ ? "write" : "read",
440			tp->th_stuff, val);
441		return 0;
442	}
443	if (bsize < 8 || bsize > 65464) {
444		syslog(LOG_NOTICE, "%s: %s request for %s: "
445			"out of range value %s for blksize option",
446			verifyhost((struct sockaddr *)&from),
447			tp->th_opcode == WRQ ? "write" : "read",
448			tp->th_stuff, val);
449		return 0;
450	}
451
452	tftp_blksize = bsize;
453	strcpy(ack + *ackl, "blksize");
454	*ackl += 8;
455	l = sprintf(ack + *ackl, "%lu", bsize);
456	*ackl += l + 1;
457
458	return 0;
459}
460
461static int
462timeout_handler(struct tftphdr *tp, char *opt, char *val, char *ack,
463		int *ackl, int *ec)
464{
465	unsigned long tout;
466	char *endp;
467	int l;
468
469	errno = 0;
470	tout = strtoul(val, &endp, 10);
471	if ((tout == ULONG_MAX && errno == ERANGE) || *endp) {
472		syslog(LOG_NOTICE, "%s: %s request for %s: "
473			"illegal value %s for timeout option",
474			verifyhost((struct sockaddr *)&from),
475			tp->th_opcode == WRQ ? "write" : "read",
476			tp->th_stuff, val);
477		return 0;
478	}
479	if (tout < 1 || tout > 255) {
480		syslog(LOG_NOTICE, "%s: %s request for %s: "
481			"out of range value %s for timeout option",
482			verifyhost((struct sockaddr *)&from),
483			tp->th_opcode == WRQ ? "write" : "read",
484			tp->th_stuff, val);
485		return 0;
486	}
487
488	rexmtval = tout;
489	strcpy(ack + *ackl, "timeout");
490	*ackl += 8;
491	l = sprintf(ack + *ackl, "%lu", tout);
492	*ackl += l + 1;
493
494	/*
495	 * Arbitrarily pick a maximum timeout on a request to 3
496	 * retransmissions if the interval timeout is more than
497	 * one minute.  Longest possible timeout is therefore
498	 * 3 * 255 - 1, or 764 seconds.
499	 */
500	if (rexmtval > 60) {
501		maxtimeout = rexmtval * 3;
502	} else {
503		maxtimeout = rexmtval * 5;
504	}
505
506	return 0;
507}
508
509static int
510tsize_handler(struct tftphdr *tp, char *opt, char *val, char *ack,
511	      int *ackl, int *ec)
512{
513	unsigned long fsize;
514	char *endp;
515
516	/*
517	 * Maximum file even with extended tftp is 65535 blocks of
518	 * length 65464, or 4290183240 octets (4784056 less than 2^32).
519	 * unsigned long is at least 32 bits on all NetBSD archs.
520	 */
521
522	errno = 0;
523	fsize = strtoul(val, &endp, 10);
524	if ((fsize == ULONG_MAX && errno == ERANGE) || *endp) {
525		syslog(LOG_NOTICE, "%s: %s request for %s: "
526			"illegal value %s for tsize option",
527			verifyhost((struct sockaddr *)&from),
528			tp->th_opcode == WRQ ? "write" : "read",
529			tp->th_stuff, val);
530		return 0;
531	}
532	if (fsize > (unsigned long) 65535 * 65464) {
533		syslog(LOG_NOTICE, "%s: %s request for %s: "
534			"out of range value %s for tsize option",
535			verifyhost((struct sockaddr *)&from),
536			tp->th_opcode == WRQ ? "write" : "read",
537			tp->th_stuff, val);
538		return 0;
539	}
540
541	tftp_opt_tsize = 1;
542	tftp_tsize = fsize;
543	/*
544	 * We will report this later -- either replying with the fsize (WRQ)
545	 * or replying with the actual filesize (RRQ).
546	 */
547
548	return 0;
549}
550
551static const struct tftp_options {
552	const char *o_name;
553	int (*o_handler)(struct tftphdr *, char *, char *, char *,
554			 int *, int *);
555} options[] = {
556	{ "blksize", blk_handler },
557	{ "timeout", timeout_handler },
558	{ "tsize", tsize_handler },
559	{ .o_name = NULL }
560};
561
562/*
563 * Get options for an extended tftp session.  Stuff the ones we
564 * recognize in oackbuf.
565 */
566static int
567get_options(struct tftphdr *tp, char *cp, int size, char *ackb,
568    int *alen, int *err)
569{
570	const struct tftp_options *op;
571	char *option, *value, *endp;
572	int r, rv=0, ec=0;
573
574	endp = cp + size;
575	while (cp < endp) {
576		option = cp;
577		while (*cp && cp < endp) {
578			*cp = tolower((unsigned char)*cp);
579			cp++;
580		}
581		if (*cp) {
582			/* if we have garbage at the end, just ignore it */
583			break;
584		}
585		cp++;	/* skip over NUL */
586		value = cp;
587		while (*cp && cp < endp) {
588			cp++;
589		}
590		if (*cp) {
591			/* if we have garbage at the end, just ignore it */
592			break;
593		}
594		cp++;
595		for (op = options; op->o_name; op++) {
596			if (strcmp(op->o_name, option) == 0)
597				break;
598		}
599		if (op->o_name) {
600			r = op->o_handler(tp, option, value, ackb, alen, &ec);
601			if (r < 0) {
602				rv = -1;
603				break;
604			}
605			rv++;
606		} /* else ignore unknown options */
607	}
608
609	if (rv < 0)
610		*err = ec;
611
612	return rv;
613}
614
615/*
616 * Handle initial connection protocol.
617 */
618static void
619tftp(struct tftphdr *tp, int size)
620{
621	struct formats *pf;
622	char	*cp;
623	char	*filename, *mode;
624	int	 first, ecode, alen, etftp = 0, r;
625
626	ecode = 0;	/* XXX gcc */
627	first = 1;
628	mode = NULL;
629
630	filename = cp = tp->th_stuff;
631again:
632	while (cp < buf + size) {
633		if (*cp == '\0')
634			break;
635		cp++;
636	}
637	if (*cp != '\0') {
638		nak(EBADOP);
639		exit(1);
640	}
641	if (first) {
642		mode = ++cp;
643		first = 0;
644		goto again;
645	}
646	for (cp = mode; *cp; cp++)
647		*cp = tolower((unsigned char)*cp);
648	for (pf = formats; pf->f_mode; pf++)
649		if (strcmp(pf->f_mode, mode) == 0)
650			break;
651	if (pf->f_mode == 0) {
652		nak(EBADOP);
653		exit(1);
654	}
655	/*
656	 * cp currently points to the NUL byte following the mode.
657	 *
658	 * If we have some valid options, then let's assume that we're
659	 * now dealing with an extended tftp session.  Note that if we
660	 * don't get any options, then we *must* assume that we do not
661	 * have an extended tftp session.  If we get options, we fill
662	 * in the ack buf to acknowledge them.  If we skip that, then
663	 * the client *must* assume that we are not using an extended
664	 * session.
665	 */
666	size -= (++cp - (char *) tp);
667	if (size > 0 && *cp) {
668		alen = 2; /* Skip over opcode */
669		r = get_options(tp, cp, size, oackbuf, &alen, &ecode);
670		if (r > 0) {
671			etftp = 1;
672		} else if (r < 0) {
673			nak(ecode);
674			exit(1);
675		}
676	}
677	/*
678	 * Globally replace the path separator given in the -p option
679	 * with / to cope with clients expecting a non-unix path separator.
680	 */
681	if (pathsep != '\0') {
682		for (cp = filename; *cp != '\0'; ++cp) {
683			if (*cp == pathsep)
684				*cp = '/';
685		}
686	}
687	ecode = (*pf->f_validate)(&filename, tp->th_opcode);
688	if (logging) {
689		syslog(LOG_INFO, "%s: %s request for %s: %s",
690			verifyhost((struct sockaddr *)&from),
691			tp->th_opcode == WRQ ? "write" : "read",
692			filename, errtomsg(ecode));
693	}
694	if (ecode) {
695		/*
696		 * Avoid storms of naks to a RRQ broadcast for a relative
697		 * bootfile pathname from a diskless Sun.
698		 */
699		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
700			exit(0);
701		nak(ecode);
702		exit(1);
703	}
704
705	if (etftp) {
706		struct tftphdr *oack_h;
707
708		if (tftp_opt_tsize) {
709			int l;
710
711			strcpy(oackbuf + alen, "tsize");
712			alen += 6;
713			l = sprintf(oackbuf + alen, "%u", tftp_tsize);
714			alen += l + 1;
715		}
716		oack_h = (struct tftphdr *) oackbuf;
717		oack_h->th_opcode = htons(OACK);
718	}
719
720	if (tp->th_opcode == WRQ)
721		(*pf->f_recv)(pf, etftp, alen);
722	else
723		(*pf->f_send)(pf, etftp, alen);
724	exit(0);
725}
726
727
728FILE *file;
729
730/*
731 * Validate file access.  Since we
732 * have no uid or gid, for now require
733 * file to exist and be publicly
734 * readable/writable.
735 * If we were invoked with arguments
736 * from inetd then the file must also be
737 * in one of the given directory prefixes.
738 */
739int
740validate_access(char **filep, int mode)
741{
742	struct stat	 stbuf;
743	struct dirlist	*dirp;
744	static char	 pathname[MAXPATHLEN];
745	char		*filename;
746	int		 fd;
747	int		 create = 0;
748	int		 trunc = 0;
749
750	filename = *filep;
751
752	/*
753	 * Prevent tricksters from getting around the directory restrictions
754	 */
755	if (strstr(filename, "/../"))
756		return (EACCESS);
757
758	if (*filename == '/') {
759		/*
760		 * Allow the request if it's in one of the approved locations.
761		 * Special case: check the null prefix ("/") by looking
762		 * for length = 1 and relying on the arg. processing that
763		 * it's a /.
764		 */
765		for (dirp = dirs; dirp->name != NULL; dirp++) {
766			if (dirp->len == 1 ||
767			    (!strncmp(filename, dirp->name, dirp->len) &&
768			     filename[dirp->len] == '/'))
769				    break;
770		}
771		/* If directory list is empty, allow access to any file */
772		if (dirp->name == NULL && dirp != dirs)
773			return (EACCESS);
774		if (stat(filename, &stbuf) < 0)
775			return (errno == ENOENT ? ENOTFOUND : EACCESS);
776		if (!S_ISREG(stbuf.st_mode))
777			return (ENOTFOUND);
778		if (mode == RRQ) {
779			if ((stbuf.st_mode & S_IROTH) == 0)
780				return (EACCESS);
781		} else {
782			if ((stbuf.st_mode & S_IWOTH) == 0)
783				return (EACCESS);
784		}
785	} else {
786		/*
787		 * Relative file name: search the approved locations for it.
788		 */
789
790		if (!strncmp(filename, "../", 3))
791			return (EACCESS);
792
793		/*
794		 * Find the first file that exists in any of the directories,
795		 * check access on it.
796		 */
797		if (dirs[0].name != NULL) {
798			for (dirp = dirs; dirp->name != NULL; dirp++) {
799				snprintf(pathname, sizeof pathname, "%s/%s",
800				    dirp->name, filename);
801				if (stat(pathname, &stbuf) == 0 &&
802				    (stbuf.st_mode & S_IFMT) == S_IFREG) {
803					break;
804				}
805			}
806			if (dirp->name == NULL)
807				return (ENOTFOUND);
808			if (mode == RRQ && !(stbuf.st_mode & S_IROTH))
809				return (EACCESS);
810			if (mode == WRQ && !(stbuf.st_mode & S_IWOTH))
811				return (EACCESS);
812			*filep = filename = pathname;
813		} else {
814			int stat_rc;
815
816			/*
817			 * If there's no directory list, take our cue from the
818			 * absolute file request check above (*filename == '/'),
819			 * and allow access to anything.
820			 */
821			stat_rc = stat(filename, &stbuf);
822			if (mode == RRQ) {
823				/* Read request */
824				if (stat_rc < 0)
825				       return (errno == ENOENT ? ENOTFOUND : EACCESS);
826				if (!S_ISREG(stbuf.st_mode))
827				       return (ENOTFOUND);
828				if ((stbuf.st_mode & S_IROTH) == 0)
829					return (EACCESS);
830			} else {
831				if (stat_rc < 0) {
832				       /* Can't stat */
833				       if (errno == EACCES) {
834					       /* Permission denied */
835					       return EACCESS;
836				       } else {
837					       /* Not there */
838					       if (unrestricted_writes) {
839						       /* need to creat new file! */
840						       create = O_CREAT;
841					       } else {
842						       /* Permission denied */
843						       return EACCESS;
844					       }
845				       }
846				} else {
847				       /* Can stat */
848				       if ((stbuf.st_mode & S_IWOTH) == 0) {
849					       return (EACCESS);
850				       }
851				       trunc = O_TRUNC;
852				}
853			}
854			*filep = filename;
855		}
856	}
857
858	if (tftp_opt_tsize && mode == RRQ)
859		tftp_tsize = (unsigned long) stbuf.st_size;
860
861	fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY | trunc | create,
862			0644); /* debatable */
863	if (fd < 0)
864		return (errno + 100);
865	file = fdopen(fd, (mode == RRQ)? "r":"w");
866	if (file == NULL) {
867		close(fd);
868		return (errno + 100);
869	}
870	return (0);
871}
872
873static int	timeout;
874static jmp_buf	timeoutbuf;
875
876static void
877timer(int dummy)
878{
879
880	timeout += rexmtval;
881	if (timeout >= maxtimeout)
882		exit(1);
883	longjmp(timeoutbuf, 1);
884}
885
886static const char *
887opcode(int code)
888{
889	static char obuf[64];
890
891	switch (code) {
892	case RRQ:
893		return "RRQ";
894	case WRQ:
895		return "WRQ";
896	case DATA:
897		return "DATA";
898	case ACK:
899		return "ACK";
900	case ERROR:
901		return "ERROR";
902	case OACK:
903		return "OACK";
904	default:
905		(void)snprintf(obuf, sizeof(obuf), "*code 0x%x*", code);
906		return obuf;
907	}
908}
909
910/*
911 * Send the requested file.
912 */
913static void
914sendfile(struct formats *pf, volatile int etftp, int acklength)
915{
916	volatile unsigned int block;
917	struct tftphdr	*dp;
918	struct tftphdr	*ap;    /* ack packet */
919	volatile int	 size;
920	int n;
921
922	signal(SIGALRM, timer);
923	ap = (struct tftphdr *)ackbuf;
924	if (etftp) {
925		dp = (struct tftphdr *)oackbuf;
926		size = acklength - 4;
927		block = 0;
928	} else {
929		dp = r_init();
930		size = 0;
931		block = 1;
932	}
933
934	do {
935		if (block > 0) {
936			size = readit(file, &dp, tftp_blksize, pf->f_convert);
937			if (size < 0) {
938				nak(errno + 100);
939				goto abort;
940			}
941			dp->th_opcode = htons((u_short)DATA);
942			dp->th_block = htons((u_short)block);
943		}
944		timeout = 0;
945		(void)setjmp(timeoutbuf);
946
947send_data:
948		if (!etftp && debug)
949			syslog(LOG_DEBUG, "Send DATA %u", block);
950		if ((n = send(peer, dp, size + 4, 0)) != size + 4) {
951			syslog(LOG_ERR, "tftpd: write: %m");
952			goto abort;
953		}
954		if (block)
955			read_ahead(file, tftp_blksize, pf->f_convert);
956		for ( ; ; ) {
957			alarm(rexmtval);        /* read the ack */
958			n = recv(peer, ackbuf, tftp_blksize, 0);
959			alarm(0);
960			if (n < 0) {
961				syslog(LOG_ERR, "tftpd: read: %m");
962				goto abort;
963			}
964			ap->th_opcode = ntohs((u_short)ap->th_opcode);
965			ap->th_block = ntohs((u_short)ap->th_block);
966			switch (ap->th_opcode) {
967			case ERROR:
968				goto abort;
969
970			case ACK:
971				if (etftp && ap->th_block == 0) {
972					etftp = 0;
973					acklength = 0;
974					dp = r_init();
975					goto done;
976				}
977				if (ap->th_block == (u_short)block)
978					goto done;
979				if (debug)
980					syslog(LOG_DEBUG, "Resync ACK %u != %u",
981					    (unsigned int)ap->th_block, block);
982				/* Re-synchronize with the other side */
983				(void) synchnet(peer, tftp_blksize);
984				if (ap->th_block == (u_short)(block - 1))
985					goto send_data;
986			default:
987				syslog(LOG_INFO, "Received %s in sendfile\n",
988				    opcode(dp->th_opcode));
989			}
990
991		}
992done:
993		if (debug)
994			syslog(LOG_DEBUG, "Received ACK for block %u", block);
995		if (block == UINT16_MAX && size == tftp_blksize)
996			syslog(LOG_WARNING,
997			    "Block number wrapped (hint: increase block size)");
998		block++;
999	} while (size == tftp_blksize || block == 1);
1000abort:
1001	(void) fclose(file);
1002}
1003
1004static void
1005justquit(int dummy)
1006{
1007
1008	exit(0);
1009}
1010
1011/*
1012 * Receive a file.
1013 */
1014static void
1015recvfile(struct formats *pf, volatile int etftp, volatile int acklength)
1016{
1017	volatile unsigned int block;
1018	struct tftphdr	*dp;
1019	struct tftphdr	*ap;    /* ack buffer */
1020	volatile int size;
1021	int n;
1022
1023	signal(SIGALRM, timer);
1024	dp = w_init();
1025	ap = (struct tftphdr *)oackbuf;
1026	block = 0;
1027	do {
1028		timeout = 0;
1029		if (etftp == 0) {
1030			ap = (struct tftphdr *)ackbuf;
1031			ap->th_opcode = htons((u_short)ACK);
1032			ap->th_block = htons((u_short)block);
1033			acklength = 4;
1034		}
1035		if (debug)
1036			syslog(LOG_DEBUG, "Sending ACK for block %u\n", block);
1037		if (block == UINT16_MAX)
1038			syslog(LOG_WARNING,
1039			    "Block number wrapped (hint: increase block size)");
1040		block++;
1041		(void) setjmp(timeoutbuf);
1042send_ack:
1043		ap = (struct tftphdr *) (etftp ? oackbuf : ackbuf);
1044		if (send(peer, ap, acklength, 0) != acklength) {
1045			syslog(LOG_ERR, "tftpd: write: %m");
1046			goto abort;
1047		}
1048		write_behind(file, pf->f_convert);
1049		for ( ; ; ) {
1050			alarm(rexmtval);
1051			n = recv(peer, dp, tftp_blksize + 4, 0);
1052			alarm(0);
1053			if (n < 0) {            /* really? */
1054				syslog(LOG_ERR, "tftpd: read: %m");
1055				goto abort;
1056			}
1057			etftp = 0;
1058			dp->th_opcode = ntohs((u_short)dp->th_opcode);
1059			dp->th_block = ntohs((u_short)dp->th_block);
1060			if (debug)
1061				syslog(LOG_DEBUG, "Received %s for block %u",
1062				    opcode(dp->th_opcode),
1063				    (unsigned int)dp->th_block);
1064
1065			switch (dp->th_opcode) {
1066			case ERROR:
1067				goto abort;
1068			case DATA:
1069				if (dp->th_block == block)
1070					goto done;   /* normal */
1071				if (debug)
1072					syslog(LOG_DEBUG, "Resync %u != %u",
1073					    (unsigned int)dp->th_block, block);
1074				/* Re-synchronize with the other side */
1075				(void) synchnet(peer, tftp_blksize);
1076				if (dp->th_block == (block-1))
1077					goto send_ack;          /* rexmit */
1078				break;
1079			default:
1080				syslog(LOG_INFO, "Received %s in recvfile\n",
1081				    opcode(dp->th_opcode));
1082				break;
1083			}
1084		}
1085done:
1086		if (debug)
1087			syslog(LOG_DEBUG, "Got block %u", block);
1088		/*  size = write(file, dp->th_data, n - 4); */
1089		size = writeit(file, &dp, n - 4, pf->f_convert);
1090		if (size != (n-4)) {                    /* ahem */
1091			if (size < 0) nak(errno + 100);
1092			else nak(ENOSPACE);
1093			goto abort;
1094		}
1095	} while (size == tftp_blksize);
1096	write_behind(file, pf->f_convert);
1097	(void) fclose(file);            /* close data file */
1098
1099	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */
1100	ap->th_block = htons((u_short)(block));
1101	if (debug)
1102		syslog(LOG_DEBUG, "Send final ACK %u", block);
1103	(void) send(peer, ackbuf, 4, 0);
1104
1105	signal(SIGALRM, justquit);      /* just quit on timeout */
1106	alarm(rexmtval);
1107	n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
1108	alarm(0);
1109	if (n >= 4 &&                   /* if read some data */
1110	    dp->th_opcode == DATA &&    /* and got a data block */
1111	    block == dp->th_block) {	/* then my last ack was lost */
1112		(void) send(peer, ackbuf, 4, 0);     /* resend final ack */
1113	}
1114abort:
1115	return;
1116}
1117
1118const struct errmsg {
1119	int		 e_code;
1120	const char	*e_msg;
1121} errmsgs[] = {
1122	{ EUNDEF,	"Undefined error code" },
1123	{ ENOTFOUND,	"File not found" },
1124	{ EACCESS,	"Access violation" },
1125	{ ENOSPACE,	"Disk full or allocation exceeded" },
1126	{ EBADOP,	"Illegal TFTP operation" },
1127	{ EBADID,	"Unknown transfer ID" },
1128	{ EEXISTS,	"File already exists" },
1129	{ ENOUSER,	"No such user" },
1130	{ EOPTNEG,	"Option negotiation failed" },
1131	{ -1,		0 }
1132};
1133
1134static const char *
1135errtomsg(int error)
1136{
1137	static char ebuf[20];
1138	const struct errmsg *pe;
1139
1140	if (error == 0)
1141		return ("success");
1142	for (pe = errmsgs; pe->e_code >= 0; pe++)
1143		if (pe->e_code == error)
1144			return (pe->e_msg);
1145	snprintf(ebuf, sizeof(ebuf), "error %d", error);
1146	return (ebuf);
1147}
1148
1149/*
1150 * Send a nak packet (error message).
1151 * Error code passed in is one of the
1152 * standard TFTP codes, or a UNIX errno
1153 * offset by 100.
1154 */
1155static void
1156nak(int error)
1157{
1158	const struct errmsg *pe;
1159	struct tftphdr *tp;
1160	int	length;
1161	size_t	msglen;
1162
1163	tp = (struct tftphdr *)buf;
1164	tp->th_opcode = htons((u_short)ERROR);
1165	msglen = sizeof(buf) - (&tp->th_msg[0] - buf);
1166	for (pe = errmsgs; pe->e_code >= 0; pe++)
1167		if (pe->e_code == error)
1168			break;
1169	if (pe->e_code < 0) {
1170		tp->th_code = EUNDEF;   /* set 'undef' errorcode */
1171		strlcpy(tp->th_msg, strerror(error - 100), msglen);
1172	} else {
1173		tp->th_code = htons((u_short)error);
1174		strlcpy(tp->th_msg, pe->e_msg, msglen);
1175	}
1176	if (debug)
1177		syslog(LOG_DEBUG, "Send NACK %s", tp->th_msg);
1178	length = strlen(tp->th_msg);
1179	msglen = &tp->th_msg[length + 1] - buf;
1180	if (send(peer, buf, msglen, 0) != (ssize_t)msglen)
1181		syslog(LOG_ERR, "nak: %m");
1182}
1183
1184static char *
1185verifyhost(struct sockaddr *fromp)
1186{
1187	static char hbuf[MAXHOSTNAMELEN];
1188
1189	if (getnameinfo(fromp, fromp->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0))
1190		strlcpy(hbuf, "?", sizeof(hbuf));
1191	return (hbuf);
1192}
1193