diff -crN publicfile-0.52/Makefile /usr2/home/one/qftpd-0.10/Makefile *** publicfile-0.52/Makefile Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/Makefile Tue Mar 27 22:25:34 2001 *************** *** 16,21 **** --- 16,38 ---- compile alloc_re.c alloc.h byte.h ./compile alloc_re.c + auth.ftpd: \ + load auth.ftpd.o prot.o file.o ip.o \ + timeoutread.o timeoutwrite.o timeoutconn.o timeoutaccept.o ndelay.a \ + env.a sig.a substdio.a alloc.a error.a open.a case.a str.a wait.a\ + fs.a socket.lib + ./load auth.ftpd prot.o file.o ip.o \ + timeoutread.o timeoutwrite.o timeoutconn.o timeoutaccept.o \ + ndelay.a env.a sig.a substdio.a alloc.a error.a \ + wait.a open.a case.a str.a fs.a `cat socket.lib` + + auth.ftpd.o: \ + compile auth.ftpd.c timeoutconn.h timeoutaccept.h timeoutread.h \ + timeoutwrite.h substdio.h stralloc.h gen_alloc.h \ + file.h tai.h uint64.h sig.h tai.h str.h error.h case.h \ + byte.h env.h fmt.h scan.h ip.h config.h server.h wait.h + ./compile auth.ftpd.c + auto-str: \ load auto-str.o substdio.a error.a str.a ./load auto-str substdio.a error.a str.a *************** *** 147,158 **** fetch.o: \ compile fetch.c substdio.h timeoutwrite.h error.h exit.h direntry.h \ ! fmt.h fetch.h ./compile fetch.c file.o: \ compile file.c subfd.h substdio.h error.h file.h tai.h uint64.h \ ! byte.h str.h tai.h env.h ./compile file.c filetype.o: \ --- 164,175 ---- fetch.o: \ compile fetch.c substdio.h timeoutwrite.h error.h exit.h direntry.h \ ! fmt.h fetch.h config.h server.h ./compile fetch.c file.o: \ compile file.c subfd.h substdio.h error.h file.h tai.h uint64.h \ ! byte.h str.h tai.h env.h config.h server.h stralloc.h ./compile file.c filetype.o: \ *************** *** 194,200 **** compile ftpd.c timeoutconn.h timeoutaccept.h timeoutread.h \ timeoutwrite.h substdio.h fetch.h pathdecode.h stralloc.h gen_alloc.h \ file.h tai.h uint64.h sig.h tai.h stralloc.h str.h error.h case.h \ ! byte.h env.h fmt.h scan.h ip.h ./compile ftpd.c getln.a: \ --- 211,217 ---- compile ftpd.c timeoutconn.h timeoutaccept.h timeoutread.h \ timeoutwrite.h substdio.h fetch.h pathdecode.h stralloc.h gen_alloc.h \ file.h tai.h uint64.h sig.h tai.h stralloc.h str.h error.h case.h \ ! byte.h env.h fmt.h scan.h ip.h config.h server.h ./compile ftpd.c getln.a: \ *************** *** 312,318 **** chmod 755 load main.o: \ ! compile main.c env.h exit.h scan.h ./compile main.c makelib: \ --- 329,335 ---- chmod 755 load main.o: \ ! compile main.c env.h exit.h scan.h config.h ./compile main.c makelib: \ *************** *** 359,365 **** ./compile open_trunc.c pathdecode.o: \ ! compile pathdecode.c pathdecode.h stralloc.h gen_alloc.h ./compile pathdecode.c percent.o: \ --- 376,382 ---- ./compile open_trunc.c pathdecode.o: \ ! compile pathdecode.c pathdecode.h stralloc.h gen_alloc.h config.h server.h ./compile pathdecode.c percent.o: \ *************** *** 367,373 **** ./compile percent.c prog: \ ! configure httpd ftpd rts utime prot.o: \ compile prot.c hasshsgr.h prot.h --- 384,390 ---- ./compile percent.c prog: \ ! configure ftpd rts utime auth.ftpd prot.o: \ compile prot.c hasshsgr.h prot.h *************** *** 580,582 **** --- 597,611 ---- utime.o: \ compile utime.c scan.h exit.h ./compile utime.c + + wait.a: \ + makelib wait_pid.o wait_nohang.o + ./makelib wait.a wait_pid.o wait_nohang.o + + wait_nohang.o: \ + compile wait_nohang.c haswaitp.h + ./compile wait_nohang.c + + wait_pid.o: \ + compile wait_pid.c error.h haswaitp.h + ./compile wait_pid.c diff -crN publicfile-0.52/auth.ftpd.c /usr2/home/one/qftpd-0.10/auth.ftpd.c *** publicfile-0.52/auth.ftpd.c Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/auth.ftpd.c Tue Mar 27 21:47:48 2001 *************** *** 0 **** --- 1,243 ---- + #include + #include + #include + #include + #include + #include "timeoutconn.h" + #include "timeoutaccept.h" + #include "timeoutread.h" + #include "timeoutwrite.h" + #include "substdio.h" + #include "file.h" + #include "sig.h" + #include "tai.h" + #include "str.h" + #include "error.h" + #include "case.h" + #include "byte.h" + #include "env.h" + #include "fmt.h" + #include "scan.h" + #include "ip.h" + #include "config.h" + #include "readwrite.h" + #include "wait.h" + + int safewrite(int fd,char *buf,int len) + { + int r; + r = timeoutwrite(DEFAULT_TIMEOUT_WRITE,fd,buf,len); + if (r <= 0) _exit(ERR_TIME); + return r; + } + + char outbuf[256]; + substdio out = SUBSTDIO_FDBUF(safewrite,1,outbuf,sizeof outbuf); + + void out_flush(void) + { + substdio_flush(&out); + } + + void out_put(char *s,int len) + { + while (len > 0) { + substdio_put(&out,s,1); + if (*s == (char) 255) substdio_put(&out,s,1); + ++s; + --len; + } + } + + void out_puts(char *s) + { + out_put(s,str_len(s)); + } + + int saferead(int fd,char *buf,int len) + { + int r; + out_flush(); + r = timeoutread(DEFAULT_TIMEOUT_READ,fd,buf,len); + if (r <= 0) _exit(ERR_TIME); + return r; + } + + char inbuf[256]; + substdio in = SUBSTDIO_FDBUF(saferead,0,inbuf,sizeof inbuf); + + void in_get(char *ch) + { + for (;;) { + substdio_get(&in,ch,1); + if (*ch != (char) 255) return; + substdio_get(&in,ch,1); + if (*ch == (char) 255) return; + + if ((*ch == (char) 254) || (*ch == (char) 252)) + substdio_get(&in,ch,1); + else if (*ch == (char) 253) { + substdio_get(&in,ch,1); + substdio_put(&out,"\377\374",2); + substdio_put(&out,ch,1); + } + else if (*ch == (char) 251) { + substdio_get(&in,ch,1); + substdio_put(&out,"\377\376",2); + substdio_put(&out,ch,1); + } + } + } + + int fd_copy(to,from) + int to; + int from; + { + if (to == from) return 0; + if (fcntl(from,F_GETFL,0) == -1) return -1; + close(to); + if (fcntl(from,F_DUPFD,to) == -1) return -1; + return 0; + } + + char unique[FMT_ULONG + FMT_ULONG + 3]; + char **childargs; + substdio ssup; + char upbuf[128]; + + void doanddie(user,userlen,pass) + char *user; + unsigned int userlen; /* including 0 byte */ + char *pass; + { + int child; + int wstat; + int pi[2]; + #ifdef BADBOY_LOGIN + sleep(BADBOY_LDELAY); + #endif + if (fd_copy(2,1) == -1) _exit(ERR_PIPE); + close(3); + if (pipe(pi) == -1) _exit(ERR_PIPE); + if (pi[0] != 3) _exit(ERR_PIPE); + switch(child = fork()) { + case -1: + _exit(ERR_FORK); + case 0: + close(pi[1]); + sig_pipedefault(); + execvp(*childargs,childargs); + _exit(ERR_ERR); + } + close(pi[0]); + substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf); + if (substdio_put(&ssup,user,userlen + 1) == -1) _exit(ERR_WRITE); + if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) _exit(ERR_WRITE); + + if (substdio_flush(&ssup) == -1) _exit(ERR_WRITE); + close(pi[1]); + byte_zero(pass,str_len(pass)); + byte_zero(upbuf,sizeof upbuf); + if (wait_pid(&wstat,child) == -1) _exit(ERR_ERR); + if (wait_crashed(wstat)) _exit(ERR_CHILD); + if (wait_exitcode(wstat)) { + #ifdef BADBOY_BADPASS + sleep(BADBOY_BDELAY); + #endif + #ifdef BADAUTH_MSG + out_puts(BADAUTH_MSG); + #endif + #ifdef BADAUTH_HANGUP + _exit(ERR_AUTH); + #endif + } + _exit(ERR_OK); + } + + struct ip_address iplocal = { {0,0,0,0} }; + struct ip_address ipremote = { {0,0,0,0} }; + struct sockaddr_in sa; + char user[MAX_USER]; + char pass[MAX_PASS]; + char line[MAX_LINE]; + + int main(int argc, char **argv) + { + char *cmd; + char *arg; + char *x; + unsigned char ch; + int i; + char *s; + + childargs = argv + 1; + { + int opt = 1; + setsockopt(0,SOL_SOCKET,SO_OOBINLINE,(char *) &opt,sizeof opt); + /* if it fails, bummer */ + } + + x = env_get("TCPLOCALIP"); + if (!x) x = "0.0.0.0"; + if (!ip_scan(x,&iplocal)) + byte_zero(&iplocal,4); + + x = env_get("TCPREMOTEIP"); + if (!x) x = "0.0.0.0"; + if (!ip_scan(x,&ipremote)) + byte_zero(&ipremote,4); + + sig_pipeignore(); + + + s = unique; + s += fmt_uint(s,getpid()); + *s++ = '.'; + s += fmt_ulong(s,(unsigned long) time((long *) 0)); + *s++ = '@'; + *s++ = 0; + out_puts(REPLY_CONNECT); + for (;;) { + line[0] = 0; + line[MAX_LINE-1]=0; + for (i=0;i0) && (line[0] != 0) && (line[i-1] == '\r')) line[i-1] = 0; + + cmd = line; + arg = cmd + str_chr(cmd,' '); + if (*arg) *arg++ = 0; + + if (case_equals(cmd,"quit")) { + out_puts(REPLY_QUIT); + out_flush(); + _exit(ERR_OK); + } + if (case_equals(cmd,"user")) { + for (i=0; i/?`~!@#$%^&*()_+-={}[]\\|:;\'\" " + #define MANGLE_USER_CHAR '-' + #define MANGLE_PASS_CHAR '-' + /**************************************************************\ + [Defaults] + These settings will control default behavior. + \**************************************************************/ + + #define DEFAULT_TRANSFER TRANSFER_BINARY + + //Time (in seconds) to wait while waiting to send data. + #define DEFAULT_TIMEOUT_WRITE 60 + + //Time (in seconds) to wait while waiting to receive data. + #define DEFAULT_TIMEOUT_READ 60 + + //Time (in seconds) to wait for idle users' input. + #define DEFAULT_TIMEOUT_IDLE 60*2 + + //Time (in seconds) to wait for connections (in or out). + #define DEFAULT_TIMEOUT_CONN 60 + + #define DEFAULT_MINUID 1000 + #define DEFAULT_MINGID 1000 + #define DEFAULT_UID 65534 + #define DEFAULT_GID 65534 + + /**************************************************************\ + [Server Responses] + You can customize server responses here. + You MUST put \r\n at the end of your responses otherwise you'll break stuff. + \**************************************************************/ + #define REPLY_SYST "215 UNIX\r\n" + #define REPLY_HELP "214 publicfile home page: http://pobox.com/~djb/publicfile.html\r\n" + #define REPLY_PASS "202 You may only authenticate once.\r\n" + #define REPLY_MKD_OK "257 Directory successfully created.\r\n" + #define REPLY_MKD_BAD "550 Unable to create directory.\r\n" + #define REPLY_RMD_OK "250 Directory successfully removed.\r\n" + #define REPLY_RMD_BAD "550 Unable to remove directory.\r\n" + #define REPLY_DELE_OK "250 File successfully deleted.\r\n" + #define REPLY_DELE_BAD "530 Unable to delete file.\r\n" + #define REPLY_RNFR_OK "350 Ok.\r\n" + #define REPLY_RNFR_BAD "530 Error.\r\n" + #define REPLY_RNTO_OK "250 File successfully renamed.\r\n" + #define REPLY_RNTO_BAD "530 Error renaming file.\r\n" + #define REPLY_NOT_ALLOWED "530 Sorry, that command is not allowed.\r\n" + #define REPLY_UNKNOWN "502 Sorry, I don't understand that command.\r\n" + #define REPLY_TYPE_BINARY "200 Okay, using binary.\r\n" + #define REPLY_TYPE_ASCII "200 Type set to A.\r\n" + #define REPLY_TYPE_BAD "504 Sorry, I don't recognize that type.\r\n" + #define REPLY_MODE_STREAM "200 Thanks, I always do stream mode.\r\n" + #define REPLY_MODE_BAD "504 Sorry, I don't do anything except stream mode.\r\n" + #define REPLY_STRU_FILE "200 Thanks, I always do file structure.\r\n" + #define REPLY_STRU_BAD "504 Sorry, I don't do anything except file structure.\r\n" + #define REPLY_NOOP "200 I'm here.\r\n" + #define REPLY_QUIT "221 Goodbye.\r\n" + #define REPLY_USER "230 You may only authenticate once.\r\n" + #define REPLY_NOAUTH "530 Please login with USER and PASS.\r\n" + #define REPLY_BADLOGIN "530 Login incorrect.\r\n" + #define REPLY_NOWPASS "331 Password required.\r\n" + #define REPLY_WELCOME "230 Welcome.\r\n" + #define REPLY_NOWRITE "550 Sorry, you do not have write permission.\r\n" + #define REPLY_CONNECT "220 You have successfully connected.\r\n" + + /**************************************************************\ + [Error Codes] + \**************************************************************/ + #define ERR_OK 0 + #define ERR_AUTH 1 + #define ERR_MEM 2 + #define ERR_TIME 3 + #define ERR_FORK 4 + #define ERR_PIPE 5 + #define ERR_WRITE 6 + #define ERR_CHILD 7 + #define ERR_ERR 8 + #define ERR_CHDIR 20 + #define ERR_STRALLOC 21 + #define ERR_LISTEN 22 + #define ERR_UIDGID 30 diff -crN publicfile-0.52/fetch.c /usr2/home/one/qftpd-0.10/fetch.c *** publicfile-0.52/fetch.c Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/fetch.c Sat Mar 17 22:51:17 2001 *************** *** 1,6 **** --- 1,7 ---- #include #include #include + #include #include "substdio.h" #include "timeoutwrite.h" #include "error.h" *************** *** 8,19 **** #include "direntry.h" #include "fmt.h" #include "fetch.h" ! int fetch_ascii = 1; unsigned long fetch_rest = 0; ! static char inbuf[1024]; ! static char ssbuf[1024]; static substdio ss; static int trouble; --- 9,23 ---- #include "direntry.h" #include "fmt.h" #include "fetch.h" + #include "config.h" + #include "server.h" ! int fetch_ascii = DEFAULT_TRANSFER; unsigned long fetch_rest = 0; ! char filebuf[BUFFER_FILE]; ! static char ssbuf[BUFFER_NETWORK]; ! static substdio ss; static int trouble; *************** *** 21,26 **** --- 25,49 ---- static struct stat st; static char strnum[FMT_ULONG]; + #ifdef BUFSTOR + static int dataread(int fd,char *buf,int len) + { + int w; + + if (trouble) return -1; + + if (fetch_rest) { + if (len > fetch_rest) len = fetch_rest; + fetch_rest -= len; + return len; + } + + w = timeoutread(config.toread,fd,buf,len); + if (w == -1) if (errno != error_intr) trouble = errno; + return w; + } + #endif + static int datawrite(int fd,char *buf,int len) { int w; *************** *** 33,45 **** return len; } ! w = timeoutwrite(60,fd,buf,len); if (w == -1) if (errno != error_intr) trouble = errno; return w; } static void printstat() { substdio_puts(&ss,"+i"); substdio_put(&ss,strnum,fmt_ulong(strnum,(unsigned long) st.st_dev)); substdio_puts(&ss,"."); --- 56,69 ---- return len; } ! w = timeoutwrite(config.towrite,fd,buf,len); if (w == -1) if (errno != error_intr) trouble = errno; return w; } static void printstat() { + #ifdef EPLF substdio_puts(&ss,"+i"); substdio_put(&ss,strnum,fmt_ulong(strnum,(unsigned long) st.st_dev)); substdio_puts(&ss,"."); *************** *** 53,73 **** --- 77,124 ---- if ((st.st_mode & S_IFMT) == S_IFDIR) substdio_puts(&ss,",/"); + #ifdef WORLD_ACCESS if (((st.st_mode & S_IFMT) == S_IFREG) && ((st.st_mode & 0444) == 0444)) { + #endif substdio_puts(&ss,",r,s"); substdio_put(&ss,strnum,fmt_ulong(strnum,(unsigned long) st.st_size)); + #ifdef WORLD_ACCESS } + #endif substdio_puts(&ss,",\t"); + #endif + #ifndef EPLF + char *datestring; + unsigned int len; + + len = fmt_ulong(strnum,(unsigned long) st.st_size); + datestring = ctime(&st.st_mtime); + + substdio_puts(&ss,(st.st_mode & S_IFMT) == S_IFDIR ? "drwxr-xr-x" : "-rw-r--r--"); + substdio_puts(&ss," 1 owner group "); + substdio_put(&ss,strnum,len); + substdio_puts(&ss," "); + substdio_put(&ss,datestring+4,7); + if (st.st_mtime + ((365/2)*86400) > now) + substdio_put(&ss,datestring+11,5); + else + substdio_put(&ss,datestring+19,5); + substdio_puts(&ss," "); + #endif } static void list(char *fn,int flaglong) { int i; + #ifdef HIDE_DOT_FILES if (fn[0] == '.') return; + #endif for (i = 0;fn[i];++i) { if ((fn[i] >= 0) && (fn[i] <= 32)) return; + #ifdef HIDE_TILDE_FILES if (fn[i] == '~') return; + #endif } if (flaglong) { *************** *** 89,98 **** int r; int i; - substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); switch(how) { case FETCH_LISTONE: if (fstat(fdfile,&st) == -1) break; printstat(&st); for (i = 0;fn[i];++i) --- 140,149 ---- int r; int i; switch(how) { case FETCH_LISTONE: + substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); if (fstat(fdfile,&st) == -1) break; printstat(&st); for (i = 0;fn[i];++i) *************** *** 101,110 **** else substdio_put(&ss,&fn[i],1); substdio_puts(&ss,"\r\n"); break; - case FETCH_LIST: case FETCH_NLST: if (fchdir(fdfile) == -1) { trouble = errno; return; --- 152,163 ---- else substdio_put(&ss,&fn[i],1); substdio_puts(&ss,"\r\n"); + substdio_flush(&ss); break; case FETCH_NLST: + case FETCH_LIST: + substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); if (fchdir(fdfile) == -1) { trouble = errno; return; *************** *** 115,145 **** while (d = readdir(dir)) /* XXX: temporary errors */ list(d->d_name,how == FETCH_LIST); closedir(dir); break; ! default: ! for (;;) { ! r = read(fdfile,inbuf,sizeof inbuf); ! if (r == -1) { ! if (errno = error_intr) continue; ! _exit(23); ! } ! if (r == 0) ! break; ! if (!fetch_ascii) ! substdio_put(&ss,inbuf,r); ! else for (i = 0;i < r;++i) { ! if (inbuf[i] == '\n') substdio_put(&ss,"\r",1); ! substdio_put(&ss,inbuf + i,1); } } break; } - - substdio_flush(&ss); } void fetch(char *fn,int fddata,int fdfile,int how) --- 168,230 ---- while (d = readdir(dir)) /* XXX: temporary errors */ list(d->d_name,how == FETCH_LIST); closedir(dir); + substdio_flush(&ss); break; ! case FETCH_RETR: ! #ifdef BUFRETR ! substdio_fdbuf(&ss,datawrite,fddata,ssbuf,sizeof ssbuf); ! if (!fetch_ascii) { ! while ((r = read(fdfile,filebuf,sizeof filebuf)) != 0) { ! if (r == -1) { ! if (errno = error_intr) continue; ! _exit(23); ! } ! substdio_bput(&ss,filebuf,r); ! } ! } ! else { ! while ((r = read(fdfile,filebuf,sizeof filebuf)) != 0) { ! if (r == -1) { ! if (errno = error_intr) continue; ! _exit(23); ! } for (i = 0;i < r;++i) { ! if (filebuf[i] == '\n') substdio_put(&ss,"\r",1); ! substdio_put(&ss,filebuf + i,1); } + } } + substdio_flush(&ss); + #endif + #ifndef BUFRETR + if (fetch_rest) + lseek(fdfile,fetch_rest,SEEK_SET); + while (((r=timeoutread(config.toread,fdfile,filebuf,sizeof filebuf)) > 0) && (timeoutwrite(config.towrite,fddata,filebuf,r) == r)) {}; + #endif + fetch_rest = 0; break; + case FETCH_APPE: + case FETCH_STOR: + #ifdef BUFSTOR + substdio_fdbuf(&ss,dataread,fddata,ssbuf,sizeof ssbuf); + while ((r = substdio_bget(&ss,filebuf,sizeof filebuf)) != 0) { + if (r == -1) { + if (errno = error_intr) continue; + _exit(23); + } + write(fdfile,filebuf,r); + } + substdio_flush(&ss); + #endif + #ifndef BUFSTOR + while (((r=timeoutread(config.toread,fddata,filebuf,sizeof filebuf)) > 0) && (timeoutwrite(config.towrite,fdfile,filebuf,r) == r)) { }; + #endif + break; + default: break; } } void fetch(char *fn,int fddata,int fdfile,int how) diff -crN publicfile-0.52/fetch.h /usr2/home/one/qftpd-0.10/fetch.h *** publicfile-0.52/fetch.h Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/fetch.h Fri Mar 9 00:13:04 2001 *************** *** 5,10 **** --- 5,12 ---- #define FETCH_NLST 1 #define FETCH_LIST 2 #define FETCH_LISTONE 3 + #define FETCH_STOR 4 + #define FETCH_APPE 5 extern void fetch(char *,int,int,int); extern int fetch_ascii; diff -crN publicfile-0.52/file.c /usr2/home/one/qftpd-0.10/file.c *** publicfile-0.52/file.c Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/file.c Sat Mar 17 22:56:03 2001 *************** *** 10,16 **** static void log(char *fn,char *result1,char *result2,int flagread) { ! int i; char ch; char *x; --- 10,16 ---- static void log(char *fn,char *result1,char *result2,int flagread) { ! /* int i; char ch; char *x; *************** *** 33,39 **** substdio_puts(subfderr,result1); substdio_puts(subfderr,result2); substdio_puts(subfderr,"\n"); ! substdio_flush(subfderr); } int file_open(char *fn,struct tai *mtime,unsigned long *length,int flagread) --- 33,44 ---- substdio_puts(subfderr,result1); substdio_puts(subfderr,result2); substdio_puts(subfderr,"\n"); ! substdio_flush(subfderr);*/ ! } ! ! int manglepath(stralloc *fn) ! { ! return(-1); } int file_open(char *fn,struct tai *mtime,unsigned long *length,int flagread) *************** *** 53,58 **** --- 58,111 ---- if (error_temp(errno)) _exit(23); return -1; } + #ifdef WORLD_ACCESS + if ((st.st_mode & 0444) != 0444) { + log(fn,": ","not ugo+r",flagread); + close(fd); + errno = error_acces; + return -1; + } + if ((st.st_mode & 0101) == 0001) { + log(fn,": ","o+x but u-x",flagread); + close(fd); + errno = error_acces; + return -1; + } + #endif + if (flagread) + if ((st.st_mode & S_IFMT) != S_IFREG) { + log(fn,": ","not a regular file",flagread); + close(fd); + errno = error_acces; + return -1; + } + + log(fn,": ","success",flagread); + + *length = st.st_size; + tai_unix(mtime,st.st_mtime); + + return fd; + } + + int file_openwrite(char *fn,struct tai *mtime,unsigned long *length,int flagread) + { + struct stat st; + int fd; + + fd = open_trunc(fn); + if (fd == -1) { + log(fn,": open failed: ",error_str(errno),flagread); + if (error_temp(errno)) _exit(23); + return -1; + } + if (fstat(fd,&st) == -1) { + log(fn,": fstat failed: ",error_str(errno),flagread); + close(fd); + if (error_temp(errno)) _exit(23); + return -1; + } + #ifdef WORLD_ACCESS if ((st.st_mode & 0444) != 0444) { log(fn,": ","not ugo+r",flagread); close(fd); *************** *** 65,70 **** --- 118,124 ---- errno = error_acces; return -1; } + #endif if (flagread) if ((st.st_mode & S_IFMT) != S_IFREG) { log(fn,": ","not a regular file",flagread); *************** *** 80,82 **** --- 134,197 ---- return fd; } + + int file_openappend(char *fn,struct tai *mtime,unsigned long *length,int flagread) + { + struct stat st; + int fd; + + fd = open_append(fn); + if (fd == -1) { + log(fn,": open failed: ",error_str(errno),flagread); + if (error_temp(errno)) _exit(23); + return -1; + } + if (fstat(fd,&st) == -1) { + log(fn,": fstat failed: ",error_str(errno),flagread); + close(fd); + if (error_temp(errno)) _exit(23); + return -1; + } + #ifdef WORLD_ACCESS + + if ((st.st_mode & 0444) != 0444) { + log(fn,": ","not ugo+r",flagread); + close(fd); + errno = error_acces; + return -1; + } + if ((st.st_mode & 0101) == 0001) { + log(fn,": ","o+x but u-x",flagread); + close(fd); + errno = error_acces; + return -1; + } + #endif + if (flagread) + if ((st.st_mode & S_IFMT) != S_IFREG) { + log(fn,": ","not a regular file",flagread); + close(fd); + errno = error_acces; + return -1; + } + + log(fn,": ","success",flagread); + + *length = st.st_size; + tai_unix(mtime,st.st_mtime); + + return fd; + } + + unsigned long filelen(const char *filename) + { + struct stat st; + errno = 0; + return(stat(filename, &st) == -1 ? 0 : st.st_size); + } + + int fileexist(const char *filename) + { + struct stat st; + return(stat(filename, &st)); + } diff -crN publicfile-0.52/file.h /usr2/home/one/qftpd-0.10/file.h *** publicfile-0.52/file.h Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/file.h Sun Mar 11 21:45:22 2001 *************** *** 2,8 **** --- 2,13 ---- #define FILE_H #include "tai.h" + #include "stralloc.h" extern int file_open(char *,struct tai *,unsigned long *,int); + extern int file_openwrite(char *,struct tai *,unsigned long *,int); + extern int file_openappend(char *,struct tai *,unsigned long *,int); + extern unsigned long filelen(const char *); + int fileexist(const char *); #endif diff -crN publicfile-0.52/ftpd.c /usr2/home/one/qftpd-0.10/ftpd.c *** publicfile-0.52/ftpd.c Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/ftpd.c Tue Mar 27 21:52:41 2001 *************** *** 21,32 **** #include "fmt.h" #include "scan.h" #include "ip.h" int safewrite(int fd,char *buf,int len) { int r; ! r = timeoutwrite(60,fd,buf,len); ! if (r <= 0) _exit(0); return r; } --- 21,37 ---- #include "fmt.h" #include "scan.h" #include "ip.h" + #include "config.h" + #include "server.h" + + ServerConfig config; + char filebuf[BUFFER_FILE]; int safewrite(int fd,char *buf,int len) { int r; ! r = timeoutwrite(config.toconn,fd,buf,len); ! if (r <= 0) _exit(ERR_OK); return r; } *************** *** 57,64 **** { int r; out_flush(); ! r = timeoutread(60,fd,buf,len); ! if (r <= 0) _exit(0); return r; } --- 62,69 ---- { int r; out_flush(); ! r = timeoutread(config.toread,fd,buf,len); ! if (r <= 0) _exit(ERR_OK); return r; } *************** *** 95,103 **** --- 100,111 ---- int fdlisten = -1; /* PASV socket; -1 if PASV not active */ unsigned int portremote = 0; + unsigned long restorlen = 0; stralloc dir = {0}; stralloc fn = {0}; + stralloc rnfr = {0}; + stralloc rnto = {0}; void startlistening(char x[6]) { *************** *** 111,125 **** byte_copy(&sa.sin_addr,4,&iplocal); fdlisten = socket(AF_INET,SOCK_STREAM,0); ! if (fdlisten == -1) _exit(22); opt = 1; setsockopt(fdlisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); ! if (bind(fdlisten,(struct sockaddr *) &sa,sizeof sa) == -1) _exit(22); ! if (listen(fdlisten,1) == -1) _exit(22); dummy = sizeof sa; ! if (getsockname(fdlisten,(struct sockaddr *) &sa,&dummy) == -1) _exit(22); byte_copy(x,4,&sa.sin_addr); byte_copy(x + 4,2,&sa.sin_port); --- 119,133 ---- byte_copy(&sa.sin_addr,4,&iplocal); fdlisten = socket(AF_INET,SOCK_STREAM,0); ! if (fdlisten == -1) _exit(ERR_LISTEN); opt = 1; setsockopt(fdlisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); ! if (bind(fdlisten,(struct sockaddr *) &sa,sizeof sa) == -1) _exit(ERR_LISTEN); ! if (listen(fdlisten,1) == -1) _exit(ERR_LISTEN); dummy = sizeof sa; ! if (getsockname(fdlisten,(struct sockaddr *) &sa,&dummy) == -1) _exit(ERR_LISTEN); byte_copy(x,4,&sa.sin_addr); byte_copy(x + 4,2,&sa.sin_port); *************** *** 142,148 **** startlistening(x); ! out_puts("227 ="); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[0])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[1])); --- 150,156 ---- startlistening(x); ! out_puts("227 Entering Passive Mode ("); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[0])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[1])); *************** *** 154,160 **** out_put(strnum,fmt_ulong(strnum,(unsigned long) x[4])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[5])); ! out_puts("\r\n"); } int portparse(char *arg,unsigned char x[6]) --- 162,168 ---- out_put(strnum,fmt_ulong(strnum,(unsigned long) x[4])); out_puts(","); out_put(strnum,fmt_ulong(strnum,(unsigned long) x[5])); ! out_puts(")\r\n"); } int portparse(char *arg,unsigned char x[6]) *************** *** 205,210 **** --- 213,309 ---- out_puts("350 Okay.\r\n"); } + void put(char *arg,int how) + { + int fdfile; + int fddata; + struct tai mtime; + unsigned long length; + int dummy; + + if (config.write != 1) { + out_puts(REPLY_NOWRITE); + return; + } + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + + if (how == FETCH_STOR) + fdfile = file_openwrite(fn.s,&mtime,&length,how == FETCH_STOR); + if (how == FETCH_APPE) + fdfile = file_openappend(fn.s,&mtime,&length,how == FETCH_APPE); + + if (fdfile == -1) { + out_puts("550 Sorry, I can't create that file: "); + out_puts(error_str(errno)); + out_puts(".\r\n"); + return; + } + + out_puts("150 "); + if ((how == FETCH_RETR) && (fetch_ascii == TRANSFER_ASCII)) + out_puts("Warning: You're using ASCII! "); + + if (fdlisten == -1) { + out_puts("Making transfer connection...\r\n"); + out_flush(); + + fddata = socket(AF_INET,SOCK_STREAM,0); + if (fddata == -1) _exit(ERR_LISTEN); + + /* kernel will reject port 0 at this point */ + if (timeoutconn(fddata,&ipremote,portremote,config.toconn) == -1) { + close(fddata); + close(fdfile); + out_puts("425 Sorry, I couldn't make a connection: "); + out_puts(error_str(errno)); + out_puts(".\r\n"); + return; + } + } + else { + out_puts("Waiting for transfer connection...\r\n"); + out_flush(); + + fddata = timeoutaccept(fdlisten,config.toconn); + close(fdlisten); fdlisten = -1; + + if (fddata != -1) { + dummy = sizeof sa; + if (getpeername(fddata,(struct sockaddr *) &sa,&dummy) == -1) { + close(fddata); fddata = -1; + } + else if (byte_diff(&sa.sin_addr,4,&ipremote)) { + errno = error_acces; + close(fddata); fddata = -1; + } + } + + if (fddata == -1) { + close(fdfile); + out_puts("425 Sorry, I couldn't accept a connection: "); + out_puts(error_str(errno)); + out_puts(".\r\n"); + return; + } + } + + dummy = 1; + setsockopt(fddata,IPPROTO_TCP,1/*TCP_NODELAY*/,&dummy,sizeof dummy); + + fetch(arg,fddata,fdfile,how); /* closes fddata and fdfile */ + + portremote = 0; + } + void get(char *arg,int how) { int fdfile; *************** *** 213,226 **** unsigned long length; int dummy; ! if (!stralloc_copys(&fn,"./0/")) _exit(21); ! if (*arg != '/') { ! if (!stralloc_cat(&fn,&dir)) _exit(21); ! if (!stralloc_append(&fn,"/")) _exit(21); ! } ! if (!stralloc_cats(&fn,arg)) _exit(21); ! pathdecode(&fn); ! if (!stralloc_0(&fn)) _exit(21); fdfile = file_open(fn.s,&mtime,&length,how == FETCH_RETR); if (fdfile == -1) { --- 312,327 ---- unsigned long length; int dummy; ! if (*arg == '/') { ! if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); ! } ! else { ! if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); ! if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); ! if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); ! } ! if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); ! if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); fdfile = file_open(fn.s,&mtime,&length,how == FETCH_RETR); if (fdfile == -1) { *************** *** 231,237 **** } out_puts("150 "); ! if ((how == FETCH_RETR) && fetch_ascii) out_puts("Warning: You're using ASCII! "); if (fdlisten == -1) { --- 332,338 ---- } out_puts("150 "); ! if ((how == FETCH_RETR) && (fetch_ascii == TRANSFER_ASCII)) out_puts("Warning: You're using ASCII! "); if (fdlisten == -1) { *************** *** 239,248 **** out_flush(); fddata = socket(AF_INET,SOCK_STREAM,0); ! if (fddata == -1) _exit(22); /* kernel will reject port 0 at this point */ ! if (timeoutconn(fddata,&ipremote,portremote,60) == -1) { close(fddata); close(fdfile); out_puts("425 Sorry, I couldn't make a connection: "); --- 340,349 ---- out_flush(); fddata = socket(AF_INET,SOCK_STREAM,0); ! if (fddata == -1) _exit(ERR_LISTEN); /* kernel will reject port 0 at this point */ ! if (timeoutconn(fddata,&ipremote,portremote,config.toconn) == -1) { close(fddata); close(fdfile); out_puts("425 Sorry, I couldn't make a connection: "); *************** *** 255,261 **** out_puts("Waiting for transfer connection...\r\n"); out_flush(); ! fddata = timeoutaccept(fdlisten,60); close(fdlisten); fdlisten = -1; if (fddata != -1) { --- 356,362 ---- out_puts("Waiting for transfer connection...\r\n"); out_flush(); ! fddata = timeoutaccept(fdlisten,config.toconn); close(fdlisten); fdlisten = -1; if (fddata != -1) { *************** *** 286,291 **** --- 387,420 ---- portremote = 0; } + void filesize(char *arg) + { + unsigned int len; + unsigned long flen; + + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + flen = filelen(fn.s); + if (errno) { + out_puts("550 Sorry, there is a failure: "); + out_puts(error_str(errno)); + out_puts(".\r\n"); + return; + } + out_puts("213 "); + len = fmt_ulong(strnum,(unsigned long) flen); + out_put(strnum, len); + out_puts("\r\n"); + } + void dir_moveup(void) { dir.len = byte_rchr(dir.s,dir.len,'/'); *************** *** 293,298 **** --- 422,428 ---- void dir_move(char *to) { + /* if (*to == '/') { if (!stralloc_copys(&dir,"")) _exit(21); ++to; *************** *** 301,306 **** --- 431,444 ---- if (!stralloc_append(&dir,"/")) _exit(21); if (!stralloc_cats(&dir,to)) _exit(21); } + */ + if (to[0] == '/') { + if (!stralloc_copys(&dir,to)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_append(&dir,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&dir,to)) _exit(ERR_STRALLOC); + } } void say_dir(char *code) *************** *** 312,318 **** out_puts("\""); if (!dir.len) out_puts("/"); - else for (i = 0;i < dir.len;++i) { ch = dir.s[i]; if (ch == '\n') out_put("",1); --- 450,455 ---- *************** *** 322,327 **** --- 459,576 ---- out_puts("\" \r\n"); } + int md(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + return mkdir(fn.s,UMASK_MKDIR); + } + + int rd(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + return rmdir(fn.s); + } + + int rm(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&fn,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&fn,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&fn,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&fn,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&fn) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&fn)) _exit(ERR_STRALLOC); + return unlink(fn.s); + } + + int renamefrom(char *arg) + { + if (config.write != 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&rnfr,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&rnfr,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&rnfr,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&rnfr,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&rnfr) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&rnfr)) _exit(ERR_STRALLOC); + return(0); + } + + int renameto(char *arg) + { + int srcfile; + int dstfile; + struct tai mtime1; + unsigned long length1; + struct tai mtime2; + unsigned long length2; + int r; + + if (config.write != 1) return(-1); + if (rnfr.len < 1) return(-1); + if (*arg == '/') { + if (!stralloc_copys(&rnto,arg)) _exit(ERR_STRALLOC); + } + else { + if (!stralloc_copy(&rnto,&dir)) _exit(ERR_STRALLOC); + if (!stralloc_append(&rnto,"/")) _exit(ERR_STRALLOC); + if (!stralloc_cats(&rnto,arg)) _exit(ERR_STRALLOC); + } + if (pathdecode(&rnto) == -1) _exit(ERR_STRALLOC); + if (!stralloc_0(&rnto)) _exit(ERR_STRALLOC); + if (rnto.len < 1) return(-1); + if (fileexist(rnfr.s) != 0) return(-1); + if (fileexist(rnto.s) == 0) return(-1); + dstfile = file_openwrite(rnto.s,&mtime1,&length1,1); + srcfile = file_open(rnfr.s,&mtime2,&length2,1); + if ((dstfile == -1) || (srcfile == -1)) { + close(dstfile); + close(srcfile); + unlink(rnto.s); + return(-1); + } + while (((r=timeoutread(config.toread,srcfile,filebuf,sizeof filebuf)) > 0) && (timeoutwrite(config.towrite,dstfile,filebuf,r) == r)) {}; + if ((close(dstfile) != 0) || (close(srcfile) != 0) || (r == -1)) { + unlink(rnto.s); + return(-1); + } + length1 = filelen(rnfr.s); + length2 = filelen(rnto.s); + if (length1 != length2) { + unlink(rnto.s); + return(-1); + } + unlink(rnfr.s); + return(0); + } + void request(char *cmd,char *arg) { if (case_equals(cmd,"spsv")) { spsv(); return; } *************** *** 331,347 **** if (case_equals(cmd,"retr")) { get(arg,FETCH_RETR); return; } if (case_equals(cmd,"list")) { get(arg,*arg ? FETCH_LISTONE : FETCH_LIST); return; } if (case_equals(cmd,"nlst")) { get(arg,FETCH_NLST); return; } if (case_equals(cmd,"quit")) { ! out_puts("221 Bye.\r\n"); out_flush(); _exit(0); } if (case_equals(cmd,"user")) { ! out_puts("230 Hi. No need to log in; I'm an anonymous ftp server.\r\n"); return; } if (case_equals(cmd,"noop")) { ! out_puts("200 I'm here.\r\n"); return; } if (case_equals(cmd,"pwd") || case_equals(cmd,"xpwd")) { --- 580,599 ---- if (case_equals(cmd,"retr")) { get(arg,FETCH_RETR); return; } if (case_equals(cmd,"list")) { get(arg,*arg ? FETCH_LISTONE : FETCH_LIST); return; } if (case_equals(cmd,"nlst")) { get(arg,FETCH_NLST); return; } + if (case_equals(cmd,"stor")) { put(arg,FETCH_STOR); return; } + if (case_equals(cmd,"appe")) { put(arg,FETCH_APPE); return; } + if (case_equals(cmd,"size")) { filesize(arg); return; } if (case_equals(cmd,"quit")) { ! out_puts(REPLY_QUIT); out_flush(); _exit(0); } if (case_equals(cmd,"user")) { ! out_puts(REPLY_USER); return; } if (case_equals(cmd,"noop")) { ! out_puts(REPLY_NOOP); return; } if (case_equals(cmd,"pwd") || case_equals(cmd,"xpwd")) { *************** *** 360,420 **** } if (case_equals(cmd,"stru")) { if ((*arg == 'f') || (*arg == 'F')) { ! out_puts("200 Thanks, I always do file structure.\r\n"); return; } ! out_puts("504 Sorry, I don't do anything except file structure.\r\n"); return; } if (case_equals(cmd,"mode")) { if ((*arg == 's') || (*arg == 'S')) { ! out_puts("200 Thanks, I always do stream mode.\r\n"); return; } ! out_puts("504 Sorry, I don't do anything except stream mode.\r\n"); return; } if (case_equals(cmd,"type")) { if ((*arg == 'a') || (*arg == 'A')) { ! fetch_ascii = 1; ! out_puts("200 Why are you using ASCII?\r\n"); return; } if ((*arg == 'i') || (*arg == 'I') || (*arg == 'l') || (*arg == 'L')) { ! fetch_ascii = 0; ! out_puts("200 Okay, using binary.\r\n"); return; } ! out_puts("504 Sorry, I don't recognize that type.\r\n"); return; } if (case_equals(cmd,"syst")) { ! out_puts("215 UNIX Type: L8\r\n"); return; } if (case_equals(cmd,"help")) { ! out_puts("214 publicfile home page: http://pobox.com/~djb/publicfile.html\r\n"); return; } if (case_equals(cmd,"pass") || case_equals(cmd,"acct")) { ! out_puts("202 I don't need account information; I'm an anonymous FTP server.\r\n"); return; } ! if (case_equals(cmd,"allo")) { ! out_puts("202 Who cares? I don't allow file creation.\r\n"); return; } ! if (case_equals(cmd,"stor") || case_equals(cmd,"stou") || case_equals(cmd,"appe") || case_equals(cmd,"dele") || case_equals(cmd,"rnfr") || case_equals(cmd,"rnto") || case_equals(cmd,"mkd") || case_equals(cmd,"xmkd") || case_equals(cmd,"rmd") || case_equals(cmd,"xrmd")) { ! out_puts("553 Sorry, I don't allow file modification.\r\n"); return; } ! out_puts("502 Sorry, I don't understand that command.\r\n"); } stralloc line = {0}; ! void doit(void) { char *cmd; char *arg; --- 612,715 ---- } if (case_equals(cmd,"stru")) { if ((*arg == 'f') || (*arg == 'F')) { ! out_puts(REPLY_STRU_FILE); return; } ! out_puts(REPLY_STRU_BAD); return; } if (case_equals(cmd,"mode")) { if ((*arg == 's') || (*arg == 'S')) { ! out_puts(REPLY_MODE_STREAM); return; } ! out_puts(REPLY_MODE_BAD); return; } if (case_equals(cmd,"type")) { if ((*arg == 'a') || (*arg == 'A')) { ! fetch_ascii = TRANSFER_ASCII; ! out_puts(REPLY_TYPE_ASCII); return; } if ((*arg == 'i') || (*arg == 'I') || (*arg == 'l') || (*arg == 'L')) { ! fetch_ascii = TRANSFER_BINARY; ! out_puts(REPLY_TYPE_BINARY); return; } ! out_puts(REPLY_TYPE_BAD); return; } if (case_equals(cmd,"syst")) { ! out_puts(REPLY_SYST); return; } if (case_equals(cmd,"help")) { ! out_puts(REPLY_HELP); return; } if (case_equals(cmd,"pass") || case_equals(cmd,"acct")) { ! out_puts(REPLY_PASS); ! return; ! } ! if (case_equals(cmd,"mkd") || case_equals(cmd,"xmkd")) { ! if (md(arg) == 0) ! out_puts(REPLY_MKD_OK); ! else ! out_puts(REPLY_MKD_BAD); ! return; ! } ! if (case_equals(cmd,"rmd") || case_equals(cmd,"xrmd")) { ! if (rd(arg) == 0) ! out_puts(REPLY_RMD_OK); ! else ! out_puts(REPLY_RMD_BAD); return; } ! if (case_equals(cmd,"dele")) { ! if (rm(arg) == 0) ! out_puts(REPLY_DELE_OK); ! else ! out_puts(REPLY_DELE_BAD); return; } ! if (case_equals(cmd,"rnfr")) { ! if (renamefrom(arg) == 0) ! out_puts(REPLY_RNFR_OK); ! else ! out_puts(REPLY_RNFR_BAD); ! return; ! } ! if (case_equals(cmd,"rnto")) { ! if (renameto(arg) == 0) ! out_puts(REPLY_RNTO_OK); ! else ! out_puts(REPLY_RNTO_BAD); ! return; ! } ! if (case_equals(cmd,"stou") || case_equals(cmd,"allo")) { ! out_puts(REPLY_NOT_ALLOWED); return; } ! out_puts(REPLY_UNKNOWN); } + void do_config(void) + { + char *x; + config.toread = DEFAULT_TIMEOUT_READ; + config.towrite = DEFAULT_TIMEOUT_WRITE; + config.toidle = DEFAULT_TIMEOUT_IDLE; + config.toconn = DEFAULT_TIMEOUT_CONN; + + x = env_get("FTPWRITE"); + if (!x) config.write = 0; + else config.write = 1; + } stralloc line = {0}; ! void doit(int writing) { char *cmd; char *arg; *************** *** 437,456 **** if (!ip_scan(x,&ipremote)) byte_zero(&ipremote,4); ! if (!stralloc_copys(&dir,"")) _exit(21); sig_pipeignore(); for (;;) { ! if (!stralloc_copys(&line,"")) _exit(21); for (;;) { in_get(&ch); if (ch == '\n') break; if (!ch) ch = '\n'; ! if (!stralloc_append(&line,&ch)) _exit(21); } if (line.len && (line.s[line.len - 1] == '\r')) --line.len; ! if (!stralloc_0(&line)) _exit(21); cmd = line.s; arg = cmd + str_chr(cmd,' '); --- 732,755 ---- if (!ip_scan(x,&ipremote)) byte_zero(&ipremote,4); ! if (!stralloc_copys(&dir,"")) _exit(ERR_STRALLOC); sig_pipeignore(); + do_config(); + if (writing==1) config.write = 1; + out_puts(REPLY_WELCOME); + for (;;) { ! if (!stralloc_copys(&line,"")) _exit(ERR_STRALLOC); for (;;) { in_get(&ch); if (ch == '\n') break; if (!ch) ch = '\n'; ! if (!stralloc_append(&line,&ch)) _exit(ERR_STRALLOC); } if (line.len && (line.s[line.len - 1] == '\r')) --line.len; ! if (!stralloc_0(&line)) _exit(ERR_STRALLOC); cmd = line.s; arg = cmd + str_chr(cmd,' '); diff -crN publicfile-0.52/haswaitp.h /usr2/home/one/qftpd-0.10/haswaitp.h *** publicfile-0.52/haswaitp.h Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/haswaitp.h Fri Mar 16 19:37:28 2001 *************** *** 0 **** --- 1 ---- + #define HASWAITPID 1 diff -crN publicfile-0.52/main.c /usr2/home/one/qftpd-0.10/main.c *** publicfile-0.52/main.c Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/main.c Tue Mar 27 21:51:49 2001 *************** *** 1,31 **** #include "env.h" #include "exit.h" #include "scan.h" ! extern void doit(void); main(int argc,char **argv) { char *x; unsigned long id; x = argv[1]; if (x) { ! if (chdir(x) == -1) _exit(20); ! if (chroot(".") == -1) _exit(30); } x = env_get("GID"); ! if (x) { scan_ulong(x,&id); ! if (prot_gid((int) id) == -1) _exit(30); ! } x = env_get("UID"); ! if (x) { scan_ulong(x,&id); ! if (prot_uid((int) id) == -1) _exit(30); ! } ! ! doit(); } --- 1,39 ---- #include "env.h" #include "exit.h" #include "scan.h" + #include "config.h" ! extern void doit(); main(int argc,char **argv) { char *x; unsigned long id; + x = argv[1]; if (x) { ! if (chdir(x) == -1) _exit(ERR_CHDIR); } + if (chroot(".") == -1) _exit(ERR_UIDGID); x = env_get("GID"); ! if (x) scan_ulong(x,&id); ! else ! id=DEFAULT_GID; ! if (id < DEFAULT_MINGID) _exit(ERR_UIDGID); ! if (prot_gid((int) id) == -1) _exit(ERR_UIDGID); x = env_get("UID"); ! if (x) scan_ulong(x,&id); ! else ! id=DEFAULT_UID; ! if (id < DEFAULT_MINUID) _exit(ERR_UIDGID); ! if (prot_uid((int) id) == -1) _exit(ERR_UIDGID); ! ! if (argc > 2) x = argv[2]; ! if (x[0] == 'w') doit(1); ! doit(0); } diff -crN publicfile-0.52/open_trunc.c /usr2/home/one/qftpd-0.10/open_trunc.c *** publicfile-0.52/open_trunc.c Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/open_trunc.c Sat Mar 10 13:21:52 2001 *************** *** 4,6 **** --- 4,9 ---- int open_trunc(fn) char *fn; { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } + + int open_append(fn) char *fn; + { return open(fn,O_WRONLY | O_NDELAY | O_APPEND); } diff -crN publicfile-0.52/pathdecode.c /usr2/home/one/qftpd-0.10/pathdecode.c *** publicfile-0.52/pathdecode.c Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/pathdecode.c Sun Mar 11 20:24:10 2001 *************** *** 1,6 **** #include "pathdecode.h" ! void pathdecode(stralloc *fn) { int i; int j; --- 1,57 ---- #include "pathdecode.h" ! ! /*int pathdecode(char *arg, stralloc *dir) ! { ! int i; //index into arg, arg is the null terminated path string ! char x; //current character ! char w; //previous character ! int len; //temp len variable for str_len ! ! len = str_len(PATH_OKCHARS); ! i = 0; ! if (!stralloc_copys(&fn,"./")) _exit(21); //start every path with a '/' character ! // if (arg[0] == '/') i++; //if user specifies a slash, account for it ! ! if (*arg != '/') { ! if (!stralloc_cat(&fn,&dir)) _exit(21); ! if (!stralloc_append(&fn,"/")) _exit(21); ! } ! else i++; ! for (i=i; i0) { ! w = arg[i-1]; ! if (w == '/') { ! if (x == '/') return(-1); ! #ifdef HIDE_DOT_FILES ! if (x == '.') { ! #ifdef MANGLE_PATH ! x = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif ! #endif ! } ! } ! } ! if (str_chr(PATH_OKCHARS,x) == len) { ! #ifdef MANGLE_PATH ! x = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif ! } ! arg[i] = x; ! } ! if (!stralloc_cat(&fn,&arg)) _exit(21); ! if (!stralloc_0(&fn)) _exit(21); ! return(0); ! } ! */ ! int pathdecode(stralloc *fn) { int i; int j; *************** *** 11,20 **** ch = fn->s[i]; if (ch == 0) ch = '\n'; if (j && (fn->s[j - 1] == '/')) { ! if (ch == '.') ch = ':'; ! if (ch == '/') continue; } fn->s[j++] = ch; } fn->len = j; } --- 62,89 ---- ch = fn->s[i]; if (ch == 0) ch = '\n'; if (j && (fn->s[j - 1] == '/')) { ! #ifdef HIDE_DOT_FILES ! if (ch == '.') { ! #ifdef MANGLE_PATH ! ch = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif ! } ! #endif ! // if (ch == '/') continue; ! } ! if (str_chr(PATH_OKCHARS,fn->s[j]) == str_len(PATH_OKCHARS)) { ! #ifdef MANGLE_PATH ! ch = MANGLE_PATH_CHAR; ! #endif ! #ifndef MANGLE_PATH ! return(-1); ! #endif } fn->s[j++] = ch; } fn->len = j; + return(0); } diff -crN publicfile-0.52/pathdecode.h /usr2/home/one/qftpd-0.10/pathdecode.h *** publicfile-0.52/pathdecode.h Tue Nov 9 02:23:46 1999 --- /usr2/home/one/qftpd-0.10/pathdecode.h Sun Mar 11 20:21:16 2001 *************** *** 1,8 **** #ifndef PATHDECODE_H #define PATHDECODE_H ! #include "stralloc.h" ! extern void pathdecode(stralloc *); #endif --- 1,9 ---- #ifndef PATHDECODE_H #define PATHDECODE_H ! #include "config.h" ! #include "server.h" ! extern int pathdecode(stralloc *); #endif diff -crN publicfile-0.52/rmtargets /usr2/home/one/qftpd-0.10/rmtargets *** publicfile-0.52/rmtargets Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/rmtargets Tue Mar 27 22:23:24 2001 *************** *** 0 **** --- 1,122 ---- + #!/bin/sh + rm load + rm compile + rm systype + rm hasdevtcp.h + rm configure.o + rm auto-str.o + rm makelib + rm substdio.o + rm substdi.o + rm substdo.o + rm substdio_copy.o + rm subfderr.o + rm substdio.a + rm error.o + rm error_str.o + rm error_temp.o + rm error.a + rm byte_chr.o + rm byte_copy.o + rm byte_cr.o + rm byte_diff.o + rm byte_rchr.o + rm byte_zero.o + rm str_chr.o + rm str_diff.o + rm str_len.o + rm str_rchr.o + rm str_start.o + rm str.a + rm auto-str + rm auto_home.c + rm auto_home.o + rm strerr_die.o + rm strerr_sys.o + rm strerr.a + rm open_read.o + rm open_trunc.o + rm open.a + rm configure + rm choose + rm uint64.h + rm httpd.o + rm main.o + rm pathdecode.o + rm file.o + rm filetype.o + rm httpdate.o + rm percent.o + rm chkshsgr.o + rm chkshsgr + rm hasshsgr.h + rm prot.o + rm select.h + rm timeoutread.o + rm timeoutwrite.o + rm caldate_fmjd.o + rm caltime_utc.o + rm leapsecs_init.o + rm leapsecs_read.o + rm leapsecs_sub.o + rm tai_now.o + rm tai_sub.o + rm tai_unpack.o + rm libtai.a + rm case_diffs.o + rm case_lowerb.o + rm case_startb.o + rm case.a + rm getln.o + rm getln2.o + rm getln.a + rm stralloc_cat.o + rm stralloc_catb.o + rm stralloc_cats.o + rm stralloc_copy.o + rm stralloc_eady.o + rm stralloc_opyb.o + rm stralloc_opys.o + rm stralloc_pend.o + rm stralloc_num.o + rm stralloc.a + rm alloc.o + rm alloc_re.o + rm alloc.a + rm hassgprm.h + rm sig_block.o + rm hassgact.h + rm sig_catch.o + rm sig_pause.o + rm sig_pipe.o + rm sig.a + rm env.o + rm env.a + rm fmt_str.o + rm fmt_uint.o + rm fmt_ulong.o + rm fmt_xlong.o + rm scan_ulong.o + rm fs.a + rm socket.lib + rm httpd + rm ftpd.o + rm direntry.h + rm fetch.o + rm ip.o + rm timeoutconn.o + rm timeoutaccept.o + rm ndelay_on.o + rm ndelay_off.o + rm ndelay.a + rm ftpd + rm rts + rm prog + rm install.o + rm hier.o + rm install + rm instcheck.o + rm instcheck + rm it + rm setup + rm check diff -crN publicfile-0.52/server.h /usr2/home/one/qftpd-0.10/server.h *** publicfile-0.52/server.h Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/server.h Tue Mar 13 13:44:22 2001 *************** *** 0 **** --- 1,19 ---- + #ifndef SERVER_H + #define SERVER_H + + #include "stralloc.h" + + typedef struct { + int toread; //reading i/o timeout seconds + int towrite; //writing i/o timeout seconds + int toidle; //idle timeout seconds + int toconn; //connection timeout seconds + int write; //1=writing enabled, else=writing disabled + } ServerConfig; + + extern ServerConfig config; + extern stralloc dir; + extern stralloc fn; + extern stralloc rnfr; + extern stralloc rnto; + #endif diff -crN publicfile-0.52/wait.3 /usr2/home/one/qftpd-0.10/wait.3 *** publicfile-0.52/wait.3 Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/wait.3 Fri Mar 16 19:37:22 2001 *************** *** 0 **** --- 1,93 ---- + .TH wait 3 + .SH NAME + wait \- check child process status + .SH SYNTAX + .B #include + + int \fBwait_nohang\fP(&\fIwstat\fR); + .br + int \fBwait_stop\fP(&\fIwstat\fR); + .br + int \fBwait_stopnohang\fP(&\fIwstat\fR); + .br + int \fBwait_pid\fP(&\fIwstat\fR,\fIpid\fR); + + int \fBwait_exitcode\fP(\fIwstat\fR); + .br + int \fBwait_crashed\fP(\fIwstat\fR); + .br + int \fBwait_stopped\fP(\fIwstat\fR); + .br + int \fBwait_stopsig\fP(\fIwstat\fR); + + int \fIpid\fR; + .br + int \fIwstat\fR; + .SH DESCRIPTION + .B wait_nohang + looks for zombies (child processes that have exited). + If it sees a zombie, + it eliminates the zombie, + puts the zombie's exit status into + .IR wstat , + and returns the zombie's process ID. + If there are several zombies, + .B wait_nohang + picks one. + If there are children but no zombies, + .B wait_nohang + returns 0. + If there are no children, + .B wait_nohang + returns -1, + setting + .B errno + appropriately. + + .B wait_stopnohang + is similar to + .BR wait_nohang , + but it also looks for children that have stopped. + + .B wait_stop + is similar to + .BR wait_stopnohang , + but if there are children it will pause waiting for one of them + to stop or exit. + + .B wait_pid + waits for child process + .I pid + to exit. + It eliminates any zombie that shows up in the meantime, + discarding the exit status. + + .B wait_stop + and + .B wait_pid + retry upon + .BR error_intr . + .SH "STATUS PARSING" + If the child stopped, + .B wait_stopped + is nonzero; + .B wait_stopsig + is the signal that caused the child to stop. + + If the child exited by crashing, + .B wait_stopped + is zero; + .B wait_crashed + is nonzero. + + If the child exited normally, + .B wait_stopped + is zero; + .B wait_crashed + is zero; + and + .B wait_exitcode + is the child's exit code. + .SH "SEE ALSO" + wait(2), + error(3) diff -crN publicfile-0.52/wait.h /usr2/home/one/qftpd-0.10/wait.h *** publicfile-0.52/wait.h Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/wait.h Fri Mar 16 19:37:22 2001 *************** *** 0 **** --- 1,14 ---- + #ifndef WAIT_H + #define WAIT_H + + extern int wait_pid(); + extern int wait_nohang(); + extern int wait_stop(); + extern int wait_stopnohang(); + + #define wait_crashed(w) ((w) & 127) + #define wait_exitcode(w) ((w) >> 8) + #define wait_stopsig(w) ((w) >> 8) + #define wait_stopped(w) (((w) & 127) == 127) + + #endif diff -crN publicfile-0.52/wait_nohang.c /usr2/home/one/qftpd-0.10/wait_nohang.c *** publicfile-0.52/wait_nohang.c Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/wait_nohang.c Fri Mar 16 19:37:22 2001 *************** *** 0 **** --- 1,12 ---- + #include + #include + #include "haswaitp.h" + + int wait_nohang(wstat) int *wstat; + { + #ifdef HASWAITPID + return waitpid(-1,wstat,WNOHANG); + #else + return wait3(wstat,WNOHANG,(struct rusage *) 0); + #endif + } diff -crN publicfile-0.52/wait_pid.c /usr2/home/one/qftpd-0.10/wait_pid.c *** publicfile-0.52/wait_pid.c Wed Dec 31 19:00:00 1969 --- /usr2/home/one/qftpd-0.10/wait_pid.c Fri Mar 16 19:37:22 2001 *************** *** 0 **** --- 1,39 ---- + #include + #include + #include "error.h" + #include "haswaitp.h" + + #ifdef HASWAITPID + + int wait_pid(wstat,pid) int *wstat; int pid; + { + int r; + + do + r = waitpid(pid,wstat,0); + while ((r == -1) && (errno == error_intr)); + return r; + } + + #else + + /* XXX untested */ + /* XXX breaks down with more than two children */ + static int oldpid = 0; + static int oldwstat; /* defined if(oldpid) */ + + int wait_pid(wstat,pid) int *wstat; int pid; + { + int r; + + if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } + + do { + r = wait(wstat); + if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } + } + while ((r == -1) && (errno == error_intr)); + return r; + } + + #endif