1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 dated June, 1991, or 6 (at your option) version 3 dated 29 June, 2007. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include "dnsmasq.h" 18 19 #ifdef HAVE_TFTP 20 21 static struct tftp_file *check_tftp_fileperm(ssize_t *len); 22 static void free_transfer(struct tftp_transfer *transfer); 23 static ssize_t tftp_err(int err, char *packet, char *mess, char *file); 24 static ssize_t tftp_err_oops(char *packet, char *file); 25 static ssize_t get_block(char *packet, struct tftp_transfer *transfer); 26 static char *next(char **p, char *end); 27 28 #define OP_RRQ 1 29 #define OP_WRQ 2 30 #define OP_DATA 3 31 #define OP_ACK 4 32 #define OP_ERR 5 33 #define OP_OACK 6 34 35 #define ERR_NOTDEF 0 36 #define ERR_FNF 1 37 #define ERR_PERM 2 38 #define ERR_FULL 3 39 #define ERR_ILL 4 40 41 void tftp_request(struct listener *listen, time_t now) 42 { 43 ssize_t len; 44 char *packet = daemon->packet; 45 char *filename, *mode, *p, *end, *opt; 46 struct sockaddr_in addr, peer; 47 struct msghdr msg; 48 struct iovec iov; 49 struct ifreq ifr; 50 int is_err = 1, if_index = 0, mtu = 0; 51 struct iname *tmp; 52 struct tftp_transfer *transfer; 53 int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */ 54 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 55 int mtuflag = IP_PMTUDISC_DONT; 56 #endif 57 58 union { 59 struct cmsghdr align; /* this ensures alignment */ 60 #if defined(HAVE_LINUX_NETWORK) 61 char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; 62 #elif defined(HAVE_SOLARIS_NETWORK) 63 char control[CMSG_SPACE(sizeof(unsigned int))]; 64 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) 65 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))]; 66 #endif 67 } control_u; 68 69 msg.msg_controllen = sizeof(control_u); 70 msg.msg_control = control_u.control; 71 msg.msg_flags = 0; 72 msg.msg_name = &peer; 73 msg.msg_namelen = sizeof(peer); 74 msg.msg_iov = &iov; 75 msg.msg_iovlen = 1; 76 77 iov.iov_base = packet; 78 iov.iov_len = daemon->packet_buff_sz; 79 80 /* we overwrote the buffer... */ 81 daemon->srv_save = NULL; 82 83 if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) 84 return; 85 86 if (daemon->options & OPT_NOWILD) 87 { 88 addr = listen->iface->addr.in; 89 mtu = listen->iface->mtu; 90 } 91 else 92 { 93 char name[IF_NAMESIZE]; 94 struct cmsghdr *cmptr; 95 96 addr.sin_addr.s_addr = 0; 97 98 #if defined(HAVE_LINUX_NETWORK) 99 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 100 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) 101 { 102 addr.sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst; 103 if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex; 104 } 105 106 #elif defined(HAVE_SOLARIS_NETWORK) 107 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 108 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) 109 addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr)); 110 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) 111 if_index = *((unsigned int *)CMSG_DATA(cmptr)); 112 113 114 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) 115 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 116 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) 117 addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr)); 118 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) 119 if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index; 120 121 #endif 122 123 if (!indextoname(listen->tftpfd, if_index, name) || 124 addr.sin_addr.s_addr == 0 || 125 !iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index)) 126 return; 127 128 /* allowed interfaces are the same as for DHCP */ 129 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) 130 if (tmp->name && (strcmp(tmp->name, name) == 0)) 131 return; 132 133 strncpy(name, ifr.ifr_name, IF_NAMESIZE); 134 if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1) 135 mtu = ifr.ifr_mtu; 136 } 137 138 addr.sin_port = htons(port); 139 addr.sin_family = AF_INET; 140 #ifdef HAVE_SOCKADDR_SA_LEN 141 addr.sin_len = sizeof(addr); 142 #endif 143 144 if (!(transfer = whine_malloc(sizeof(struct tftp_transfer)))) 145 return; 146 147 if ((transfer->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 148 { 149 free(transfer); 150 return; 151 } 152 153 transfer->peer = peer; 154 transfer->timeout = now + 2; 155 transfer->backoff = 1; 156 transfer->block = 1; 157 transfer->blocksize = 512; 158 transfer->offset = 0; 159 transfer->file = NULL; 160 transfer->opt_blocksize = transfer->opt_transize = 0; 161 transfer->netascii = transfer->carrylf = 0; 162 163 /* if we have a nailed-down range, iterate until we find a free one. */ 164 while (1) 165 { 166 if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 || 167 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 168 setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 || 169 #endif 170 !fix_fd(transfer->sockfd)) 171 { 172 if (errno == EADDRINUSE && daemon->start_tftp_port != 0) 173 { 174 if (++port <= daemon->end_tftp_port) 175 { 176 addr.sin_port = htons(port); 177 continue; 178 } 179 my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP")); 180 } 181 free_transfer(transfer); 182 return; 183 } 184 break; 185 } 186 187 p = packet + 2; 188 end = packet + len; 189 190 if (ntohs(*((unsigned short *)packet)) != OP_RRQ || 191 !(filename = next(&p, end)) || 192 !(mode = next(&p, end)) || 193 (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0)) 194 len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), inet_ntoa(peer.sin_addr)); 195 else 196 { 197 if (strcasecmp(mode, "netascii") == 0) 198 transfer->netascii = 1; 199 200 while ((opt = next(&p, end))) 201 { 202 if (strcasecmp(opt, "blksize") == 0) 203 { 204 if ((opt = next(&p, end)) && 205 !(daemon->options & OPT_TFTP_NOBLOCK)) 206 { 207 transfer->blocksize = atoi(opt); 208 if (transfer->blocksize < 1) 209 transfer->blocksize = 1; 210 if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4) 211 transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4; 212 /* 32 bytes for IP, UDP and TFTP headers */ 213 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32) 214 transfer->blocksize = (unsigned)mtu - 32; 215 transfer->opt_blocksize = 1; 216 transfer->block = 0; 217 } 218 } 219 else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii) 220 { 221 transfer->opt_transize = 1; 222 transfer->block = 0; 223 } 224 } 225 226 /* cope with backslashes from windows boxen. */ 227 while ((p = strchr(filename, '\\'))) 228 *p = '/'; 229 230 strcpy(daemon->namebuff, "/"); 231 if (daemon->tftp_prefix) 232 { 233 if (daemon->tftp_prefix[0] == '/') 234 daemon->namebuff[0] = 0; 235 strncat(daemon->namebuff, daemon->tftp_prefix, (MAXDNAME-1) - strlen(daemon->namebuff)); 236 if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/') 237 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff)); 238 239 if (daemon->options & OPT_TFTP_APREF) 240 { 241 size_t oldlen = strlen(daemon->namebuff); 242 struct stat statbuf; 243 244 strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), (MAXDNAME-1) - strlen(daemon->namebuff)); 245 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff)); 246 247 /* remove unique-directory if it doesn't exist */ 248 if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode)) 249 daemon->namebuff[oldlen] = 0; 250 } 251 252 /* Absolute pathnames OK if they match prefix */ 253 if (filename[0] == '/') 254 { 255 if (strstr(filename, daemon->namebuff) == filename) 256 daemon->namebuff[0] = 0; 257 else 258 filename++; 259 } 260 } 261 else if (filename[0] == '/') 262 daemon->namebuff[0] = 0; 263 strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff)); 264 265 /* check permissions and open file */ 266 if ((transfer->file = check_tftp_fileperm(&len))) 267 { 268 if ((len = get_block(packet, transfer)) == -1) 269 len = tftp_err_oops(packet, daemon->namebuff); 270 else 271 is_err = 0; 272 } 273 } 274 275 while (sendto(transfer->sockfd, packet, len, 0, 276 (struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR); 277 278 if (is_err) 279 free_transfer(transfer); 280 else 281 { 282 my_syslog(MS_TFTP | LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr)); 283 transfer->next = daemon->tftp_trans; 284 daemon->tftp_trans = transfer; 285 } 286 } 287 288 static struct tftp_file *check_tftp_fileperm(ssize_t *len) 289 { 290 char *packet = daemon->packet, *namebuff = daemon->namebuff; 291 struct tftp_file *file; 292 struct tftp_transfer *t; 293 uid_t uid = geteuid(); 294 struct stat statbuf; 295 int fd = -1; 296 297 /* trick to ban moving out of the subtree */ 298 if (daemon->tftp_prefix && strstr(namebuff, "/../")) 299 goto perm; 300 301 if ((fd = open(namebuff, O_RDONLY)) == -1) 302 { 303 if (errno == ENOENT) 304 { 305 *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff); 306 return NULL; 307 } 308 else if (errno == EACCES) 309 goto perm; 310 else 311 goto oops; 312 } 313 314 /* stat the file descriptor to avoid stat->open races */ 315 if (fstat(fd, &statbuf) == -1) 316 goto oops; 317 318 /* running as root, must be world-readable */ 319 if (uid == 0) 320 { 321 if (!(statbuf.st_mode & S_IROTH)) 322 goto perm; 323 } 324 /* in secure mode, must be owned by user running dnsmasq */ 325 else if ((daemon->options & OPT_TFTP_SECURE) && uid != statbuf.st_uid) 326 goto perm; 327 328 /* If we're doing many tranfers from the same file, only 329 open it once this saves lots of file descriptors 330 when mass-booting a big cluster, for instance. 331 Be conservative and only share when inode and name match 332 this keeps error messages sane. */ 333 for (t = daemon->tftp_trans; t; t = t->next) 334 if (t->file->dev == statbuf.st_dev && 335 t->file->inode == statbuf.st_ino && 336 strcmp(t->file->filename, namebuff) == 0) 337 { 338 close(fd); 339 t->file->refcount++; 340 return t->file; 341 } 342 343 if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1))) 344 { 345 errno = ENOMEM; 346 goto oops; 347 } 348 349 file->fd = fd; 350 file->size = statbuf.st_size; 351 file->dev = statbuf.st_dev; 352 file->inode = statbuf.st_ino; 353 file->refcount = 1; 354 strcpy(file->filename, namebuff); 355 return file; 356 357 perm: 358 errno = EACCES; 359 *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff); 360 if (fd != -1) 361 close(fd); 362 return NULL; 363 364 oops: 365 *len = tftp_err_oops(packet, namebuff); 366 if (fd != -1) 367 close(fd); 368 return NULL; 369 } 370 371 void check_tftp_listeners(fd_set *rset, time_t now) 372 { 373 struct tftp_transfer *transfer, *tmp, **up; 374 ssize_t len; 375 376 struct ack { 377 unsigned short op, block; 378 } *mess = (struct ack *)daemon->packet; 379 380 /* Check for activity on any existing transfers */ 381 for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp) 382 { 383 tmp = transfer->next; 384 385 if (FD_ISSET(transfer->sockfd, rset)) 386 { 387 /* we overwrote the buffer... */ 388 daemon->srv_save = NULL; 389 390 if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack)) 391 { 392 if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block) 393 { 394 /* Got ack, ensure we take the (re)transmit path */ 395 transfer->timeout = now; 396 transfer->backoff = 0; 397 if (transfer->block++ != 0) 398 transfer->offset += transfer->blocksize - transfer->expansion; 399 } 400 else if (ntohs(mess->op) == OP_ERR) 401 { 402 char *p = daemon->packet + sizeof(struct ack); 403 char *end = daemon->packet + len; 404 char *err = next(&p, end); 405 /* Sanitise error message */ 406 if (!err) 407 err = ""; 408 else 409 { 410 char *q, *r; 411 for (q = r = err; *r; r++) 412 if (isprint((int)*r)) 413 *(q++) = *r; 414 *q = 0; 415 } 416 my_syslog(MS_TFTP | LOG_ERR, _("TFTP error %d %s received from %s"), 417 (int)ntohs(mess->block), err, 418 inet_ntoa(transfer->peer.sin_addr)); 419 420 /* Got err, ensure we take abort */ 421 transfer->timeout = now; 422 transfer->backoff = 100; 423 } 424 } 425 } 426 427 if (difftime(now, transfer->timeout) >= 0.0) 428 { 429 int endcon = 0; 430 431 /* timeout, retransmit */ 432 transfer->timeout += 1 + (1<<transfer->backoff); 433 434 /* we overwrote the buffer... */ 435 daemon->srv_save = NULL; 436 437 if ((len = get_block(daemon->packet, transfer)) == -1) 438 { 439 len = tftp_err_oops(daemon->packet, transfer->file->filename); 440 endcon = 1; 441 } 442 else if (++transfer->backoff > 5) 443 { 444 /* don't complain about timeout when we're awaiting the last 445 ACK, some clients never send it */ 446 if (len != 0) 447 my_syslog(MS_TFTP | LOG_ERR, _("TFTP failed sending %s to %s"), 448 transfer->file->filename, inet_ntoa(transfer->peer.sin_addr)); 449 len = 0; 450 } 451 452 if (len != 0) 453 while(sendto(transfer->sockfd, daemon->packet, len, 0, 454 (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR); 455 456 if (endcon || len == 0) 457 { 458 /* unlink */ 459 *up = tmp; 460 free_transfer(transfer); 461 continue; 462 } 463 } 464 465 up = &transfer->next; 466 } 467 } 468 469 static void free_transfer(struct tftp_transfer *transfer) 470 { 471 close(transfer->sockfd); 472 if (transfer->file && (--transfer->file->refcount) == 0) 473 { 474 close(transfer->file->fd); 475 free(transfer->file); 476 } 477 free(transfer); 478 } 479 480 static char *next(char **p, char *end) 481 { 482 char *ret = *p; 483 size_t len; 484 485 if (*(end-1) != 0 || 486 *p == end || 487 (len = strlen(ret)) == 0) 488 return NULL; 489 490 *p += len + 1; 491 return ret; 492 } 493 494 static ssize_t tftp_err(int err, char *packet, char *message, char *file) 495 { 496 struct errmess { 497 unsigned short op, err; 498 char message[]; 499 } *mess = (struct errmess *)packet; 500 ssize_t ret = 4; 501 char *errstr = strerror(errno); 502 503 mess->op = htons(OP_ERR); 504 mess->err = htons(err); 505 ret += (snprintf(mess->message, 500, message, file, errstr) + 1); 506 my_syslog(MS_TFTP | LOG_ERR, "TFTP %s", mess->message); 507 508 return ret; 509 } 510 511 static ssize_t tftp_err_oops(char *packet, char *file) 512 { 513 return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file); 514 } 515 516 /* return -1 for error, zero for done. */ 517 static ssize_t get_block(char *packet, struct tftp_transfer *transfer) 518 { 519 if (transfer->block == 0) 520 { 521 /* send OACK */ 522 char *p; 523 struct oackmess { 524 unsigned short op; 525 char data[]; 526 } *mess = (struct oackmess *)packet; 527 528 p = mess->data; 529 mess->op = htons(OP_OACK); 530 if (transfer->opt_blocksize) 531 { 532 p += (sprintf(p, "blksize") + 1); 533 p += (sprintf(p, "%d", transfer->blocksize) + 1); 534 } 535 if (transfer->opt_transize) 536 { 537 p += (sprintf(p,"tsize") + 1); 538 p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1); 539 } 540 541 return p - packet; 542 } 543 else 544 { 545 /* send data packet */ 546 struct datamess { 547 unsigned short op, block; 548 unsigned char data[]; 549 } *mess = (struct datamess *)packet; 550 551 size_t size = transfer->file->size - transfer->offset; 552 553 if (transfer->offset > transfer->file->size) 554 return 0; /* finished */ 555 556 if (size > transfer->blocksize) 557 size = transfer->blocksize; 558 559 mess->op = htons(OP_DATA); 560 mess->block = htons((unsigned short)(transfer->block)); 561 562 if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 || 563 !read_write(transfer->file->fd, mess->data, size, 1)) 564 return -1; 565 566 transfer->expansion = 0; 567 568 /* Map '\n' to CR-LF in netascii mode */ 569 if (transfer->netascii) 570 { 571 size_t i; 572 int newcarrylf; 573 574 for (i = 0, newcarrylf = 0; i < size; i++) 575 if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf)) 576 { 577 if (size == transfer->blocksize) 578 { 579 transfer->expansion++; 580 if (i == size - 1) 581 newcarrylf = 1; /* don't expand LF again if it moves to the next block */ 582 } 583 else 584 size++; /* room in this block */ 585 586 /* make space and insert CR */ 587 memmove(&mess->data[i+1], &mess->data[i], size - (i + 1)); 588 mess->data[i] = '\r'; 589 590 i++; 591 } 592 transfer->carrylf = newcarrylf; 593 594 } 595 596 return size + 4; 597 } 598 } 599 600 #endif 601