Home | History | Annotate | Line # | Download | only in tftpd
tftpd.c revision 1.1.1.2
      1 /*
      2  * Copyright (c) 1983, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char copyright[] =
     36 "@(#) Copyright (c) 1983, 1993\n\
     37 	The Regents of the University of California.  All rights reserved.\n";
     38 #endif /* not lint */
     39 
     40 #ifndef lint
     41 static char sccsid[] = "@(#)tftpd.c	8.1 (Berkeley) 6/4/93";
     42 #endif /* not lint */
     43 
     44 /*
     45  * Trivial file transfer protocol server.
     46  *
     47  * This version includes many modifications by Jim Guyton
     48  * <guyton@rand-unix>.
     49  */
     50 
     51 #include <sys/param.h>
     52 #include <sys/ioctl.h>
     53 #include <sys/stat.h>
     54 #include <sys/socket.h>
     55 
     56 #include <netinet/in.h>
     57 #include <arpa/tftp.h>
     58 #include <arpa/inet.h>
     59 
     60 #include <ctype.h>
     61 #include <errno.h>
     62 #include <fcntl.h>
     63 #include <netdb.h>
     64 #include <setjmp.h>
     65 #include <signal.h>
     66 #include <stdio.h>
     67 #include <stdlib.h>
     68 #include <string.h>
     69 #include <syslog.h>
     70 #include <unistd.h>
     71 
     72 #include "tftpsubs.h"
     73 
     74 #define	TIMEOUT		5
     75 
     76 int	peer;
     77 int	rexmtval = TIMEOUT;
     78 int	maxtimeout = 5*TIMEOUT;
     79 
     80 #define	PKTSIZE	SEGSIZE+4
     81 char	buf[PKTSIZE];
     82 char	ackbuf[PKTSIZE];
     83 struct	sockaddr_in from;
     84 int	fromlen;
     85 
     86 void	tftp __P((struct tftphdr *, int));
     87 
     88 /*
     89  * Null-terminated directory prefix list for absolute pathname requests and
     90  * search list for relative pathname requests.
     91  *
     92  * MAXDIRS should be at least as large as the number of arguments that
     93  * inetd allows (currently 20).
     94  */
     95 #define MAXDIRS	20
     96 static struct dirlist {
     97 	char	*name;
     98 	int	len;
     99 } dirs[MAXDIRS+1];
    100 static int	suppress_naks;
    101 static int	logging;
    102 
    103 static char *errtomsg __P((int));
    104 static void  nak __P((int));
    105 static char *verifyhost __P((struct sockaddr_in *));
    106 
    107 int
    108 main(argc, argv)
    109 	int argc;
    110 	char *argv[];
    111 {
    112 	register struct tftphdr *tp;
    113 	register int n;
    114 	int ch, on;
    115 	struct sockaddr_in sin;
    116 
    117 	openlog("tftpd", LOG_PID, LOG_FTP);
    118 	while ((ch = getopt(argc, argv, "ln")) != EOF) {
    119 		switch (ch) {
    120 		case 'l':
    121 			logging = 1;
    122 			break;
    123 		case 'n':
    124 			suppress_naks = 1;
    125 			break;
    126 		default:
    127 			syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
    128 		}
    129 	}
    130 	if (optind < argc) {
    131 		struct dirlist *dirp;
    132 
    133 		/* Get list of directory prefixes. Skip relative pathnames. */
    134 		for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];
    135 		     optind++) {
    136 			if (argv[optind][0] == '/') {
    137 				dirp->name = argv[optind];
    138 				dirp->len  = strlen(dirp->name);
    139 				dirp++;
    140 			}
    141 		}
    142 	}
    143 
    144 	on = 1;
    145 	if (ioctl(0, FIONBIO, &on) < 0) {
    146 		syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
    147 		exit(1);
    148 	}
    149 	fromlen = sizeof (from);
    150 	n = recvfrom(0, buf, sizeof (buf), 0,
    151 	    (struct sockaddr *)&from, &fromlen);
    152 	if (n < 0) {
    153 		syslog(LOG_ERR, "recvfrom: %m\n");
    154 		exit(1);
    155 	}
    156 	/*
    157 	 * Now that we have read the message out of the UDP
    158 	 * socket, we fork and exit.  Thus, inetd will go back
    159 	 * to listening to the tftp port, and the next request
    160 	 * to come in will start up a new instance of tftpd.
    161 	 *
    162 	 * We do this so that inetd can run tftpd in "wait" mode.
    163 	 * The problem with tftpd running in "nowait" mode is that
    164 	 * inetd may get one or more successful "selects" on the
    165 	 * tftp port before we do our receive, so more than one
    166 	 * instance of tftpd may be started up.  Worse, if tftpd
    167 	 * break before doing the above "recvfrom", inetd would
    168 	 * spawn endless instances, clogging the system.
    169 	 */
    170 	{
    171 		int pid;
    172 		int i, j;
    173 
    174 		for (i = 1; i < 20; i++) {
    175 		    pid = fork();
    176 		    if (pid < 0) {
    177 				sleep(i);
    178 				/*
    179 				 * flush out to most recently sent request.
    180 				 *
    181 				 * This may drop some request, but those
    182 				 * will be resent by the clients when
    183 				 * they timeout.  The positive effect of
    184 				 * this flush is to (try to) prevent more
    185 				 * than one tftpd being started up to service
    186 				 * a single request from a single client.
    187 				 */
    188 				j = sizeof from;
    189 				i = recvfrom(0, buf, sizeof (buf), 0,
    190 				    (struct sockaddr *)&from, &j);
    191 				if (i > 0) {
    192 					n = i;
    193 					fromlen = j;
    194 				}
    195 		    } else {
    196 				break;
    197 		    }
    198 		}
    199 		if (pid < 0) {
    200 			syslog(LOG_ERR, "fork: %m\n");
    201 			exit(1);
    202 		} else if (pid != 0) {
    203 			exit(0);
    204 		}
    205 	}
    206 	from.sin_family = AF_INET;
    207 	alarm(0);
    208 	close(0);
    209 	close(1);
    210 	peer = socket(AF_INET, SOCK_DGRAM, 0);
    211 	if (peer < 0) {
    212 		syslog(LOG_ERR, "socket: %m\n");
    213 		exit(1);
    214 	}
    215 	memset(&sin, 0, sizeof(sin));
    216 	sin.sin_family = AF_INET;
    217 	if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
    218 		syslog(LOG_ERR, "bind: %m\n");
    219 		exit(1);
    220 	}
    221 	if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {
    222 		syslog(LOG_ERR, "connect: %m\n");
    223 		exit(1);
    224 	}
    225 	tp = (struct tftphdr *)buf;
    226 	tp->th_opcode = ntohs(tp->th_opcode);
    227 	if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
    228 		tftp(tp, n);
    229 	exit(1);
    230 }
    231 
    232 struct formats;
    233 int	validate_access __P((char **, int));
    234 void	sendfile __P((struct formats *));
    235 void	recvfile __P((struct formats *));
    236 
    237 struct formats {
    238 	char	*f_mode;
    239 	int	(*f_validate) __P((char **, int));
    240 	void	(*f_send) __P((struct formats *));
    241 	void	(*f_recv) __P((struct formats *));
    242 	int	f_convert;
    243 } formats[] = {
    244 	{ "netascii",	validate_access,	sendfile,	recvfile, 1 },
    245 	{ "octet",	validate_access,	sendfile,	recvfile, 0 },
    246 #ifdef notdef
    247 	{ "mail",	validate_user,		sendmail,	recvmail, 1 },
    248 #endif
    249 	{ 0 }
    250 };
    251 
    252 /*
    253  * Handle initial connection protocol.
    254  */
    255 void
    256 tftp(tp, size)
    257 	struct tftphdr *tp;
    258 	int size;
    259 {
    260 	register char *cp;
    261 	int first = 1, ecode;
    262 	register struct formats *pf;
    263 	char *filename, *mode;
    264 
    265 	filename = cp = tp->th_stuff;
    266 again:
    267 	while (cp < buf + size) {
    268 		if (*cp == '\0')
    269 			break;
    270 		cp++;
    271 	}
    272 	if (*cp != '\0') {
    273 		nak(EBADOP);
    274 		exit(1);
    275 	}
    276 	if (first) {
    277 		mode = ++cp;
    278 		first = 0;
    279 		goto again;
    280 	}
    281 	for (cp = mode; *cp; cp++)
    282 		if (isupper(*cp))
    283 			*cp = tolower(*cp);
    284 	for (pf = formats; pf->f_mode; pf++)
    285 		if (strcmp(pf->f_mode, mode) == 0)
    286 			break;
    287 	if (pf->f_mode == 0) {
    288 		nak(EBADOP);
    289 		exit(1);
    290 	}
    291 	ecode = (*pf->f_validate)(&filename, tp->th_opcode);
    292 	if (logging) {
    293 		syslog(LOG_INFO, "%s: %s request for %s: %s",
    294 			verifyhost(&from),
    295 			tp->th_opcode == WRQ ? "write" : "read",
    296 			filename, errtomsg(ecode));
    297 	}
    298 	if (ecode) {
    299 		/*
    300 		 * Avoid storms of naks to a RRQ broadcast for a relative
    301 		 * bootfile pathname from a diskless Sun.
    302 		 */
    303 		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
    304 			exit(0);
    305 		nak(ecode);
    306 		exit(1);
    307 	}
    308 	if (tp->th_opcode == WRQ)
    309 		(*pf->f_recv)(pf);
    310 	else
    311 		(*pf->f_send)(pf);
    312 	exit(0);
    313 }
    314 
    315 
    316 FILE *file;
    317 
    318 /*
    319  * Validate file access.  Since we
    320  * have no uid or gid, for now require
    321  * file to exist and be publicly
    322  * readable/writable.
    323  * If we were invoked with arguments
    324  * from inetd then the file must also be
    325  * in one of the given directory prefixes.
    326  * Note also, full path name must be
    327  * given as we have no login directory.
    328  */
    329 int
    330 validate_access(filep, mode)
    331 	char **filep;
    332 	int mode;
    333 {
    334 	struct stat stbuf;
    335 	int	fd;
    336 	struct dirlist *dirp;
    337 	static char pathname[MAXPATHLEN];
    338 	char *filename = *filep;
    339 
    340 	/*
    341 	 * Prevent tricksters from getting around the directory restrictions
    342 	 */
    343 	if (strstr(filename, "/../"))
    344 		return (EACCESS);
    345 
    346 	if (*filename == '/') {
    347 		/*
    348 		 * Allow the request if it's in one of the approved locations.
    349 		 * Special case: check the null prefix ("/") by looking
    350 		 * for length = 1 and relying on the arg. processing that
    351 		 * it's a /.
    352 		 */
    353 		for (dirp = dirs; dirp->name != NULL; dirp++) {
    354 			if (dirp->len == 1 ||
    355 			    (!strncmp(filename, dirp->name, dirp->len) &&
    356 			     filename[dirp->len] == '/'))
    357 				    break;
    358 		}
    359 		/* If directory list is empty, allow access to any file */
    360 		if (dirp->name == NULL && dirp != dirs)
    361 			return (EACCESS);
    362 		if (stat(filename, &stbuf) < 0)
    363 			return (errno == ENOENT ? ENOTFOUND : EACCESS);
    364 		if ((stbuf.st_mode & S_IFMT) != S_IFREG)
    365 			return (ENOTFOUND);
    366 		if (mode == RRQ) {
    367 			if ((stbuf.st_mode & S_IROTH) == 0)
    368 				return (EACCESS);
    369 		} else {
    370 			if ((stbuf.st_mode & S_IWOTH) == 0)
    371 				return (EACCESS);
    372 		}
    373 	} else {
    374 		int err;
    375 
    376 		/*
    377 		 * Relative file name: search the approved locations for it.
    378 		 * Don't allow write requests or ones that avoid directory
    379 		 * restrictions.
    380 		 */
    381 
    382 		if (mode != RRQ || !strncmp(filename, "../", 3))
    383 			return (EACCESS);
    384 
    385 		/*
    386 		 * If the file exists in one of the directories and isn't
    387 		 * readable, continue looking. However, change the error code
    388 		 * to give an indication that the file exists.
    389 		 */
    390 		err = ENOTFOUND;
    391 		for (dirp = dirs; dirp->name != NULL; dirp++) {
    392 			sprintf(pathname, "%s/%s", dirp->name, filename);
    393 			if (stat(pathname, &stbuf) == 0 &&
    394 			    (stbuf.st_mode & S_IFMT) == S_IFREG) {
    395 				if ((stbuf.st_mode & S_IROTH) != 0) {
    396 					break;
    397 				}
    398 				err = EACCESS;
    399 			}
    400 		}
    401 		if (dirp->name == NULL)
    402 			return (err);
    403 		*filep = filename = pathname;
    404 	}
    405 	fd = open(filename, mode == RRQ ? 0 : 1);
    406 	if (fd < 0)
    407 		return (errno + 100);
    408 	file = fdopen(fd, (mode == RRQ)? "r":"w");
    409 	if (file == NULL) {
    410 		return errno+100;
    411 	}
    412 	return (0);
    413 }
    414 
    415 int	timeout;
    416 jmp_buf	timeoutbuf;
    417 
    418 void
    419 timer()
    420 {
    421 
    422 	timeout += rexmtval;
    423 	if (timeout >= maxtimeout)
    424 		exit(1);
    425 	longjmp(timeoutbuf, 1);
    426 }
    427 
    428 /*
    429  * Send the requested file.
    430  */
    431 void
    432 sendfile(pf)
    433 	struct formats *pf;
    434 {
    435 	struct tftphdr *dp, *r_init();
    436 	register struct tftphdr *ap;    /* ack packet */
    437 	register int size, n;
    438 	volatile int block;
    439 
    440 	signal(SIGALRM, timer);
    441 	dp = r_init();
    442 	ap = (struct tftphdr *)ackbuf;
    443 	block = 1;
    444 	do {
    445 		size = readit(file, &dp, pf->f_convert);
    446 		if (size < 0) {
    447 			nak(errno + 100);
    448 			goto abort;
    449 		}
    450 		dp->th_opcode = htons((u_short)DATA);
    451 		dp->th_block = htons((u_short)block);
    452 		timeout = 0;
    453 		(void)setjmp(timeoutbuf);
    454 
    455 send_data:
    456 		if (send(peer, dp, size + 4, 0) != size + 4) {
    457 			syslog(LOG_ERR, "tftpd: write: %m\n");
    458 			goto abort;
    459 		}
    460 		read_ahead(file, pf->f_convert);
    461 		for ( ; ; ) {
    462 			alarm(rexmtval);        /* read the ack */
    463 			n = recv(peer, ackbuf, sizeof (ackbuf), 0);
    464 			alarm(0);
    465 			if (n < 0) {
    466 				syslog(LOG_ERR, "tftpd: read: %m\n");
    467 				goto abort;
    468 			}
    469 			ap->th_opcode = ntohs((u_short)ap->th_opcode);
    470 			ap->th_block = ntohs((u_short)ap->th_block);
    471 
    472 			if (ap->th_opcode == ERROR)
    473 				goto abort;
    474 
    475 			if (ap->th_opcode == ACK) {
    476 				if (ap->th_block == block)
    477 					break;
    478 				/* Re-synchronize with the other side */
    479 				(void) synchnet(peer);
    480 				if (ap->th_block == (block -1))
    481 					goto send_data;
    482 			}
    483 
    484 		}
    485 		block++;
    486 	} while (size == SEGSIZE);
    487 abort:
    488 	(void) fclose(file);
    489 }
    490 
    491 void
    492 justquit()
    493 {
    494 	exit(0);
    495 }
    496 
    497 
    498 /*
    499  * Receive a file.
    500  */
    501 void
    502 recvfile(pf)
    503 	struct formats *pf;
    504 {
    505 	struct tftphdr *dp, *w_init();
    506 	register struct tftphdr *ap;    /* ack buffer */
    507 	register int n, size;
    508 	volatile int block;
    509 
    510 	signal(SIGALRM, timer);
    511 	dp = w_init();
    512 	ap = (struct tftphdr *)ackbuf;
    513 	block = 0;
    514 	do {
    515 		timeout = 0;
    516 		ap->th_opcode = htons((u_short)ACK);
    517 		ap->th_block = htons((u_short)block);
    518 		block++;
    519 		(void) setjmp(timeoutbuf);
    520 send_ack:
    521 		if (send(peer, ackbuf, 4, 0) != 4) {
    522 			syslog(LOG_ERR, "tftpd: write: %m\n");
    523 			goto abort;
    524 		}
    525 		write_behind(file, pf->f_convert);
    526 		for ( ; ; ) {
    527 			alarm(rexmtval);
    528 			n = recv(peer, dp, PKTSIZE, 0);
    529 			alarm(0);
    530 			if (n < 0) {            /* really? */
    531 				syslog(LOG_ERR, "tftpd: read: %m\n");
    532 				goto abort;
    533 			}
    534 			dp->th_opcode = ntohs((u_short)dp->th_opcode);
    535 			dp->th_block = ntohs((u_short)dp->th_block);
    536 			if (dp->th_opcode == ERROR)
    537 				goto abort;
    538 			if (dp->th_opcode == DATA) {
    539 				if (dp->th_block == block) {
    540 					break;   /* normal */
    541 				}
    542 				/* Re-synchronize with the other side */
    543 				(void) synchnet(peer);
    544 				if (dp->th_block == (block-1))
    545 					goto send_ack;          /* rexmit */
    546 			}
    547 		}
    548 		/*  size = write(file, dp->th_data, n - 4); */
    549 		size = writeit(file, &dp, n - 4, pf->f_convert);
    550 		if (size != (n-4)) {                    /* ahem */
    551 			if (size < 0) nak(errno + 100);
    552 			else nak(ENOSPACE);
    553 			goto abort;
    554 		}
    555 	} while (size == SEGSIZE);
    556 	write_behind(file, pf->f_convert);
    557 	(void) fclose(file);            /* close data file */
    558 
    559 	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */
    560 	ap->th_block = htons((u_short)(block));
    561 	(void) send(peer, ackbuf, 4, 0);
    562 
    563 	signal(SIGALRM, justquit);      /* just quit on timeout */
    564 	alarm(rexmtval);
    565 	n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
    566 	alarm(0);
    567 	if (n >= 4 &&                   /* if read some data */
    568 	    dp->th_opcode == DATA &&    /* and got a data block */
    569 	    block == dp->th_block) {	/* then my last ack was lost */
    570 		(void) send(peer, ackbuf, 4, 0);     /* resend final ack */
    571 	}
    572 abort:
    573 	return;
    574 }
    575 
    576 struct errmsg {
    577 	int	e_code;
    578 	char	*e_msg;
    579 } errmsgs[] = {
    580 	{ EUNDEF,	"Undefined error code" },
    581 	{ ENOTFOUND,	"File not found" },
    582 	{ EACCESS,	"Access violation" },
    583 	{ ENOSPACE,	"Disk full or allocation exceeded" },
    584 	{ EBADOP,	"Illegal TFTP operation" },
    585 	{ EBADID,	"Unknown transfer ID" },
    586 	{ EEXISTS,	"File already exists" },
    587 	{ ENOUSER,	"No such user" },
    588 	{ -1,		0 }
    589 };
    590 
    591 static char *
    592 errtomsg(error)
    593 	int error;
    594 {
    595 	static char buf[20];
    596 	register struct errmsg *pe;
    597 	if (error == 0)
    598 		return "success";
    599 	for (pe = errmsgs; pe->e_code >= 0; pe++)
    600 		if (pe->e_code == error)
    601 			return pe->e_msg;
    602 	sprintf(buf, "error %d", error);
    603 	return buf;
    604 }
    605 
    606 /*
    607  * Send a nak packet (error message).
    608  * Error code passed in is one of the
    609  * standard TFTP codes, or a UNIX errno
    610  * offset by 100.
    611  */
    612 static void
    613 nak(error)
    614 	int error;
    615 {
    616 	register struct tftphdr *tp;
    617 	int length;
    618 	register struct errmsg *pe;
    619 
    620 	tp = (struct tftphdr *)buf;
    621 	tp->th_opcode = htons((u_short)ERROR);
    622 	tp->th_code = htons((u_short)error);
    623 	for (pe = errmsgs; pe->e_code >= 0; pe++)
    624 		if (pe->e_code == error)
    625 			break;
    626 	if (pe->e_code < 0) {
    627 		pe->e_msg = strerror(error - 100);
    628 		tp->th_code = EUNDEF;   /* set 'undef' errorcode */
    629 	}
    630 	strcpy(tp->th_msg, pe->e_msg);
    631 	length = strlen(pe->e_msg);
    632 	tp->th_msg[length] = '\0';
    633 	length += 5;
    634 	if (send(peer, buf, length, 0) != length)
    635 		syslog(LOG_ERR, "nak: %m\n");
    636 }
    637 
    638 static char *
    639 verifyhost(fromp)
    640 	struct sockaddr_in *fromp;
    641 {
    642 	struct hostent *hp;
    643 
    644 	hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (fromp->sin_addr),
    645 			    fromp->sin_family);
    646 	if (hp)
    647 		return hp->h_name;
    648 	else
    649 		return inet_ntoa(fromp->sin_addr);
    650 }
    651