home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
useful
/
comm
/
tcp
/
ftpdaemon
/
source
/
ftpserv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-02
|
25KB
|
979 lines
#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 Us