tftpd.c (146827) | tftpd.c (173852) |
---|---|
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 --- 28 unchanged lines hidden (view full) --- 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; 43#endif 44static const char rcsid[] = | 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 --- 28 unchanged lines hidden (view full) --- 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; 43#endif 44static const char rcsid[] = |
45 "$FreeBSD: head/libexec/tftpd/tftpd.c 146827 2005-05-31 17:22:53Z maxim $"; | 45 "$FreeBSD: head/libexec/tftpd/tftpd.c 173852 2007-11-23 00:05:29Z edwin $"; |
46#endif /* not lint */ 47 48/* 49 * Trivial file transfer protocol server. 50 * 51 * This version includes many modifications by Jim Guyton 52 * <guyton@rand-unix>. 53 */ --- 51 unchanged lines hidden (view full) --- 105static struct dirlist { 106 const char *name; 107 int len; 108} dirs[MAXDIRS+1]; 109static int suppress_naks; 110static int logging; 111static int ipchroot; 112static int create_new = 0; | 46#endif /* not lint */ 47 48/* 49 * Trivial file transfer protocol server. 50 * 51 * This version includes many modifications by Jim Guyton 52 * <guyton@rand-unix>. 53 */ --- 51 unchanged lines hidden (view full) --- 105static struct dirlist { 106 const char *name; 107 int len; 108} dirs[MAXDIRS+1]; 109static int suppress_naks; 110static int logging; 111static int ipchroot; 112static int create_new = 0; |
113static char *newfile_format = "%Y%m%d"; 114static int increase_name = 0; |
|
113static mode_t mask = S_IWGRP|S_IWOTH; 114 115static const char *errtomsg(int); 116static void nak(int); 117static void oack(void); 118 119static void timer(int); 120static void justquit(int); --- 8 unchanged lines hidden (view full) --- 129 struct sockaddr_storage me; 130 char *chroot_dir = NULL; 131 struct passwd *nobody; 132 const char *chuser = "nobody"; 133 134 tzset(); /* syslog in localtime */ 135 136 openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); | 115static mode_t mask = S_IWGRP|S_IWOTH; 116 117static const char *errtomsg(int); 118static void nak(int); 119static void oack(void); 120 121static void timer(int); 122static void justquit(int); --- 8 unchanged lines hidden (view full) --- 131 struct sockaddr_storage me; 132 char *chroot_dir = NULL; 133 struct passwd *nobody; 134 const char *chuser = "nobody"; 135 136 tzset(); /* syslog in localtime */ 137 138 openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); |
137 while ((ch = getopt(argc, argv, "cClns:u:U:w")) != -1) { | 139 while ((ch = getopt(argc, argv, "cCF:lns:u:U:wW")) != -1) { |
138 switch (ch) { 139 case 'c': 140 ipchroot = 1; 141 break; 142 case 'C': 143 ipchroot = 2; 144 break; | 140 switch (ch) { 141 case 'c': 142 ipchroot = 1; 143 break; 144 case 'C': 145 ipchroot = 2; 146 break; |
147 case 'F': 148 newfile_format = optarg; 149 break; |
|
145 case 'l': 146 logging = 1; 147 break; 148 case 'n': 149 suppress_naks = 1; 150 break; 151 case 's': 152 chroot_dir = optarg; 153 break; 154 case 'u': 155 chuser = optarg; 156 break; 157 case 'U': 158 mask = strtol(optarg, NULL, 0); 159 break; 160 case 'w': 161 create_new = 1; 162 break; | 150 case 'l': 151 logging = 1; 152 break; 153 case 'n': 154 suppress_naks = 1; 155 break; 156 case 's': 157 chroot_dir = optarg; 158 break; 159 case 'u': 160 chuser = optarg; 161 break; 162 case 'U': 163 mask = strtol(optarg, NULL, 0); 164 break; 165 case 'w': 166 create_new = 1; 167 break; |
168 case 'W': 169 create_new = 1; 170 increase_name = 1; 171 break; |
|
163 default: 164 syslog(LOG_WARNING, "ignoring unknown option -%c", ch); 165 } 166 } 167 if (optind < argc) { 168 struct dirlist *dirp; 169 170 /* Get list of directory prefixes. Skip relative pathnames. */ --- 337 unchanged lines hidden (view full) --- 508 (*pf->f_send)(pf); 509 exit(0); 510} 511 512 513FILE *file; 514 515/* | 172 default: 173 syslog(LOG_WARNING, "ignoring unknown option -%c", ch); 174 } 175 } 176 if (optind < argc) { 177 struct dirlist *dirp; 178 179 /* Get list of directory prefixes. Skip relative pathnames. */ --- 337 unchanged lines hidden (view full) --- 517 (*pf->f_send)(pf); 518 exit(0); 519} 520 521 522FILE *file; 523 524/* |
525 * Find the next value for YYYYMMDD.nn when the file to be written should 526 * be unique. Due to the limitations of nn, we will fail if nn reaches 100. 527 * Besides, that is four updates per hour on a file, which is kind of 528 * execessive anyway. 529 */ 530static int 531find_next_name(char *filename, int *fd) 532{ 533 int i; 534 time_t tval; 535 size_t len; 536 struct tm lt; 537 char yyyymmdd[MAXPATHLEN]; 538 char newname[MAXPATHLEN]; 539 struct stat sb; 540 int ret; 541 542 /* Create the YYYYMMDD part of the filename */ 543 time(&tval); 544 lt = *localtime(&tval); 545 len = strftime(yyyymmdd, sizeof(yyyymmdd), newfile_format, <); 546 if (len == 0) { 547 syslog(LOG_WARNING, 548 "Filename suffix too long (%d characters maximum)", 549 MAXPATHLEN); 550 return (EACCESS); 551 } 552 553 /* Make sure the new filename is not too long */ 554 if (strlen(filename) > MAXPATHLEN - len - 5) { 555 syslog(LOG_WARNING, 556 "Filename too long (%d characters, %d maximum)", 557 strlen(filename), MAXPATHLEN - len - 5); 558 return (EACCESS); 559 } 560 561 /* Find the first file which doesn't exist */ 562 for (i = 0; i < 100; i++) { 563 sprintf(newname, "%s.%s.%02d", filename, yyyymmdd, i); 564 *fd = open(newname, 565 O_WRONLY | O_CREAT | O_EXCL, 566 S_IRUSR | S_IWUSR | S_IRGRP | 567 S_IWGRP | S_IROTH | S_IWOTH); 568 if (*fd > 0) 569 return 0; 570 } 571 572 return (EEXIST); 573} 574 575/* |
|
516 * Validate file access. Since we 517 * have no uid or gid, for now require 518 * file to exist and be publicly 519 * readable/writable. 520 * If we were invoked with arguments 521 * from inetd then the file must also be 522 * in one of the given directory prefixes. 523 * Note also, full path name must be 524 * given as we have no login directory. 525 */ 526int 527validate_access(char **filep, int mode) 528{ 529 struct stat stbuf; 530 int fd; | 576 * Validate file access. Since we 577 * have no uid or gid, for now require 578 * file to exist and be publicly 579 * readable/writable. 580 * If we were invoked with arguments 581 * from inetd then the file must also be 582 * in one of the given directory prefixes. 583 * Note also, full path name must be 584 * given as we have no login directory. 585 */ 586int 587validate_access(char **filep, int mode) 588{ 589 struct stat stbuf; 590 int fd; |
591 int error; |
|
531 struct dirlist *dirp; 532 static char pathname[MAXPATHLEN]; 533 char *filename = *filep; 534 535 /* 536 * Prevent tricksters from getting around the directory restrictions 537 */ 538 if (strstr(filename, "/../")) --- 66 unchanged lines hidden (view full) --- 605 else 606 /* XXX Allows writes of all sizes. */ 607 options[OPT_TSIZE].o_reply = 608 atoi(options[OPT_TSIZE].o_request); 609 } 610 if (mode == RRQ) 611 fd = open(filename, O_RDONLY); 612 else { | 592 struct dirlist *dirp; 593 static char pathname[MAXPATHLEN]; 594 char *filename = *filep; 595 596 /* 597 * Prevent tricksters from getting around the directory restrictions 598 */ 599 if (strstr(filename, "/../")) --- 66 unchanged lines hidden (view full) --- 666 else 667 /* XXX Allows writes of all sizes. */ 668 options[OPT_TSIZE].o_reply = 669 atoi(options[OPT_TSIZE].o_request); 670 } 671 if (mode == RRQ) 672 fd = open(filename, O_RDONLY); 673 else { |
613 if (create_new) 614 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0666); 615 else 616 fd = open(filename, O_WRONLY|O_TRUNC); | 674 if (create_new) { 675 if (increase_name) { 676 error = find_next_name(filename, &fd); 677 if (error > 0) 678 return (error + 100); 679 } else 680 fd = open(filename, 681 O_WRONLY | O_TRUNC | O_CREAT, 682 S_IRUSR | S_IWUSR | S_IRGRP | 683 S_IWGRP | S_IROTH | S_IWOTH ); 684 } else 685 fd = open(filename, O_WRONLY | O_TRUNC); |
617 } 618 if (fd < 0) 619 return (errno + 100); 620 file = fdopen(fd, (mode == RRQ)? "r":"w"); 621 if (file == NULL) { 622 close(fd); 623 return (errno + 100); 624 } --- 305 unchanged lines hidden --- | 686 } 687 if (fd < 0) 688 return (errno + 100); 689 file = fdopen(fd, (mode == RRQ)? "r":"w"); 690 if (file == NULL) { 691 close(fd); 692 return (errno + 100); 693 } --- 305 unchanged lines hidden --- |