tftpd.c revision 1.23
1/*	$OpenBSD: tftpd.c,v 1.23 2014/11/19 11:48:39 dlg Exp $	*/
2
3/*
4 * Copyright (c) 2012 David Gwynne <dlg@uq.edu.au>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Copyright (c) 1983 Regents of the University of California.
21 * All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. Neither the name of the University nor the names of its contributors
32 *    may be used to endorse or promote products derived from this software
33 *    without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48/*
49 * Trivial file transfer protocol server.
50 *
51 * This version is based on src/libexec/tftpd which includes many
52 * modifications by Jim Guyton <guyton@rand-unix>.
53 *
54 * It was restructured to be a persistent event driven daemon
55 * supporting concurrent connections by dlg for use at the University
56 * of Queensland in the Faculty of Engineering Architecture and
57 * Information Technology.
58 */
59
60#include <sys/ioctl.h>
61#include <sys/param.h>
62#include <sys/types.h>
63#include <sys/queue.h>
64#include <sys/socket.h>
65#include <sys/stat.h>
66#include <sys/uio.h>
67#include <sys/un.h>
68
69#include <netinet/in.h>
70#include <arpa/inet.h>
71#include <arpa/tftp.h>
72#include <netdb.h>
73
74#include <err.h>
75#include <ctype.h>
76#include <errno.h>
77#include <event.h>
78#include <fcntl.h>
79#include <poll.h>
80#include <pwd.h>
81#include <stdio.h>
82#include <stdlib.h>
83#include <string.h>
84#include <stdarg.h>
85#include <syslog.h>
86#include <unistd.h>
87#include <vis.h>
88
89#define TIMEOUT		5		/* packet rexmt timeout */
90#define TIMEOUT_MIN	1		/* minimal packet rexmt timeout */
91#define TIMEOUT_MAX	255		/* maximal packet rexmt timeout */
92
93#define RETRIES		5
94
95struct formats;
96
97enum opt_enum {
98	OPT_TSIZE = 0,
99	OPT_TIMEOUT,
100	OPT_BLKSIZE,
101	NOPT
102};
103
104static char *opt_names[] = {
105	"tsize",
106	"timeout",
107	"blksize"
108};
109
110struct opt_client {
111	char *o_request;
112	long long o_reply;
113};
114
115
116struct tftp_server {
117	struct event ev;
118	TAILQ_ENTRY(tftp_server) entry;
119	int s;
120};
121
122TAILQ_HEAD(, tftp_server) tftp_servers;
123
124struct tftp_client {
125	char buf[SEGSIZE_MAX + 4];
126	struct event sev;
127	struct sockaddr_storage ss;
128
129	struct timeval tv;
130
131	TAILQ_ENTRY(tftp_client) entry;
132
133	struct opt_client *options;
134
135	size_t segment_size;
136	size_t packet_size;
137	size_t buflen;
138
139	FILE *file;
140	int (*fgetc)(struct tftp_client *);
141	int (*fputc)(struct tftp_client *, int);
142
143	u_int retries;
144	u_int16_t block;
145
146	int opcode;
147	int newline;
148
149	int sock;
150};
151
152__dead void	usage(void);
153const char	*getip(void *);
154
155void		rewrite_connect(const char *);
156void		rewrite_events(void);
157void		rewrite_map(struct tftp_client *, const char *);
158void		rewrite_req(int, short, void *);
159void		rewrite_res(int, short, void *);
160
161int		tftpd_listen(const char *, const char *, int);
162void		tftpd_events(void);
163void		tftpd_recv(int, short, void *);
164int		retry(struct tftp_client *);
165int		tftp_flush(struct tftp_client *);
166void		tftp_end(struct tftp_client *);
167
168void		tftp(struct tftp_client *, struct tftphdr *, size_t);
169void		tftp_open(struct tftp_client *, const char *);
170void		nak(struct tftp_client *, int);
171int		oack(struct tftp_client *);
172void		oack_done(int, short, void *);
173
174void		sendfile(struct tftp_client *);
175void		recvfile(struct tftp_client *);
176int		fget_octet(struct tftp_client *);
177int		fput_octet(struct tftp_client *, int);
178int		fget_netascii(struct tftp_client *);
179int		fput_netascii(struct tftp_client *, int);
180void		file_read(struct tftp_client *);
181int		tftp_wrq_ack_packet(struct tftp_client *);
182void		tftp_rrq_ack(int, short, void *);
183void		tftp_wrq_ack(struct tftp_client *client);
184void		tftp_wrq(int, short, void *);
185void		tftp_wrq_end(int, short, void *);
186
187int		parse_options(struct tftp_client *, char *, size_t,
188		    struct opt_client *);
189int		validate_access(struct tftp_client *, const char *);
190
191struct tftp_client *
192		client_alloc(void);
193void		client_free(struct tftp_client *client);
194
195struct formats {
196	const char	*f_mode;
197	int (*f_getc)(struct tftp_client *);
198	int (*f_putc)(struct tftp_client *, int);
199} formats[] = {
200	{ "octet",	fget_octet,	fput_octet },
201	{ "netascii",	fget_netascii,	fput_netascii },
202	{ NULL,		NULL }
203};
204
205struct errmsg {
206	int		 e_code;
207	const char	*e_msg;
208} errmsgs[] = {
209	{ EUNDEF,	"Undefined error code" },
210	{ ENOTFOUND,	"File not found" },
211	{ EACCESS,	"Access violation" },
212	{ ENOSPACE,	"Disk full or allocation exceeded" },
213	{ EBADOP,	"Illegal TFTP operation" },
214	{ EBADID,	"Unknown transfer ID" },
215	{ EEXISTS,	"File already exists" },
216	{ ENOUSER,	"No such user" },
217	{ EOPTNEG,	"Option negotiation failed" },
218	{ -1,		NULL }
219};
220
221struct loggers {
222	void (*err)(int, const char *, ...);
223	void (*errx)(int, const char *, ...);
224	void (*warn)(const char *, ...);
225	void (*warnx)(const char *, ...);
226	void (*info)(const char *, ...);
227};
228
229const struct loggers conslogger = {
230	err,
231	errx,
232	warn,
233	warnx,
234	warnx
235};
236
237void	syslog_err(int, const char *, ...);
238void	syslog_errx(int, const char *, ...);
239void	syslog_warn(const char *, ...);
240void	syslog_warnx(const char *, ...);
241void	syslog_info(const char *, ...);
242void	syslog_vstrerror(int, int, const char *, va_list);
243
244const struct loggers syslogger = {
245	syslog_err,
246	syslog_errx,
247	syslog_warn,
248	syslog_warnx,
249	syslog_info,
250};
251
252const struct loggers *logger = &conslogger;
253
254#define lerr(_e, _f...) logger->err((_e), _f)
255#define lerrx(_e, _f...) logger->errx((_e), _f)
256#define lwarn(_f...) logger->warn(_f)
257#define lwarnx(_f...) logger->warnx(_f)
258#define linfo(_f...) logger->info(_f)
259
260__dead void
261usage(void)
262{
263	extern char *__progname;
264	fprintf(stderr, "usage: %s [-46cdv] [-l address] [-p port] [-r socket]"
265	    " directory\n", __progname);
266	exit(1);
267}
268
269int		  cancreate = 0;
270int		  verbose = 0;
271
272int
273main(int argc, char *argv[])
274{
275	extern char *__progname;
276	int debug = 0;
277
278	int		 c;
279	struct passwd	*pw;
280
281	char *dir = NULL;
282	char *rewrite = NULL;
283
284	char *addr = NULL;
285	char *port = "tftp";
286	int family = AF_UNSPEC;
287
288	while ((c = getopt(argc, argv, "46cdl:p:r:v")) != -1) {
289		switch (c) {
290		case '4':
291			family = AF_INET;
292			break;
293		case '6':
294			family = AF_INET6;
295			break;
296		case 'c':
297			cancreate = 1;
298			break;
299		case 'd':
300			verbose = debug = 1;
301			break;
302		case 'l':
303			addr = optarg;
304			break;
305		case 'p':
306			port = optarg;
307			break;
308		case 'r':
309			rewrite = optarg;
310			break;
311		case 'v':
312			verbose = 1;
313			break;
314		default:
315			usage();
316			/* NOTREACHED */
317		}
318	}
319
320	argc -= optind;
321	argv += optind;
322
323	if (argc != 1)
324		usage();
325
326	dir = argv[0];
327
328	if (geteuid() != 0)
329		errx(1, "need root privileges");
330
331	pw = getpwnam("_tftpd");
332	if (pw == NULL)
333		errx(1, "no _tftpd user");
334
335	if (!debug) {
336		openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
337		tzset();
338		logger = &syslogger;
339	}
340
341	if (rewrite != NULL)
342		rewrite_connect(rewrite);
343
344	tftpd_listen(addr, port, family);
345
346	if (chroot(dir))
347		err(1, "chroot %s", dir);
348	if (chdir("/"))
349		err(1, "chdir %s", dir);
350
351	/* drop privs */
352	if (setgroups(1, &pw->pw_gid) ||
353	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
354	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
355		errx(1, "can't drop privileges");
356
357	if (!debug && daemon(1, 0) == -1)
358		err(1, "unable to daemonize");
359
360	event_init();
361
362	if (rewrite != NULL)
363		rewrite_events();
364
365	tftpd_events();
366
367	event_dispatch();
368
369	exit(0);
370}
371
372struct rewritemap {
373	struct event wrev;
374	struct event rdev;
375	struct evbuffer *wrbuf;
376	struct evbuffer *rdbuf;
377
378	TAILQ_HEAD(, tftp_client) clients;
379
380	int s;
381};
382
383struct rewritemap *rwmap = NULL;
384
385void
386rewrite_connect(const char *path)
387{
388	int s;
389	struct sockaddr_un remote;
390	size_t len;
391	int on = 1;
392
393	rwmap = malloc(sizeof(*rwmap));
394	if (rwmap == NULL)
395		err(1, "rewrite event malloc");
396
397	rwmap->wrbuf = evbuffer_new();
398	if (rwmap->wrbuf == NULL)
399		err(1, "rewrite wrbuf");
400
401	rwmap->rdbuf = evbuffer_new();
402	if (rwmap->rdbuf == NULL)
403		err(1, "rewrite rdbuf");
404
405	TAILQ_INIT(&rwmap->clients);
406
407	s = socket(AF_UNIX, SOCK_STREAM, 0);
408	if (s == -1)
409		err(1, "rewrite socket");
410
411	remote.sun_family = AF_UNIX;
412	len = strlcpy(remote.sun_path, path, sizeof(remote.sun_path));
413	if (len >= sizeof(remote.sun_path))
414		errx(1, "rewrite socket path is too long");
415
416	len += sizeof(remote.sun_family) + 1;
417	if (connect(s, (struct sockaddr *)&remote, len) == -1)
418		err(1, "%s", path);
419
420	if (ioctl(s, FIONBIO, &on) < 0)
421		err(1, "rewrite ioctl(FIONBIO)");
422
423	rwmap->s = s;
424}
425
426void
427rewrite_events(void)
428{
429	event_set(&rwmap->wrev, rwmap->s, EV_WRITE, rewrite_req, NULL);
430	event_set(&rwmap->rdev, rwmap->s, EV_READ | EV_PERSIST, rewrite_res, NULL);
431	event_add(&rwmap->rdev, NULL);
432}
433
434void
435rewrite_map(struct tftp_client *client, const char *filename)
436{
437	char *nicebuf;
438
439	if (stravis(&nicebuf, filename, VIS_SAFE|VIS_OCTAL) == -1)
440		lerr(1, "rwmap stravis");
441
442	if (evbuffer_add_printf(rwmap->wrbuf, "%s %s %s\n", getip(&client->ss),
443	    client->opcode == WRQ ? "write" : "read", nicebuf) == -1)
444		lerr(1, "rwmap printf");
445
446	free(nicebuf);
447
448	TAILQ_INSERT_TAIL(&rwmap->clients, client, entry);
449
450	event_add(&rwmap->wrev, NULL);
451}
452
453void
454rewrite_req(int fd, short events, void *arg)
455{
456	if (evbuffer_write(rwmap->wrbuf, fd) == -1)
457		lerr(1, "rwmap read");
458
459	if (EVBUFFER_LENGTH(rwmap->wrbuf))
460		event_add(&rwmap->wrev, NULL);
461}
462
463void
464rewrite_res(int fd, short events, void *arg)
465{
466	struct tftp_client *client;
467	char *filename;
468	size_t len;
469
470	if (evbuffer_read(rwmap->rdbuf, fd, MAXPATHLEN) == -1)
471		lerr(1, "rwmap read");
472
473	while ((filename = evbuffer_readln(rwmap->rdbuf, &len,
474	    EVBUFFER_EOL_LF)) != NULL) {
475		client = TAILQ_FIRST(&rwmap->clients);
476		if (client == NULL)
477			lerrx(1, "unexpected rwmap reply");
478
479		TAILQ_REMOVE(&rwmap->clients, client, entry);
480
481		tftp_open(client, filename);
482
483		free(filename);
484	};
485}
486
487int
488tftpd_listen(const char *addr, const char *port, int family)
489{
490	struct tftp_server *server;
491
492	struct addrinfo hints, *res, *res0;
493	int error;
494	int s;
495
496	int cerrno = EADDRNOTAVAIL;
497	const char *cause = "getaddrinfo";
498
499	int on = 1;
500
501	memset(&hints, 0, sizeof(hints));
502	hints.ai_family = family;
503	hints.ai_socktype = SOCK_DGRAM;
504	hints.ai_flags = AI_PASSIVE;
505
506	TAILQ_INIT(&tftp_servers);
507
508	error = getaddrinfo(addr, port, &hints, &res0);
509	if (error) {
510		errx(1, "%s:%s: %s", addr ? addr : "*", port,
511		    gai_strerror(error));
512	}
513
514	for (res = res0; res != NULL; res = res->ai_next) {
515		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
516		if (s == -1) {
517			cause = "socket";
518			cerrno = errno;
519			continue;
520		}
521
522		if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
523			cause = "bind";
524			cerrno = errno;
525			close(s);
526			continue;
527		}
528
529		if (ioctl(s, FIONBIO, &on) < 0)
530			err(1, "ioctl(FIONBIO)");
531
532		switch (res->ai_family) {
533		case AF_INET:
534			if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
535			    &on, sizeof(on)) == -1)
536				err(1, "setsockopt(IP_RECVDSTADDR)");
537			break;
538		case AF_INET6:
539			if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
540			    &on, sizeof(on)) == -1)
541				err(1, "setsockopt(IPV6_RECVPKTINFO)");
542			break;
543		}
544
545		server = malloc(sizeof(*server));
546		if (server == NULL)
547			err(1, "malloc");
548
549		server->s = s;
550		TAILQ_INSERT_TAIL(&tftp_servers, server, entry);
551	}
552
553	if (TAILQ_EMPTY(&tftp_servers))
554		errc(1, cerrno, "%s", cause);
555
556	freeaddrinfo(res0);
557	return (0);
558}
559
560void
561tftpd_events(void)
562{
563	struct tftp_server *server;
564	TAILQ_FOREACH(server, &tftp_servers, entry) {
565		event_set(&server->ev, server->s, EV_READ | EV_PERSIST,
566		    tftpd_recv, server);
567		event_add(&server->ev, NULL);
568	}
569}
570
571struct tftp_client *
572client_alloc(void)
573{
574	struct tftp_client *client;
575
576	client = calloc(1, sizeof(*client));
577	if (client == NULL)
578		return (NULL);
579
580	client->segment_size = SEGSIZE;
581	client->packet_size = SEGSIZE + 4;
582
583	client->tv.tv_sec = TIMEOUT;
584	client->tv.tv_usec = 0;
585
586	client->sock = -1;
587	client->file = NULL;
588	client->newline = 0;
589
590	return (client);
591}
592
593void
594client_free(struct tftp_client *client)
595{
596	if (client->options != NULL)
597		free(client->options);
598
599	if (client->file != NULL)
600		fclose(client->file);
601
602	close(client->sock);
603
604	free(client);
605}
606
607void
608tftpd_recv(int fd, short events, void *arg)
609{
610	union {
611		struct cmsghdr hdr;
612		char	buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
613	} cmsgbuf;
614	struct cmsghdr *cmsg;
615	struct msghdr msg;
616	struct iovec iov;
617
618	ssize_t n;
619	struct sockaddr_storage s_in;
620	int dobind = 1;
621	int on = 1;
622
623	struct tftphdr *tp;
624
625	struct tftp_client *client;
626
627	client = client_alloc();
628	if (client == NULL) {
629		char *buf = alloca(SEGSIZE_MAX + 4);
630		/* no memory! flush this request... */
631		recv(fd, buf, SEGSIZE_MAX + 4, 0);
632		/* dont care if it fails */
633		return;
634	}
635
636	bzero(&msg, sizeof(msg));
637	iov.iov_base = client->buf;
638	iov.iov_len = client->packet_size;
639	msg.msg_name = &client->ss;
640	msg.msg_namelen = sizeof(client->ss);
641	msg.msg_iov = &iov;
642	msg.msg_iovlen = 1;
643	msg.msg_control = &cmsgbuf.buf;
644	msg.msg_controllen = sizeof(cmsgbuf.buf);
645
646	n = recvmsg(fd, &msg, 0);
647	if (n == -1) {
648		lwarn("recvmsg");
649		goto err;
650	}
651	if (n < 4)
652		goto err;
653
654	client->sock = socket(client->ss.ss_family, SOCK_DGRAM, 0);
655	if (client->sock == -1) {
656		lwarn("socket");
657		goto err;
658	}
659	memset(&s_in, 0, sizeof(s_in));
660	s_in.ss_family = client->ss.ss_family;
661	s_in.ss_len = client->ss.ss_len;
662
663	/* get local address if possible */
664	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
665	    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
666		if (cmsg->cmsg_level == IPPROTO_IP &&
667		    cmsg->cmsg_type == IP_RECVDSTADDR) {
668			memcpy(&((struct sockaddr_in *)&s_in)->sin_addr,
669			    CMSG_DATA(cmsg), sizeof(struct in_addr));
670			if (((struct sockaddr_in *)&s_in)->sin_addr.s_addr ==
671			    INADDR_BROADCAST)
672				dobind = 0;
673			break;
674		}
675		if (cmsg->cmsg_level == IPPROTO_IPV6 &&
676		    cmsg->cmsg_type == IPV6_PKTINFO) {
677			struct in6_pktinfo *ipi;
678
679			ipi = (struct in6_pktinfo *)CMSG_DATA(cmsg);
680			memcpy(&((struct sockaddr_in6 *)&s_in)->sin6_addr,
681			    &ipi->ipi6_addr, sizeof(struct in6_addr));
682#ifdef __KAME__
683			if (IN6_IS_ADDR_LINKLOCAL(&ipi->ipi6_addr))
684				((struct sockaddr_in6 *)&s_in)->sin6_scope_id =
685				    ipi->ipi6_ifindex;
686#endif
687			break;
688		}
689	}
690
691	if (dobind) {
692		setsockopt(client->sock, SOL_SOCKET, SO_REUSEADDR,
693		    &on, sizeof(on));
694		setsockopt(client->sock, SOL_SOCKET, SO_REUSEPORT,
695		    &on, sizeof(on));
696
697		if (bind(client->sock, (struct sockaddr *)&s_in,
698		    s_in.ss_len) < 0) {
699			lwarn("bind to %s", getip(&s_in));
700			goto err;
701		}
702	}
703	if (connect(client->sock, (struct sockaddr *)&client->ss,
704	    client->ss.ss_len) == -1) {
705		lwarn("connect to %s", getip(&client->ss));
706		goto err;
707	}
708
709	if (ioctl(client->sock, FIONBIO, &on) < 0)
710		err(1, "client ioctl(FIONBIO)");
711
712	tp = (struct tftphdr *)client->buf;
713	client->opcode = ntohs(tp->th_opcode);
714	if (client->opcode != RRQ && client->opcode != WRQ) {
715		/* bad request */
716		goto err;
717	}
718
719	tftp(client, tp, n);
720
721	return;
722
723err:
724	client_free(client);
725}
726
727int
728parse_options(struct tftp_client *client, char *cp, size_t size,
729    struct opt_client *options)
730{
731	char *option;
732	char *ccp;
733	int has_options = 0;
734	int i;
735
736	while (++cp < client->buf + size) {
737		for (i = 2, ccp = cp; i > 0; ccp++) {
738			if (ccp >= client->buf + size) {
739				/*
740				 * Don't reject the request, just stop trying
741				 * to parse the option and get on with it.
742				 * Some Apple OpenFirmware versions have
743				 * trailing garbage on the end of otherwise
744				 * valid requests.
745				 */
746				return (has_options);
747			} else if (*ccp == '\0')
748				i--;
749		}
750
751		for (option = cp; *cp; cp++)
752			*cp = tolower((unsigned char)*cp);
753
754		for (i = 0; i < NOPT; i++) {
755			if (strcmp(option, opt_names[i]) == 0) {
756				options[i].o_request = ++cp;
757				has_options = 1;
758			}
759		}
760		cp = ccp - 1;
761	}
762
763	return (has_options);
764}
765
766/*
767 * Handle initial connection protocol.
768 */
769void
770tftp(struct tftp_client *client, struct tftphdr *tp, size_t size)
771{
772	struct opt_client *options;
773
774	char		*cp;
775	int		 i, first = 1, ecode, to;
776	struct formats	*pf;
777	char		*mode = NULL;
778	char		 filename[MAXPATHLEN];
779	const char	*errstr;
780
781	if (size < 5) {
782		ecode = EBADOP;
783		goto error;
784	}
785
786	cp = tp->th_stuff;
787again:
788	while (cp < client->buf + size) {
789		if (*cp == '\0')
790			break;
791		cp++;
792	}
793	if (*cp != '\0') {
794		ecode = EBADOP;
795		goto error;
796	}
797	i = cp - tp->th_stuff;
798	if (i >= sizeof(filename)) {
799		ecode = EBADOP;
800		goto error;
801	}
802	memcpy(filename, tp->th_stuff, i);
803	filename[i] = '\0';
804	if (first) {
805		mode = ++cp;
806		first = 0;
807		goto again;
808	}
809	for (cp = mode; *cp; cp++)
810		*cp = tolower((unsigned char)*cp);
811
812	for (pf = formats; pf->f_mode; pf++) {
813		if (strcmp(pf->f_mode, mode) == 0)
814			break;
815	}
816	if (pf->f_mode == 0) {
817		ecode = EBADOP;
818		goto error;
819	}
820	client->fgetc = pf->f_getc;
821	client->fputc = pf->f_putc;
822
823	client->options = options = calloc(NOPT, sizeof(*client->options));
824	if (options == NULL) {
825		ecode = 100 + ENOMEM;
826		goto error;
827	}
828
829	if (parse_options(client, cp, size, options)) {
830		if (options[OPT_TIMEOUT].o_request != NULL) {
831			to = strtonum(options[OPT_TIMEOUT].o_request,
832			    TIMEOUT_MIN, TIMEOUT_MAX, &errstr);
833			if (errstr) {
834				ecode = EBADOP;
835				goto error;
836			}
837			options[OPT_TIMEOUT].o_reply = client->tv.tv_sec = to;
838		}
839
840		if (options[OPT_BLKSIZE].o_request) {
841			client->segment_size = strtonum(
842			    options[OPT_BLKSIZE].o_request,
843			    SEGSIZE_MIN, SEGSIZE_MAX, &errstr);
844			if (errstr) {
845				ecode = EBADOP;
846				goto error;
847			}
848			client->packet_size = client->segment_size + 4;
849			options[OPT_BLKSIZE].o_reply = client->segment_size;
850		}
851	} else {
852		free(options);
853		client->options = NULL;
854	}
855
856	if (verbose) {
857		char nicebuf[MAXPATHLEN];
858
859		(void)strnvis(nicebuf, filename, MAXPATHLEN,
860		    VIS_SAFE|VIS_OCTAL);
861
862		linfo("%s: %s request for '%s'", getip(&client->ss),
863		    client->opcode == WRQ ? "write" : "read", nicebuf);
864	}
865
866	if (rwmap != NULL)
867		rewrite_map(client, filename);
868	else
869		tftp_open(client, filename);
870
871	return;
872
873error:
874	nak(client, ecode);
875}
876
877void
878tftp_open(struct tftp_client *client, const char *filename)
879{
880	int ecode;
881
882	ecode = validate_access(client, filename);
883	if (ecode)
884		goto error;
885
886	if (client->options) {
887		if (oack(client) == -1)
888			goto error;
889
890		free(client->options);
891		client->options = NULL;
892	} else if (client->opcode == WRQ) {
893		recvfile(client);
894	} else
895		sendfile(client);
896
897	return;
898error:
899	nak(client, ecode);
900}
901
902/*
903 * Validate file access.  Since we
904 * have no uid or gid, for now require
905 * file to exist and be publicly
906 * readable/writable.
907 * If we were invoked with arguments
908 * from inetd then the file must also be
909 * in one of the given directory prefixes.
910 * Note also, full path name must be
911 * given as we have no login directory.
912 */
913int
914validate_access(struct tftp_client *client, const char *filename)
915{
916	int		 mode = client->opcode;
917	struct opt_client *options = client->options;
918	struct stat	 stbuf;
919	int		 fd, wmode;
920	const char	*errstr;
921
922	/*
923	 * We use a different permissions scheme if `cancreate' is
924	 * set.
925	 */
926	wmode = O_TRUNC;
927	if (stat(filename, &stbuf) < 0) {
928		if (!cancreate)
929			return (errno == ENOENT ? ENOTFOUND : EACCESS);
930		else {
931			if ((errno == ENOENT) && (mode != RRQ))
932				wmode |= O_CREAT;
933			else
934				return (EACCESS);
935		}
936	} else {
937		if (mode == RRQ) {
938			if ((stbuf.st_mode & (S_IRUSR >> 6)) == 0)
939				return (EACCESS);
940		} else {
941			if ((stbuf.st_mode & (S_IWUSR >> 6)) == 0)
942				return (EACCESS);
943		}
944	}
945
946	if (options != NULL && options[OPT_TSIZE].o_request) {
947		if (mode == RRQ)
948			options[OPT_TSIZE].o_reply = stbuf.st_size;
949		else {
950			/* allows writes of 65535 blocks * SEGSIZE_MAX bytes */
951			options[OPT_TSIZE].o_reply =
952			    strtonum(options[OPT_TSIZE].o_request,
953			    1, 65535LL * SEGSIZE_MAX, &errstr);
954			if (errstr)
955				return (EOPTNEG);
956		}
957	}
958	fd = open(filename, mode == RRQ ? O_RDONLY : (O_WRONLY|wmode), 0666);
959	if (fd < 0)
960		return (errno + 100);
961	/*
962	 * If the file was created, set default permissions.
963	 */
964	if ((wmode & O_CREAT) && fchmod(fd, 0666) < 0) {
965		int serrno = errno;
966
967		close(fd);
968		unlink(filename);
969
970		return (serrno + 100);
971	}
972	client->file = fdopen(fd, mode == RRQ ? "r" : "w");
973	if (client->file == NULL) {
974		close(fd);
975		return (errno + 100);
976	}
977
978	return (0);
979}
980
981int
982fget_octet(struct tftp_client *client)
983{
984	return (getc(client->file));
985}
986
987int
988fput_octet(struct tftp_client *client, int c)
989{
990	return (putc(c, client->file));
991}
992
993int
994fget_netascii(struct tftp_client *client)
995{
996	int c = -1;
997
998	switch (client->newline) {
999	case 0:
1000		c = getc(client->file);
1001		if (c == EOF)
1002			break;
1003
1004		if (c == '\n' || c == '\r') {
1005			client->newline = c;
1006			c = '\r';
1007		}
1008		break;
1009	case '\n':
1010		client->newline = 0;
1011		c = '\n';
1012		break;
1013	case '\r':
1014		client->newline = 0;
1015		c = '\0';
1016		break;
1017	}
1018
1019	return (c);
1020}
1021
1022int
1023fput_netascii(struct tftp_client *client, int c)
1024{
1025	if (client->newline == '\r') {
1026		client->newline = 0;
1027
1028		if (c == '\0')
1029			c = '\r';
1030
1031	} else if (c == '\r') {
1032		client->newline = c;
1033		return (c);
1034	}
1035
1036	return (putc(c, client->file));
1037}
1038
1039void
1040sendfile(struct tftp_client *client)
1041{
1042	event_set(&client->sev, client->sock, EV_READ, tftp_rrq_ack, client);
1043	client->block = 1;
1044
1045	file_read(client);
1046}
1047
1048void
1049file_read(struct tftp_client *client)
1050{
1051	u_int8_t *buf;
1052	struct tftphdr *dp;
1053	int i;
1054	int c;
1055
1056	dp = (struct tftphdr *)client->buf;
1057	dp->th_opcode = htons((u_short)DATA);
1058	dp->th_block = htons(client->block);
1059	buf = (u_int8_t *)dp->th_data;
1060
1061	for (i = 0; i < client->segment_size; i++) {
1062		c = client->fgetc(client);
1063		if (c == EOF) {
1064			if (ferror(client->file)) {
1065				nak(client, 100 + EIO);
1066				return;
1067			}
1068
1069			break;
1070		}
1071		buf[i] = c;
1072	}
1073
1074	client->buflen = i + 4;
1075	client->retries = RETRIES;
1076
1077	if (send(client->sock, client->buf, client->buflen, 0) == -1) {
1078		lwarn("send(block)");
1079		client_free(client);
1080		return;
1081	}
1082
1083	event_add(&client->sev, &client->tv);
1084}
1085
1086void
1087tftp_rrq_ack(int fd, short events, void *arg)
1088{
1089	struct tftp_client *client = arg;
1090	struct tftphdr *ap; /* ack packet */
1091	char rbuf[SEGSIZE_MIN];
1092	ssize_t n;
1093
1094	if (events & EV_TIMEOUT) {
1095		if (retry(client) == -1) {
1096			lwarn("%s: retry", getip(&client->ss));
1097			goto done;
1098		}
1099
1100		return;
1101	}
1102
1103	n = recv(fd, rbuf, sizeof(rbuf), 0);
1104	if (n == -1) {
1105		switch (errno) {
1106		case EINTR:
1107		case EAGAIN:
1108			event_add(&client->sev, &client->tv);
1109			return;
1110
1111		default:
1112			lwarn("%s: recv", getip(&client->ss));
1113			goto done;
1114		}
1115	}
1116
1117	ap = (struct tftphdr *)rbuf;
1118	ap->th_opcode = ntohs((u_short)ap->th_opcode);
1119	ap->th_block = ntohs((u_short)ap->th_block);
1120
1121	switch (ap->th_opcode) {
1122	case ERROR:
1123		goto done;
1124	case ACK:
1125		break;
1126	default:
1127		goto retry;
1128	}
1129
1130	if (ap->th_block != client->block) {
1131		if (tftp_flush(client) == -1) {
1132			lwarnx("%s: flush", getip(&client->ss));
1133			goto done;
1134		}
1135
1136		if (ap->th_block != (client->block - 1))
1137			goto done;
1138
1139		goto retry;
1140	}
1141
1142	if (client->buflen != client->packet_size) {
1143		/* this was the last packet in the stream */
1144		goto done;
1145	}
1146
1147	client->block++;
1148	file_read(client);
1149	return;
1150
1151retry:
1152	event_add(&client->sev, &client->tv);
1153	return;
1154
1155done:
1156	client_free(client);
1157}
1158
1159int
1160tftp_flush(struct tftp_client *client)
1161{
1162	char rbuf[SEGSIZE_MIN];
1163	ssize_t n;
1164
1165	for (;;) {
1166		n = recv(client->sock, rbuf, sizeof(rbuf), 0);
1167		if (n == -1) {
1168			switch (errno) {
1169			case EAGAIN:
1170				return (0);
1171
1172			case EINTR:
1173				break;
1174
1175			default:
1176				return (-1);
1177			}
1178		}
1179	}
1180}
1181
1182void
1183recvfile(struct tftp_client *client)
1184{
1185	event_set(&client->sev, client->sock, EV_READ, tftp_wrq, client);
1186	tftp_wrq_ack(client);
1187}
1188
1189int
1190tftp_wrq_ack_packet(struct tftp_client *client)
1191{
1192	struct tftphdr *ap; /* ack packet */
1193
1194	ap = (struct tftphdr *)client->buf;
1195	ap->th_opcode = htons((u_short)ACK);
1196	ap->th_block = htons(client->block);
1197
1198	client->buflen = 4;
1199	client->retries = RETRIES;
1200
1201	return (send(client->sock, client->buf, client->buflen, 0) != 4);
1202}
1203
1204void
1205tftp_wrq_ack(struct tftp_client *client)
1206{
1207	if (tftp_wrq_ack_packet(client) != 0) {
1208		lwarn("tftp wrq ack");
1209		client_free(client);
1210		return;
1211	}
1212
1213	client->block++;
1214	event_add(&client->sev, &client->tv);
1215}
1216
1217void
1218tftp_wrq(int fd, short events, void *arg)
1219{
1220	char wbuf[SEGSIZE_MAX + 4];
1221	struct tftp_client *client = arg;
1222	struct tftphdr *dp;
1223	ssize_t n;
1224	int i;
1225
1226	if (events & EV_TIMEOUT) {
1227		if (retry(client) == -1) {
1228			lwarn("%s", getip(&client->ss));
1229			goto done;
1230		}
1231
1232		return;
1233	}
1234
1235	n = recv(fd, wbuf, client->packet_size, 0);
1236	if (n == -1) {
1237		switch (errno) {
1238		case EINTR:
1239		case EAGAIN:
1240			goto retry;
1241
1242		default:
1243			lwarn("tftp_wrq recv");
1244			goto done;
1245		}
1246	}
1247
1248	if (n < 4)
1249		goto done;
1250
1251	dp = (struct tftphdr *)wbuf;
1252	dp->th_opcode = ntohs((u_short)dp->th_opcode);
1253	dp->th_block = ntohs((u_short)dp->th_block);
1254
1255	switch (dp->th_opcode) {
1256	case ERROR:
1257		goto done;
1258	case DATA:
1259		break;
1260	default:
1261		goto retry;
1262	}
1263
1264	if (dp->th_block != client->block) {
1265		if (tftp_flush(client) == -1) {
1266			lwarnx("%s: flush", getip(&client->ss));
1267			goto done;
1268		}
1269
1270		if (dp->th_block != (client->block - 1))
1271			goto done;
1272
1273		goto retry;
1274	}
1275
1276	for (i = 4; i < n; i++) {
1277		if (client->fputc(client, wbuf[i]) == EOF) {
1278			lwarn("tftp wrq");
1279			goto done;
1280		}
1281	}
1282
1283	if (n < client->packet_size) {
1284		tftp_wrq_ack_packet(client);
1285		fclose(client->file);
1286		client->file = NULL;
1287		event_set(&client->sev, client->sock, EV_READ,
1288		    tftp_wrq_end, client);
1289		event_add(&client->sev, &client->tv);
1290		return;
1291	}
1292
1293	tftp_wrq_ack(client);
1294	return;
1295
1296retry:
1297	event_add(&client->sev, &client->tv);
1298	return;
1299done:
1300	client_free(client);
1301}
1302
1303void
1304tftp_wrq_end(int fd, short events, void *arg)
1305{
1306	char wbuf[SEGSIZE_MAX + 4];
1307	struct tftp_client *client = arg;
1308	struct tftphdr *dp;
1309	ssize_t n;
1310
1311	if (events & EV_TIMEOUT) {
1312		/* this was the last packet, we can clean up */
1313		goto done;
1314	}
1315
1316	n = recv(fd, wbuf, client->packet_size, 0);
1317	if (n == -1) {
1318		switch (errno) {
1319		case EINTR:
1320		case EAGAIN:
1321			goto retry;
1322
1323		default:
1324			lwarn("tftp_wrq_end recv");
1325			goto done;
1326		}
1327	}
1328
1329	if (n < 4)
1330		goto done;
1331
1332	dp = (struct tftphdr *)wbuf;
1333	dp->th_opcode = ntohs((u_short)dp->th_opcode);
1334	dp->th_block = ntohs((u_short)dp->th_block);
1335
1336	switch (dp->th_opcode) {
1337	case ERROR:
1338		goto done;
1339	case DATA:
1340		break;
1341	default:
1342		goto retry;
1343	}
1344
1345	if (dp->th_block != client->block)
1346		goto done;
1347
1348retry:
1349	if (retry(client) == -1) {
1350		lwarn("%s", getip(&client->ss));
1351		goto done;
1352	}
1353	return;
1354done:
1355	client_free(client);
1356	return;
1357}
1358
1359
1360/*
1361 * Send a nak packet (error message).
1362 * Error code passed in is one of the
1363 * standard TFTP codes, or a UNIX errno
1364 * offset by 100.
1365 */
1366void
1367nak(struct tftp_client *client, int error)
1368{
1369	struct tftphdr	*tp;
1370	struct errmsg	*pe;
1371	size_t		 length;
1372
1373	tp = (struct tftphdr *)client->buf;
1374	tp->th_opcode = htons((u_short)ERROR);
1375	tp->th_code = htons((u_short)error);
1376
1377	for (pe = errmsgs; pe->e_code >= 0; pe++) {
1378		if (pe->e_code == error)
1379			break;
1380	}
1381	if (pe->e_code < 0) {
1382		pe->e_msg = strerror(error - 100);
1383		tp->th_code = htons(EUNDEF);   /* set 'undef' errorcode */
1384	}
1385
1386	length = strlcpy(tp->th_msg, pe->e_msg, client->packet_size - 5) + 5;
1387	if (length > client->packet_size)
1388		length = client->packet_size;
1389
1390	if (send(client->sock, client->buf, length, 0) != length)
1391		lwarn("nak");
1392
1393	client_free(client);
1394}
1395
1396/*
1397 * Send an oack packet (option acknowledgement).
1398 */
1399int
1400oack(struct tftp_client *client)
1401{
1402	struct opt_client *options = client->options;
1403	struct tftphdr *tp;
1404	char *bp;
1405	int i, n, size;
1406
1407	tp = (struct tftphdr *)client->buf;
1408	bp = (char *)tp->th_stuff;
1409	size = sizeof(client->buf) - 2;
1410
1411	tp->th_opcode = htons((u_short)OACK);
1412	for (i = 0; i < NOPT; i++) {
1413		if (options[i].o_request == NULL)
1414			continue;
1415
1416		n = snprintf(bp, size, "%s%c%lld", opt_names[i], '\0',
1417		    options[i].o_reply);
1418		if (n == -1 || n >= size) {
1419			lwarnx("oack: no buffer space");
1420			goto error;
1421		}
1422
1423		bp += n + 1;
1424		size -= n + 1;
1425		if (size < 0) {
1426			lwarnx("oack: no buffer space");
1427			goto error;
1428		}
1429	}
1430
1431	client->buflen = bp - client->buf;
1432	client->retries = RETRIES;
1433
1434	if (send(client->sock, client->buf, client->buflen, 0) == -1) {
1435		lwarn("oack");
1436		goto error;
1437	}
1438
1439	/* no client ACK for write requests with options */
1440	if (client->opcode == WRQ) {
1441		client->block = 1;
1442		event_set(&client->sev, client->sock, EV_READ,
1443		    tftp_wrq, client);
1444	} else
1445		event_set(&client->sev, client->sock, EV_READ,
1446		    oack_done, client);
1447
1448	event_add(&client->sev, &client->tv);
1449	return (0);
1450
1451error:
1452	return (-1);
1453}
1454
1455int
1456retry(struct tftp_client *client)
1457{
1458	if (--client->retries == 0) {
1459		errno = ETIMEDOUT;
1460		return (-1);
1461	}
1462
1463	if (send(client->sock, client->buf, client->buflen, 0) == -1)
1464		return (-1);
1465
1466	event_add(&client->sev, &client->tv);
1467
1468	return (0);
1469}
1470
1471void
1472oack_done(int fd, short events, void *arg)
1473{
1474	struct tftp_client *client = arg;
1475	struct tftphdr *ap;
1476	ssize_t n;
1477
1478	if (events & EV_TIMEOUT) {
1479		if (retry(client) == -1) {
1480			lwarn("%s", getip(&client->ss));
1481			goto done;
1482		}
1483
1484		return;
1485	}
1486
1487	n = recv(client->sock, client->buf, client->packet_size, 0);
1488	if (n == -1) {
1489		switch (errno) {
1490		case EINTR:
1491		case EAGAIN:
1492			event_add(&client->sev, &client->tv);
1493			return;
1494
1495		default:
1496			lwarn("%s: recv", getip(&client->ss));
1497			goto done;
1498		}
1499	}
1500
1501	if (n < 4)
1502		goto done;
1503
1504	ap = (struct tftphdr *)client->buf;
1505	ap->th_opcode = ntohs((u_short)ap->th_opcode);
1506	ap->th_block = ntohs((u_short)ap->th_block);
1507
1508	if (ap->th_opcode != ACK || ap->th_block != 0)
1509		goto done;
1510
1511	sendfile(client);
1512	return;
1513
1514done:
1515	client_free(client);
1516}
1517
1518const char *
1519getip(void *s)
1520{
1521	struct sockaddr *sa = s;
1522	static char hbuf[NI_MAXHOST];
1523
1524	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
1525	    NULL, 0, NI_NUMERICHOST))
1526		strlcpy(hbuf, "0.0.0.0", sizeof(hbuf));
1527
1528	return(hbuf);
1529}
1530
1531void
1532syslog_vstrerror(int e, int priority, const char *fmt, va_list ap)
1533{
1534	char *s;
1535
1536	if (vasprintf(&s, fmt, ap) == -1) {
1537		syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror");
1538		exit(1);
1539	}
1540
1541	syslog(priority, "%s: %s", s, strerror(e));
1542
1543	free(s);
1544}
1545
1546void
1547syslog_err(int ecode, const char *fmt, ...)
1548{
1549	va_list ap;
1550
1551	va_start(ap, fmt);
1552	syslog_vstrerror(errno, LOG_EMERG, fmt, ap);
1553	va_end(ap);
1554
1555	exit(ecode);
1556}
1557
1558void
1559syslog_errx(int ecode, const char *fmt, ...)
1560{
1561	va_list ap;
1562
1563	va_start(ap, fmt);
1564	vsyslog(LOG_WARNING, fmt, ap);
1565	va_end(ap);
1566
1567	exit(ecode);
1568}
1569
1570void
1571syslog_warn(const char *fmt, ...)
1572{
1573	va_list ap;
1574
1575	va_start(ap, fmt);
1576	syslog_vstrerror(errno, LOG_WARNING, fmt, ap);
1577	va_end(ap);
1578}
1579
1580void
1581syslog_warnx(const char *fmt, ...)
1582{
1583	va_list ap;
1584
1585	va_start(ap, fmt);
1586	vsyslog(LOG_WARNING, fmt, ap);
1587	va_end(ap);
1588}
1589
1590void
1591syslog_info(const char *fmt, ...)
1592{
1593	va_list ap;
1594
1595	va_start(ap, fmt);
1596	vsyslog(LOG_INFO, fmt, ap);
1597	va_end(ap);
1598}
1599
1600