home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <error.h>
- #include <stat.h>
- #include <dos.h>
- #include <sys/ioctl.h>
- #include <sys/dir.h>
- #include <lineread.h>
- #include <sys/socket.h>
- #include <exec/memory.h>
- #include <dos/dostags.h>
- #include <libraries/multiuser.h>
-
- #include <proto/exec.h>
- #include <proto/socket.h>
- #include <proto/multiuser.h>
- #include <proto/dos.h>
-
- #include "ftp.h"
-
- struct muBase *muBase;
- extern LONG server_socket;
-
- char VersionTag[]="\0$VER: JoranFtpd 2.0 (14.12.93)";
-
- char Hostname[40]="unknown";
- char Version[]="Joran 2.0";
-
- char buf2[512];
- int tt1, tt2, tnw;
- int pdata=-1; // For passive mode
- struct FileInfoBlock *PermChkFib;
- struct muUserInfo *UserInfo;
-
- long gethostname(char *,long len);
-
- struct LineRead *LineRead;
-
- /* Command table */
- static char *commands[] = {
- "user",
- "acct",
- "pass",
- "type",
- "list",
- "cwd",
- "dele",
- "name",
- "quit",
- "retr",
- "stor",
- "port",
- "nlst",
- "pwd",
- "xpwd", /* For compatibility with 4.2BSD */
- "mkd ",
- "xmkd", /* For compatibility with 4.2BSD */
- "xrmd", /* For compatibility with 4.2BSD */
- "rmd ",
- "stru",
- "mode",
- "pasv", /* Pasive mode */
- NULL
- };
-
- /* Response messages */
- static char binwarn[] = "100 Warning: File %s appears to be BINARY\n";
- static char sending[] = "150 Open %s for %s %s (%ld Bytes)\n";
- static char recving[] = "150 Open %s for %s %s\n";
-
- static char typeok[] = "200 Type %s OK\n";
- static char mkdok[] = "200 MKD ok\n";
- static char portok[] = "200 Port command okay\n";
- static char okay[] = "200 Ok\n";
- static char banner[] = "220 %s FTP Ready - v%s\n";
- static char bye[] = "221 Goodbye!\n";
- static char rxok[] = "226 File received OK\n";
- static char txok[] = "226 File sent OK\n";
- static char logged[] = "230 %s Logged in, %s\n";
- static char loggeda[] = "230 %s Logged in as anonymous, %s\n";
- static char deleok[] = "250 File deleted\n";
- static char pwdmsg[] = "257 \"%s\" is current directory\n";
-
- static char givepass[] = "331 Enter Password\n";
- static char givepasa[] = "331 Please enter your email address '<user-id>@<host-name>'\n";
-
- static char lowmem[] = "421 System overloaded, try again later\n";
- static char noconn[] = "425 Data connection reset\n";
-
- static char unsupp[] = "500 Unsupported command or option\n";
- static char badcmd[] = "500 Unknown command\n";
- static char only8[] = "501 Only logical bytesize 8 supported\n";
- static char badtype[] = "501 Unknown type \"%s\"\n";
- static char badport[] = "501 Bad port syntax\n";
- static char unimp[] = "502 Command not yet implemented\n";
- static char userfirst[] = "503 Login with USER first.\n";
- static char notlog[] = "530 Please log in with USER and PASS\n";
- static char noperm[] = "550 Permission denied\n";
- static char cantopen[] = "550 Can't read file \"%s\": %s\n";
- static char delefail[] = "550 Delete failed: %s\n";
- static char writerr[] = "552 Write error: %s\n";
- static char nodir[] = "553 Can't read directory \"%s\": %s\n";
- static char cantmake[] = "553 Can't create \"%s\": %s\n";
- static char notyet[] = "555 Try Later : Access '%2d:00-%2d:59 %s' only\n";
- static char nopasv[] = "425 Can't open passive connection\n";
- static char pasvcon[] = "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\n";
-
- void CloseAll(void)
- {
- if(UserInfo) muFreeUserInfo(UserInfo);
- if(PermChkFib) FreeDosObject(DOS_FIB,PermChkFib);
- if(LineRead) FreeMem(LineRead,sizeof(struct LineRead));
- if(muBase) CloseLibrary((struct Library *)muBase);
-
- if(LogLevel>=20) AddLog("FTPDeamon Stopped",FindTask(NULL));
- }
-
- void InitAll(void)
- {
- atexit(CloseAll);
-
- SetProgramName("JoranFtpd");
- muBase=(struct muBase *)OpenLibrary(MULTIUSERNAME,MULTIUSERVERSION);
- if(muBase && !(UserInfo=muAllocUserInfo())) exit(20);
- gethostname(Hostname,sizeof(Hostname));
- if(!(LineRead=AllocMem(sizeof(struct LineRead),MEMF_ANY))) exit(20);
- initLineRead(LineRead,server_socket,RL_LFREQLF,RL_BUFSIZE);
- if(!(PermChkFib=AllocDosObject(DOS_FIB,NULL))) exit(20);
- }
-
- /* replace terminating end of line marker(s) with null */
- void rip(char *s)
- {
- char *cp;
- if((cp = strchr(s,'\n')) != NULL) *cp = '\0';
- if((cp = strchr(s,'\r')) != NULL) *cp = '\0';
- }
-
- /* This checks the current time is in a preset Time-Window before
- allowing a user to login */
- int timewind(int argc,char *argv[],void *p)
- {
- char *now;
- long t;
- char *t1, *t2;
-
- t1 = strdup(curftwin);
- *(t1 + 2) = '\0';
- tt1 = atoi(t1);
-
- t2 = strdup(curftwin+2);
- *(t2 + 2) = '\0';
- tt2 = atoi(t2);
-
- time(&t);
- now = ctime(&t) + 11;
- *(now + 2) = '\0';
- tnw = atoi(now);
-
- if(tt1 > tt2) {
- if(((tnw >= tt1) && (tnw <= 23)) ||
- ((tnw <= tt2) && (tnw >= 0)))
- return 0; /* right in time */
- } else {
- if((tnw >= tt1) && (tnw <= tt2))
- return 0; /* right in time */
- }
-
- return 1;
- }
-
- /* Return 1 if the file operation is allowed, 0 otherwise */
- int permcheck(char *path,int perms,int op,char *file)
- {
- BPTR l;
- BYTE prot;
-
- if(file == NULL || path == NULL)
- return 0; /* Probably hasn't logged in yet */
-
- /* The target file must be under the user's allowed search path */
- if(strncmp(file,path,strlen(path)) != 0)
- return 0;
-
- prot=-1;
- // if(muBase & perms&FTP_MULTIUSER)
- // {
- // Check default protection
- // if(l=Lock(file,ACCESS_READ))
- // {
- // if(Examine(l,PermChkFib))
- // {
- // if(UserInfo->uid==muNOBODYUID)
- // {
- //
- // }
- // if(UserInfo->uid==PermChkFib->fib_OwnerUID)
- // {
- // }
- // if(UserInfo->gid==PermChkFib->fib_GroupUID)
- // {
- // }
- //
- // }
- // UnLock(l);
- // }
- // }
-
- if(l=Lock(file,ACCESS_READ)) UnLock(l);
-
- switch(op){
- case RETR_CMD:
- /* User must have permission to read files */
- if(perms&FTP_READ && prot&FIBF_READ)
- return 1;
- return 0;
- case DELE_CMD:
- case RMD_CMD:
- /* User must have permission to (over)write files */
- if(perms&FTP_WRITE && prot&FIBF_DELETE)
- return 1;
- return 0;
- case STOR_CMD:
- case MKD_CMD:
- /* User must have permission to (over)write files, or permission
- * to create them if the file doesn't already exist
- */
- if(!l && perms&FTP_CREATE) return 1;
- if(l && perms&FTP_WRITE && prot&FIBF_DELETE)
- return 1;
- return 0;
- }
- return 0; /* "can't happen" -- keep lint happy */
- }
-
- /* Subroutine for logging in the user whose name is name and
- password is pass. The buffer path should be long enough to
- keep a line from the userfile. If pwdignore is true, the
- password check will be overridden. The return value is the
- permissions field or -1 if the login failed. Path is set to
- point at the path field, and pwdignore will be true if no
- particular password was needed for this user.
- */
- int userlogin(char *name,char *pass,char **path,int len,int *pwdignore)
- {
- char *cp,*cp1;
- FILE *fp;
- char *rest = NULL;
- int anony, perm;
- int unknown=FALSE;
-
- *pwdignore=!strcmp("ftp",name);
- anony = *pwdignore;
-
- if((fp = fopen(Userfile,"r")) == NULL) return -1; /* Userfile doesn't exist */
-
- while(fgets(*path,len,fp),!feof(fp))
- {
- if(*path[0] == '#') continue; /* Comment */
- if((cp=strchr(*path,' '))==NULL) continue; /* Bogus entry */
- *cp++ = '\0'; /* Now points to password */
-
- if(stricmp(name,*path)==0) break; /* Found user name */
- if(stricmp("rest",*path)==0) rest=strdup(cp); /* remember default entry */
- }
- unknown=feof(fp);
- if((rest==NULL) && unknown)
- {
- /* User not in file, nor was anonymous */
- fclose(fp);
- return -1;
- }
- if(unknown)
- {
- /* restore default entry */
- strcpy(cp = *path, rest);
- }
- fclose(fp);
-
- /* Look for space after password field in file */
- if((cp1 = strchr(cp,' ')) == NULL) return -1; /* Invalid file entry */
-
- *cp1++ = '\0'; /* Now points to path field */
- if(strcmp(cp,"*")!=0)
- {
- if(strcmp(cp,pass)!=0) return -1; /* Password required, but wrong one given */
- }
- if((cp = strchr(cp1,' ')) == NULL) return -1; /* Permission field missing */
-
- *cp++ = '\0'; /* now points to permission field */
- perm = atoi(cp);
-
- if(unknown && (!muBase || !perm&FTP_MULTIUSER)) return -1;
-
- if(muBase && perm&FTP_MULTIUSER)
- {
- strncpy(UserInfo->UserID,name,muUSERIDSIZE);
- if(!muGetUserInfo(UserInfo,muKeyType_UserID))
- {
- if(LogLevel>=10) AddLog("Unknown User \"%s\"",name);
- return -1;
- }
- if(!muLogin(
- muT_UserID,UserInfo->UserID,
- muT_Password,anony?"":pass,
- TAG_DONE
- ))
- {
- if(LogLevel>=10) AddLog("Wrong password for \"%s\"",UserInfo->UserID);
- return -1;
- }
- }
-
- /*
- * Well, on the Amiga, a file can be referenced by many names:
- * device names (DF0:) or volume names (My_Disk:). This hunk of code
- * passed the pathname specified in the ftpusers file, and gets the
- * absolute path copied into the user's buffer. We really should just
- * allocate the buffer and return a pointer to it, since the caller
- * really doesn't have a good idea how long the path string is..
- */
- if(cp1[0]=='*') cp1=strdup("");
- else cp1=pathname("",cp1);
-
- if (cp1) strcpy(*path, cp1);
- else **path = '\0';
- free(cp1);
-
- /* Finally return the permission bits */
- return perm;
- }
-
- /* Attempt to log in the user whose name is in ftp->username and password
- * in pass
- */
- static void ftplogin(struct ftpserv *ftp,char *pass)
- {
- long t;
- char *path,buf2[77],*cp,*cp1;
- int anony = 0;
- FILE *fp;
-
- path = malloc(200);
- if((ftp->perms=userlogin(ftp->username,pass,&path,200,&anony)) == -1)
- {
- usprintf(ftp->control,noperm);
- free(path);
- return;
- }
- /* Set up current directory and path prefix */
- if(*path) ftp->cd=strdup(path);
- else
- {
- if(muBase) ftp->cd=pathname(UserInfo->HomeDir,"");
- else ftp->cd=pathname(":","");
- }
- ftp->path = strdup(path);
- free(path);
-
- sprintf(buf2,"%sFTP.After",SignOn);
- if((fp = fopen(buf2,"r")) != NULL)
- {
- sendfile(fp,ftp->control,ASCII_TYPE,0);
- fclose(fp);
- }
-
- time(&t);
- cp = ctime(&t);
- if((cp1 = strchr(cp,'\n')) != NULL) *cp1 = '\0';
-
- if(!anony)
- {
- usprintf(ftp->control,logged,ftp->username,cp);
- if(LogLevel>=15) AddLog("%s logged in",ftp->username);
- }
- else
- {
- usprintf(ftp->control,loggeda,
- strcmp(ftp->username,"ftp") ?
- ftp->username : "",cp);
- if(LogLevel>=15) AddLog("%s logged in, ID %s",ftp->username,pass);
- }
- }
-
- static int sendit(struct ftpserv *ftp,char *command,char *file)
- {
- long total;
- struct sockaddr_in dport;
- struct stat stb;
-
- ftp->data = socket(AF_INET,SOCK_STREAM,0);
- dport.sin_family=AF_INET;
- dport.sin_addr.s_addr=INADDR_ANY;
- dport.sin_port=IPPORT_FTPD;
- bind(ftp->data,(struct sockaddr *)&dport,sizeof(struct sockaddr_in));
-
- stat(file,&stb);
- usprintf(ftp->control,sending,file,ftp->type ? "BINARY" : "ASCII",command,stb.st_size);
- if(connect(ftp->data,(struct sockaddr *)&ftp->port,sizeof(struct sockaddr_in)) == -1){
- fclose(ftp->fp);
- ftp->fp = NULL;
- CloseSocket(ftp->data);
- ftp->data = -1;
- ftp->pdata = -1;
- usprintf(ftp->control,noconn);
- return -1;
- }
- //#ifdef FTPTDISC
- /* Turn of the timeout timer here, some ftp's could
- * take a long time with sloooow packet channels - WG7J
- */
- // stop_timer(&ftp->tdisc);
- //#endif
- /* Do the actual transfer */
- total = sendfile(ftp->fp,ftp->data,ftp->type,0);
-
- //#ifdef FTPTDISC
- /* And turn it back on now */
- // start_timer(&ftp->tdisc);
- //#endif
- if(total == -1)
- {
- /* An error occurred on the data connection */
- usprintf(ftp->control,noconn);
- shutdown(ftp->data,2); /* Blow away data connection */
- } else usprintf(ftp->control,txok);
-
- fclose(ftp->fp);
- ftp->fp = NULL;
- CloseSocket(ftp->data);
- ftp->data = -1;
- ftp->pdata = -1;
- if(total == -1) return -1;
- else return 0;
- }
-
- int recvit(struct ftpserv *ftp,char *command,char *file)
- {
- struct sockaddr_in dport;
- long total;
-
- ftp->data=socket(AF_INET,SOCK_STREAM,0);
- dport.sin_family=AF_INET;
- dport.sin_addr.s_addr=INADDR_ANY;
- dport.sin_port = IPPORT_FTPD;
- bind(ftp->data,(struct sockaddr *)&dport,sizeof(struct sockaddr_in));
- usprintf(ftp->control,recving,file,ftp->type?"BINARY":"ASCII",command);
- if(connect(ftp->data,(struct sockaddr *)&ftp->port,sizeof(struct sockaddr_in)) == -1)
- {
- fclose(ftp->fp);
- ftp->fp = NULL;
- CloseSocket(ftp->data);
- ftp->data = -1;
- ftp->pdata = -1;
- usprintf(ftp->control,noconn);
- return -1;
- }
-
- //#ifdef FTPTDISC
- /* Turn of the timeout timer here; some ftp's could
- * take a long time with sloooow packet channels - WG7J
- */
- // stop_timer(&ftp->tdisc);
- //#endif
-
- /* Do the actual transfer */
- total = recvfile(ftp->fp,ftp->data,ftp->type,0);
-
- //#ifdef FTPTDISC
- /* And turn it back on now */
- // start_timer(&ftp->tdisc);
- //#endif
-
- if(total == -1)
- {
- /* An error occurred while writing the file */
- usprintf(ftp->control,writerr,sys_errlist[errno]);
- shutdown(ftp->data,2); /* Blow it away */
- }
- else
- {
- usprintf(ftp->control,rxok);
- CloseSocket(ftp->data);
- }
- ftp->data = -1;
- ftp->pdata = -1;
- fclose(ftp->fp);
- ftp->fp = NULL;
- if(total == -1) return -1;
- else return 0;
- }
-
- static int pport(struct sockaddr_in *sock,char *arg)
- {
- int n;
- int i;
-
- n = 0;
- for(i=0;i<4;i++)
- {
- n = atoi(arg) + (n << 8);
- if((arg = strchr(arg,',')) == NULL) return -1;
- arg++;
- }
- sock->sin_addr.s_addr = n;
- n = atoi(arg);
- if((arg = strchr(arg,',')) == NULL) return -1;
- arg++;
- n = atoi(arg) + (n << 8);
- sock->sin_port = n;
- return 0;
- }
-
- FILE *dir(char *path,int full)
- {
- int ftotal=0, fnumbr=0;
- BPTR FrameLock_p;
- struct FileInfoBlock *fib_p;
- FILE *f;
- char wildcard[40],*p=NULL;
- char parsecard[82];
-
- if(strchr(path,'*') || strchr(path,'?')) p=FilePart(path);
- if(p)
- {
- strncpy(wildcard,p,sizeof(wildcard));
- wildcard[sizeof(wildcard)-1]='\0';
- p=PathPart(path);
- if(p) *p='\0';
- } else strcpy(wildcard,"*");
-
- if(ParsePatternNoCase(wildcard,parsecard,sizeof(parsecard))<=0) return NULL;
-
- if((f=tmpfile())==NULL) return NULL;
-
- if(FrameLock_p=Lock(path,ACCESS_READ))
- {
- if (fib_p=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
- {
- if(Examine(FrameLock_p,fib_p))
- {
- if(fib_p->fib_DirEntryType<0)
- fprintf(f,"You can only use this command with a Directory Name\n");
- else
- {
- if(full) fprintf(f," Size File/Dir Name Comment\n");
- while(ExNext(FrameLock_p,fib_p))
- {
- if(MatchPatternNoCase(parsecard,fib_p->fib_FileName))
- {
- if(full)
- {
- if(fib_p->fib_DirEntryType>0)
- {
- fprintf(f," (Dir) ");
- }
- else if(fib_p->fib_Size == 0)
- {
- fprintf(f," (empty) ");
- }
- else
- {
- ftotal=ftotal+fib_p->fib_Size;
- fnumbr++;
- fprintf(f,"%8d ",fib_p->fib_Size);
- }
-
- fprintf(f,"%-16s", fib_p->fib_FileName);
- fprintf(f,strlen(fib_p->fib_Comment) ? " : %-30s\n" : "\n",
- fib_p->fib_Comment);
- }
- else if(fib_p->fib_DirEntryType<0) fprintf(f,"%s\n", fib_p->fib_FileName);
- }
- }
- if(full)
- fprintf(f, "Directory %s : %d Bytes : %d Files\n", path, ftotal, fnumbr);
- }
- }
- FreeMem(fib_p,sizeof(struct FileInfoBlock));
- }
- UnLock(FrameLock_p);
- }
-
- rewind(f);
-
- return f;
- }
-
- FILE *extdir(char *arg)
- {
- BPTR f;
- FILE *fp;
- char fn[30];
-
- sprintf(fn,"T:JoranFtpd%08X",FindTask(NULL));
-
- if(*arg) sprintf(buf2,ArgDirCommand,arg);
- else sprintf(buf2,DefDirCommand,arg);
- if(LogLevel>=30) AddLog("%s",buf2);
- if(f=Open(fn,MODE_NEWFILE))
- {
- SystemTags(buf2,
- SYS_Output,f,
- TAG_DONE
- );
- Close(f);
- if(fp=fopen(fn,"r")) return fp;
- }
-
- return NULL;
- }
-
- /* Note: a response of 425 is not mentioned as a possible response to the
- * PASV command in RFC959. However, it has been blessed as a legitimate
- * response by Jon Postel in a telephone conversation with Rick Adams on 25
- * Jan 89. */
- void passive(struct ftpserv *ftp)
- {
- LONG len;
- register char *p,*a;
-
- ftp->pdata = socket(AF_INET, SOCK_STREAM, 0);
- if (ftp->pdata < 0) {
- usprintf(ftp->control,nopasv);
- return;
- }
- ftp->pasv = ftp->port;
- ftp->pasv.sin_port = 0;
- // (void) seteuid((uid_t) 0);
- if (bind(ftp->pdata, (struct sockaddr *) &ftp->pasv, sizeof(ftp->pasv)) < 0) {
- // (void) seteuid((uid_t) pw->pw_uid);
- goto pasv_error;
- }
- //(void) seteuid((uid_t) pw->pw_uid);
- len = sizeof(ftp->pasv);
- if (getsockname(ftp->pdata, (struct sockaddr *) &ftp->pasv, &len) < 0)
- goto pasv_error;
- if (listen(ftp->pdata, 1) < 0)
- goto pasv_error;
- a = (char *) &ftp->pasv.sin_addr;
- p = (char *) &ftp->pasv.sin_port;
-
- #define UC(b) (((int) b) & 0xff)
-
- usprintf(ftp->control,pasvcon,
- UC(a[0]),UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
- return;
-
- pasv_error:
- CloseSocket(ftp->pdata);
- ftp->pdata = -1;
- usprintf(ftp->control,nopasv);
- return;
- }
-
- main()
- {
- struct ftpserv ftp;
- FILE *fp;
- long l,cnt;
- char *buf,*arg;
- char **cmdp,*p;
- char *file,*mode;
- fd_set readfds;
-
- AddLog("FTPDeamon Initialising");
-
- if(server_socket==-1) exit(20);
-
- InitAll();
- ReadConfig();
-
- memset((char *)&ftp,0,sizeof(ftp)); /* Start with clear slate */
- ftp.data=-1;
- ftp.pdata=-1;
- ftp.control=server_socket;
- l=sizeof(struct sockaddr_in);
- getpeername(server_socket,(struct sockaddr *)&ftp.port,&l);
- ftp.port.sin_port=IPPORT_FTPD;
-
- if(LogLevel>=20) AddLog("FTPDeamon started",FindTask(NULL));
-
- sprintf(buf2,"%sFTP.Before",SignOn);
- if((fp=fopen(buf2,"r"))!=NULL)
- {
- sendfile(fp,server_socket,ASCII_TYPE,0);
- fclose(fp);
- }
-
- usprintf(server_socket,banner,Hostname,Version);
-
- FD_ZERO(&readfds);
-
- for(;;)
- {
- FD_SET(server_socket,&readfds);
- if (select(server_socket+1,&readfds,NULL,NULL,NULL)<0) break;
- if(!FD_ISSET(server_socket,&readfds)) continue;
-
- cnt=lineRead(LineRead);
-
- if(cnt==0) continue; // EOF
- if(cnt==-1)
- {
- if(LineRead->rl_Line==NULL) goto finish;
- continue;
- }
-
- buf=LineRead->rl_Line;
- rip(buf);
-
- AddLog("%s",buf);
-
- /* Find command in table; if not present, return syntax error */
- for(cmdp=commands;*cmdp != NULL;cmdp++)
- if(strnicmp(*cmdp,buf,strlen(*cmdp)) == 0)
- break;
- if(*cmdp == NULL){
- usprintf(ftp.control,badcmd);
- continue;
- }
- /* Allow only USER, PASS, QUIT before logging in */
- if(ftp.cd == NULL || ftp.path == NULL){
- switch(cmdp-commands){
- case USER_CMD:
- case PASS_CMD:
- case QUIT_CMD:
- break;
- default:
- usprintf(ftp.control,notlog);
- continue;
- }
- }
- arg = &buf[strlen(*cmdp)];
- while(*arg == ' ') arg++;
-
- switch(cmdp-commands)
- {
- case USER_CMD:
- if(timewind(NULL,NULL,NULL)) {
- usprintf(ftp.control,notyet,tt1,tt2,
- ((p = getenv("TZ")) == NULL) ? "GMT" : p);
- goto finish;
- }
- free(ftp.username);
- if(!strcmp("anonymous",arg)) ftp.username=strdup("ftp");
- else ftp.username=strdup(arg);
- if(!stricmp("ftp",ftp.username)) usprintf(ftp.control,givepasa);
- else usprintf(ftp.control,givepass);
- break;
- case TYPE_CMD:
- switch(arg[0])
- {
- case 'A':
- case 'a': /* Ascii */
- ftp.type = ASCII_TYPE;
- usprintf(ftp.control,typeok,arg);
- break;
- case 'l':
- case 'L':
- while(*arg != ' ' && *arg != '\0') arg++;
- if(*arg == '\0' || *++arg != '8')
- {
- usprintf(ftp.control,only8);
- break;
- }
- ftp.type = LOGICAL_TYPE;
- ftp.logbsize = 8;
- usprintf(ftp.control,typeok,arg);
- break;
- case 'B':
- case 'b': /* Binary */
- case 'I':
- case 'i': /* Image */
- ftp.type = IMAGE_TYPE;
- usprintf(ftp.control,typeok,arg);
- break;
- default: /* Invalid */
- usprintf(ftp.control,badtype,arg);
- break;
- }
- break;
- case QUIT_CMD:
- usprintf(ftp.control,bye);
- goto finish;
- case RETR_CMD:
- if(timewind(NULL,NULL,NULL))
- {
- usprintf(ftp.control,notyet,tt1,tt2,
- ((p = getenv("TZ")) == NULL) ? "GMT" : p);
- goto finish;
- }
- file=pathname(ftp.cd,arg);
- switch(ftp.type) {
- case IMAGE_TYPE:
- case LOGICAL_TYPE:
- mode = "rb";
- break;
- case ASCII_TYPE:
- mode = "r";
- break;
- }
- if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file))
- usprintf(ftp.control,noperm);
- else if((ftp.fp = fopen(file,mode)) == NULL)
- usprintf(ftp.control,cantopen,file,sys_errlist[errno]);
- else
- {
- if(LogLevel>=10) AddLog("RETR %s by %s",file,ftp.username);
- if(ftp.type == ASCII_TYPE && isbinary(ftp.fp)){
- usprintf(ftp.control,binwarn,file);
- }
- sendit(&ftp,"RETR",file);
- }
- free(file);
- break;
- case STOR_CMD:
- if(timewind(NULL,NULL,NULL)) {
- usprintf(ftp.control,notyet,tt1,tt2,
- ((p = getenv("TZ")) == NULL) ? "GMT" : p);
- goto finish;
- }
- file = pathname(ftp.cd,arg);
- switch(ftp.type){
- case IMAGE_TYPE:
- case LOGICAL_TYPE:
- mode = "wb";
- break;
- case ASCII_TYPE:
- mode = "w";
- break;
- }
- if(!permcheck(ftp.path,ftp.perms,STOR_CMD,file))
- usprintf(ftp.control,noperm);
- else if((ftp.fp = fopen(file,mode)) == NULL)
- usprintf(ftp.control,cantmake,file,sys_errlist[errno]);
- else
- {
- if(LogLevel>=5) AddLog("STOR %s by %s",file,ftp.username);
- recvit(&ftp,"STOR",file);
- }
- free(file);
- break;
- case PORT_CMD:
- if(pport(&ftp.port,arg) == -1) usprintf(ftp.control,badport);
- else usprintf(ftp.control,portok);
- break;
- case LIST_CMD:
- if(DefDirCommand && ArgDirCommand && !(ftp.perms&FTP_NOEXTDIR))
- {
- /* User external dir-command, you lose some protection when
- using this option */
- if(chdir(ftp.cd)) usprintf(ftp.control,nodir,file,sys_errlist[errno]);
- else if((ftp.fp=extdir(arg))==NULL) usprintf(ftp.control,nodir,file,sys_errlist[errno]);
- else sendit(&ftp,"LIST",DefDirCommand);
- }
- else
- {
- file = pathname(ftp.cd,arg);
- if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)) usprintf(ftp.control,noperm);
- else if((ftp.fp = dir(file,1)) == NULL) usprintf(ftp.control,nodir,file,sys_errlist[errno]);
- else sendit(&ftp,"LIST",file);
- free(file);
- }
- break;
- case NLST_CMD:
- file = pathname(ftp.cd,arg);
- if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file))
- usprintf(ftp.control,noperm);
- else if((ftp.fp = dir(file,0)) == NULL)
- usprintf(ftp.control,nodir,file,sys_errlist[errno]);
- else sendit(&ftp,"NLST",file);
- free(file);
- break;
- case PASS_CMD:
- if(ftp.username == NULL) usprintf(ftp.control,userfirst);
- else
- {
- if(!strcmp(arg,"anonymous")) arg="ftp";
- ftplogin(&ftp,arg);
- }
- break;
- case CWD_CMD:
- if(!strncmp(arg,"..",2)) arg="/";
- file = pathname(ftp.cd,arg);
- if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file))
- {
- usprintf(ftp.control,noperm);
- free(file);
- }
- else if(access(file,0) == 0)
- { /* See if it exists */
- /* Succeeded, record in control block */
- free(ftp.cd);
- ftp.cd = file;
- sprintf(buf2,"%s/FTP.Dir",file);
- if((fp=fopen(buf2,"r"))!=NULL)
- {
- sendfile(fp,server_socket,ASCII_TYPE,0);
- fclose(fp);
- }
- usprintf(ftp.control,pwdmsg,file);
- }
- else
- {
- /* Failed, don't change anything */
- usprintf(ftp.control,nodir,file,sys_errlist[errno]);
- free(file);
- }
- break;
- case XPWD_CMD:
- case PWD_CMD:
- usprintf(ftp.control,pwdmsg,ftp.cd);
- break;
- case XMKD_CMD:
- case MKD_CMD:
- file = pathname(ftp.cd,arg);
- if(!permcheck(ftp.path,ftp.perms,MKD_CMD,file))
- usprintf(ftp.control,noperm);
- else if(mkdir(file) == 0)
- {
- if(LogLevel>=5) AddLog("MKD %s by %s",file,ftp.username);
- usprintf(ftp.control,mkdok);
- }
- else usprintf(ftp.control,cantmake,file,sys_errlist[errno]);
- free(file);
- break;
- case XRMD_CMD:
- case RMD_CMD:
- file = pathname(ftp.cd,arg);
- if(!permcheck(ftp.path,ftp.perms,RMD_CMD,file))
- usprintf(ftp.control,noperm);
- else if(rmdir(file) == 0)
- {
- if(LogLevel>=5) AddLog("RMD %s by %s",file,ftp.username);
- usprintf(ftp.control,deleok);
- }
- else usprintf(ftp.control,delefail,sys_errlist[errno]);
- free(file);
- break;
- case ACCT_CMD:
- usprintf(ftp.control,unimp);
- break;
- case STRU_CMD:
- if(tolower(arg[0]) != 'f') usprintf(ftp.control,unsupp);
- else usprintf(ftp.control,okay);
- break;
- case MODE_CMD:
- if(tolower(arg[0]) != 's') usprintf(ftp.control,unsupp);
- else usprintf(ftp.control,okay);
- break;
- case DELE_CMD:
- file = pathname(ftp.cd,arg);
- if(!permcheck(ftp.path,ftp.perms,DELE_CMD,file))
- usprintf(ftp.control,noperm);
- else if(unlink(file) == 0)
- {
- if(LogLevel>=5) AddLog("DELE %s by %s",file,ftp.username);
- usprintf(ftp.control,deleok);
- }
- else usprintf(ftp.control,delefail,sys_errlist[errno]);
- free(file);
- break;
- // case PASV_CMD:
- // passive(&ftp);
- // break;
- }
- }
-
- finish:
- free(ftp.username);
- free(ftp.path);
- free(ftp.cd);
-
- exit(0);
- }
-