1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * 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 char copyright[] = 36 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 /*static char sccsid[] = "from: @(#)tftpd.c 5.13 (Berkeley) 2/26/91";*/ 42 /*static char rcsid[] = "$Id: tftpd.c,v 1.3 1993/08/01 18:28:53 mycroft Exp $";*/ 43 #endif /* not lint */ 44 45 /* 46 * Trivial file transfer protocol server. 47 * 48 * This version includes many modifications by Jim Guyton <guyton@rand-unix> 49 */ 50 51 #include <sys/types.h> 52 #include <sys/ioctl.h> 53 #include <sys/stat.h> 54 #include <unistd.h> 55 #include <signal.h> 56 #include <fcntl.h> 57 58 #include <sys/socket.h> 59 #include <netinet/in.h> 60 #include <netdb.h> 61 62 #include <setjmp.h> 63 #include <syslog.h> 64 #include <stdio.h> 65 #include <errno.h> 66 #include <ctype.h> 67 #include <string.h> 68 #include <stdlib.h> 69 70 #include "tftp.h" 71 72 #ifndef MSG_CONFIRM 73 #define MSG_CONFIRM 0 74 #warning Please, upgrade kernel, otherwise this tftpd has no advantages. 75 #endif 76 77 #define TIMEOUT 5 78 79 int peer; 80 int rexmtval = TIMEOUT; 81 int maxtimeout = 5*TIMEOUT; 82 83 #define PKTSIZE SEGSIZE+4 84 char buf[PKTSIZE]; 85 char ackbuf[PKTSIZE]; 86 union { 87 struct sockaddr sa; 88 struct sockaddr_in sin; 89 struct sockaddr_in6 sin6; 90 } from; 91 socklen_t fromlen; 92 93 #define MAXARG 1 94 char *dirs[MAXARG+1]; 95 96 void tftp(struct tftphdr *tp, int size) __attribute__((noreturn)); 97 void nak(int error); 98 int validate_access(char *filename, int mode); 99 100 struct formats; 101 102 void sendfile(struct formats *pf); 103 void recvfile(struct formats *pf); 104 105 106 int main(int ac, char **av) 107 { 108 register struct tftphdr *tp; 109 register int n = 0; 110 int on = 1; 111 112 /* Sanity. If parent forgot to setuid() on us. */ 113 if (geteuid() == 0) { 114 setgid(65534); 115 setuid(65534); 116 } 117 118 ac--; av++; 119 while (ac-- > 0 && n < MAXARG) 120 dirs[n++] = *av++; 121 122 openlog("tftpd", LOG_PID, LOG_DAEMON); 123 if (ioctl(0, FIONBIO, &on) < 0) { 124 syslog(LOG_ERR, "ioctl(FIONBIO): %m\n"); 125 exit(1); 126 } 127 fromlen = sizeof (from); 128 n = recvfrom(0, buf, sizeof (buf), 0, 129 (struct sockaddr *)&from, &fromlen); 130 if (n < 0) { 131 if (errno != EAGAIN) 132 syslog(LOG_ERR, "recvfrom: %m\n"); 133 exit(1); 134 } 135 /* 136 * Now that we have read the message out of the UDP 137 * socket, we fork and exit. Thus, inetd will go back 138 * to listening to the tftp port, and the next request 139 * to come in will start up a new instance of tftpd. 140 * 141 * We do this so that inetd can run tftpd in "wait" mode. 142 * The problem with tftpd running in "nowait" mode is that 143 * inetd may get one or more successful "selects" on the 144 * tftp port before we do our receive, so more than one 145 * instance of tftpd may be started up. Worse, if tftpd 146 * break before doing the above "recvfrom", inetd would 147 * spawn endless instances, clogging the system. 148 */ 149 { 150 int pid; 151 int i; 152 socklen_t j; 153 154 for (i = 1; i < 20; i++) { 155 pid = fork(); 156 if (pid < 0) { 157 sleep(i); 158 /* 159 * flush out to most recently sent request. 160 * 161 * This may drop some request, but those 162 * will be resent by the clients when 163 * they timeout. The positive effect of 164 * this flush is to (try to) prevent more 165 * than one tftpd being started up to service 166 * a single request from a single client. 167 */ 168 j = sizeof from; 169 i = recvfrom(0, buf, sizeof (buf), 0, 170 (struct sockaddr *)&from, &j); 171 if (i > 0) { 172 n = i; 173 fromlen = j; 174 } 175 } else { 176 break; 177 } 178 } 179 if (pid < 0) { 180 syslog(LOG_ERR, "fork: %m\n"); 181 exit(1); 182 } else if (pid != 0) { 183 exit(0); 184 } 185 } 186 alarm(0); 187 close(0); 188 close(1); 189 peer = socket(from.sa.sa_family, SOCK_DGRAM, 0); 190 if (peer < 0) { 191 syslog(LOG_ERR, "socket: %m\n"); 192 exit(1); 193 } 194 if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) { 195 syslog(LOG_ERR, "connect: %m\n"); 196 exit(1); 197 } 198 tp = (struct tftphdr *)buf; 199 tp->th_opcode = ntohs(tp->th_opcode); 200 if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) 201 tftp(tp, n); 202 exit(1); 203 } 204 205 struct formats { 206 char *f_mode; 207 int (*f_validate)(char *filename, int mode); 208 void (*f_send)(struct formats*); 209 void (*f_recv)(struct formats*); 210 int f_convert; 211 } formats[] = { 212 { "netascii", validate_access, sendfile, recvfile, 1 }, 213 { "octet", validate_access, sendfile, recvfile, 0 }, 214 #ifdef notdef 215 { "mail", validate_user, sendmail, recvmail, 1 }, 216 #endif 217 { 0 } 218 }; 219 220 /* 221 * Handle initial connection protocol. 222 */ 223 void tftp(struct tftphdr *tp, int size) 224 { 225 register char *cp; 226 int first = 1, ecode; 227 register struct formats *pf; 228 char *filename, *mode = NULL; 229 230 filename = cp = tp->th_stuff; 231 again: 232 while (cp < buf + size) { 233 if (*cp == '\0') 234 break; 235 cp++; 236 } 237 if (*cp != '\0') { 238 nak(EBADOP); 239 exit(1); 240 } 241 if (first) { 242 mode = ++cp; 243 first = 0; 244 goto again; 245 } 246 for (cp = mode; *cp; cp++) 247 if (isupper(*cp)) 248 *cp = tolower(*cp); 249 for (pf = formats; pf->f_mode; pf++) 250 if (strcmp(pf->f_mode, mode) == 0) 251 break; 252 if (pf->f_mode == 0) { 253 nak(EBADOP); 254 exit(1); 255 } 256 ecode = (*pf->f_validate)(filename, tp->th_opcode); 257 if (ecode) { 258 nak(ecode); 259 exit(1); 260 } 261 if (tp->th_opcode == WRQ) 262 (*pf->f_recv)(pf); 263 else 264 (*pf->f_send)(pf); 265 exit(0); 266 } 267 268 269 FILE *file; 270 271 /* 272 * Validate file access. Since we 273 * have no uid or gid, for now require 274 * file to exist and be publicly 275 * readable/writable. 276 * If we were invoked with arguments 277 * from inetd then the file must also be 278 * in one of the given directory prefixes. 279 * Note also, full path name must be 280 * given as we have no login directory. 281 */ 282 int validate_access(char *filename, int mode) 283 { 284 struct stat stbuf; 285 int fd; 286 char *cp; 287 char fnamebuf[1024+512]; 288 289 for (cp = filename; *cp; cp++) { 290 if(*cp == '.' && (cp == filename || strncmp(cp-1, "/../", 4) == 0)) { 291 syslog(LOG_ERR, "bad path %s", filename); 292 return(EACCESS); 293 } 294 } 295 296 if (*filename == '/') 297 filename++; 298 299 if (!*dirs) { 300 syslog(LOG_ERR, "no dirs"); 301 return EACCESS; 302 } 303 snprintf(fnamebuf, sizeof(fnamebuf)-1, "%s/%s", *dirs, filename); 304 filename = fnamebuf; 305 306 if (stat(filename, &stbuf) < 0) { 307 syslog(LOG_ERR, "stat %s : %m", filename); 308 return (errno == ENOENT ? ENOTFOUND : EACCESS); 309 } 310 if (mode == RRQ) { 311 if ((stbuf.st_mode&(S_IREAD >> 6)) == 0) { 312 syslog(LOG_ERR, "not readable %s", filename); 313 return (EACCESS); 314 } 315 } else { 316 if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0) { 317 syslog(LOG_ERR, "not writable %s", filename); 318 return (EACCESS); 319 } 320 } 321 fd = open(filename, mode == RRQ ? 0 : 1); 322 if (fd < 0) { 323 syslog(LOG_ERR, "cannot open %s: %m", filename); 324 return (errno + 100); 325 } 326 file = fdopen(fd, (mode == RRQ)? "r":"w"); 327 if (file == NULL) { 328 return errno+100; 329 } 330 return (0); 331 } 332 333 int confirmed; 334 int timeout; 335 jmp_buf timeoutbuf; 336 337 void timer(int signo) 338 { 339 confirmed = 0; 340 timeout += rexmtval; 341 if (timeout >= maxtimeout) 342 exit(1); 343 longjmp(timeoutbuf, 1); 344 } 345 346 /* 347 * Send the requested file. 348 */ 349 void sendfile(struct formats *pf) 350 { 351 struct tftphdr *dp; 352 register struct tftphdr *ap; /* ack packet */ 353 volatile int block = 1; 354 int size, n; 355 356 confirmed = 0; 357 signal(SIGALRM, timer); 358 dp = r_init(); 359 ap = (struct tftphdr *)ackbuf; 360 do { 361 size = readit(file, &dp, pf->f_convert); 362 if (size < 0) { 363 nak(errno + 100); 364 goto abort; 365 } 366 dp->th_opcode = htons((u_short)DATA); 367 dp->th_block = htons((u_short)block); 368 timeout = 0; 369 (void) setjmp(timeoutbuf); 370 371 send_data: 372 if (send(peer, dp, size + 4, confirmed) != size + 4) { 373 syslog(LOG_ERR, "tftpd: write: %m\n"); 374 goto abort; 375 } 376 confirmed = 0; 377 read_ahead(file, pf->f_convert); 378 for ( ; ; ) { 379 alarm(rexmtval); /* read the ack */ 380 n = recv(peer, ackbuf, sizeof (ackbuf), 0); 381 alarm(0); 382 if (n < 0) { 383 syslog(LOG_ERR, "tftpd: read: %m\n"); 384 goto abort; 385 } 386 ap->th_opcode = ntohs((u_short)ap->th_opcode); 387 ap->th_block = ntohs((u_short)ap->th_block); 388 389 if (ap->th_opcode == ERROR) 390 goto abort; 391 392 if (ap->th_opcode == ACK) { 393 if (ap->th_block == block) { 394 confirmed = MSG_CONFIRM; 395 break; 396 } 397 /* Re-synchronize with the other side */ 398 synchnet(peer); 399 if (ap->th_block == (block -1)) { 400 goto send_data; 401 } 402 } 403 404 } 405 block++; 406 } while (size == SEGSIZE); 407 abort: 408 (void) fclose(file); 409 } 410 411 void justquit(int signo) 412 { 413 exit(0); 414 } 415 416 417 /* 418 * Receive a file. 419 */ 420 void recvfile(struct formats *pf) 421 { 422 struct tftphdr *dp; 423 register struct tftphdr *ap; /* ack buffer */ 424 volatile int block = 0, n, size; 425 426 confirmed = 0; 427 signal(SIGALRM, timer); 428 dp = w_init(); 429 ap = (struct tftphdr *)ackbuf; 430 do { 431 timeout = 0; 432 ap->th_opcode = htons((u_short)ACK); 433 ap->th_block = htons((u_short)block); 434 block++; 435 (void) setjmp(timeoutbuf); 436 send_ack: 437 if (send(peer, ackbuf, 4, confirmed) != 4) { 438 syslog(LOG_ERR, "tftpd: write: %m\n"); 439 goto abort; 440 } 441 confirmed = 0; 442 write_behind(file, pf->f_convert); 443 for ( ; ; ) { 444 alarm(rexmtval); 445 n = recv(peer, dp, PKTSIZE, 0); 446 alarm(0); 447 if (n < 0) { /* really? */ 448 syslog(LOG_ERR, "tftpd: read: %m\n"); 449 goto abort; 450 } 451 dp->th_opcode = ntohs((u_short)dp->th_opcode); 452 dp->th_block = ntohs((u_short)dp->th_block); 453 if (dp->th_opcode == ERROR) 454 goto abort; 455 if (dp->th_opcode == DATA) { 456 if (dp->th_block == block) { 457 confirmed = MSG_CONFIRM; 458 break; /* normal */ 459 } 460 /* Re-synchronize with the other side */ 461 (void) synchnet(peer); 462 if (dp->th_block == (block-1)) 463 goto send_ack; /* rexmit */ 464 } 465 } 466 /* size = write(file, dp->th_data, n - 4); */ 467 size = writeit(file, &dp, n - 4, pf->f_convert); 468 if (size != (n-4)) { /* ahem */ 469 if (size < 0) nak(errno + 100); 470 else nak(ENOSPACE); 471 goto abort; 472 } 473 } while (size == SEGSIZE); 474 write_behind(file, pf->f_convert); 475 (void) fclose(file); /* close data file */ 476 477 ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */ 478 ap->th_block = htons((u_short)(block)); 479 (void) send(peer, ackbuf, 4, confirmed); 480 481 signal(SIGALRM, justquit); /* just quit on timeout */ 482 alarm(rexmtval); 483 n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */ 484 alarm(0); 485 if (n >= 4 && /* if read some data */ 486 dp->th_opcode == DATA && /* and got a data block */ 487 block == dp->th_block) { /* then my last ack was lost */ 488 (void) send(peer, ackbuf, 4, 0); /* resend final ack */ 489 } 490 abort: 491 return; 492 } 493 494 struct errmsg { 495 int e_code; 496 char *e_msg; 497 } errmsgs[] = { 498 { EUNDEF, "Undefined error code" }, 499 { ENOTFOUND, "File not found" }, 500 { EACCESS, "Access violation" }, 501 { ENOSPACE, "Disk full or allocation exceeded" }, 502 { EBADOP, "Illegal TFTP operation" }, 503 { EBADID, "Unknown transfer ID" }, 504 { EEXISTS, "File already exists" }, 505 { ENOUSER, "No such user" }, 506 { -1, 0 } 507 }; 508 509 /* 510 * Send a nak packet (error message). 511 * Error code passed in is one of the 512 * standard TFTP codes, or a UNIX errno 513 * offset by 100. 514 */ 515 void nak(int error) 516 { 517 register struct tftphdr *tp; 518 int length; 519 register struct errmsg *pe; 520 521 tp = (struct tftphdr *)buf; 522 tp->th_opcode = htons((u_short)ERROR); 523 tp->th_code = htons((u_short)error); 524 for (pe = errmsgs; pe->e_code >= 0; pe++) 525 if (pe->e_code == error) 526 break; 527 if (pe->e_code < 0) { 528 pe->e_msg = strerror(error - 100); 529 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 530 } 531 strcpy(tp->th_msg, pe->e_msg); 532 length = strlen(pe->e_msg); 533 tp->th_msg[length] = '\0'; 534 length += 5; 535 if (send(peer, buf, length, 0) != length) 536 syslog(LOG_ERR, "nak: %m\n"); 537 } 538