tftpd.c revision 1.38 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
37 static 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
80 static int peer;
81 static int rexmtval = TIMEOUT;
82 static int maxtimeout = 5*TIMEOUT;
83
84 static char buf[MAXPKTSIZE];
85 static char ackbuf[PKTSIZE];
86 static char oackbuf[PKTSIZE];
87 static struct sockaddr_storage from;
88 static socklen_t fromlen;
89 static int debug;
90
91 static int tftp_opt_tsize = 0;
92 static int tftp_blksize = SEGSIZE;
93 static 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
103 static struct dirlist {
104 char *name;
105 int len;
106 } dirs[MAXDIRS+1];
107 static int suppress_naks;
108 static int logging;
109 static int secure;
110 static char pathsep = '\0';
111 static char *securedir;
112 static int unrestricted_writes; /* uploaded files don't have to exist */
113
114 struct formats;
115
116 static const char *errtomsg(int);
117 static void nak(int);
118 static void tftp(struct tftphdr *, int);
119 static void usage(void) __attribute__((__noreturn__));
120 static char *verifyhost(struct sockaddr *);
121 static void justquit(int);
122 static void recvfile(struct formats *, int, int);
123 static void sendfile(struct formats *, int, int);
124 static void timer(int);
125 static const char *opcode(int);
126 static int validate_access(char **, int);
127
128 static 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
140 static void
141 usage(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
150 int
151 main(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
421 static int
422 blk_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
461 static int
462 timeout_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
509 static int
510 tsize_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
551 static 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 */
566 static int
567 get_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 */
618 static void
619 tftp(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;
631 again:
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
728 FILE *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 */
739 int
740 validate_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
873 static int timeout;
874 static jmp_buf timeoutbuf;
875
876 static void
877 timer(int dummy)
878 {
879
880 timeout += rexmtval;
881 if (timeout >= maxtimeout)
882 exit(1);
883 longjmp(timeoutbuf, 1);
884 }
885
886 static const char *
887 opcode(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 */
913 static void
914 sendfile(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
947 send_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 }
992 done:
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);
1000 abort:
1001 (void) fclose(file);
1002 }
1003
1004 static void
1005 justquit(int dummy)
1006 {
1007
1008 exit(0);
1009 }
1010
1011 /*
1012 * Receive a file.
1013 */
1014 static void
1015 recvfile(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);
1042 send_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 }
1085 done:
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 }
1114 abort:
1115 return;
1116 }
1117
1118 const 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
1134 static const char *
1135 errtomsg(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 */
1155 static void
1156 nak(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
1184 static char *
1185 verifyhost(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