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