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

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <error.h>
  6. #include <stat.h>
  7. #include <dos.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/dir.h>
  10. #include <lineread.h>
  11. #include <sys/socket.h>
  12. #include <exec/memory.h>
  13. #include <dos/dostags.h>
  14. #include <libraries/multiuser.h>
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/socket.h>
  18. #include <proto/multiuser.h>
  19. #include <proto/dos.h>
  20.  
  21. #include "ftp.h"
  22.  
  23. struct muBase *muBase;
  24. extern LONG server_socket;
  25.  
  26. char VersionTag[]="\0$VER: JoranFtpd 2.0 (14.12.93)";
  27.  
  28. char Hostname[40]="unknown";
  29. char Version[]="Joran 2.0";
  30.  
  31. char buf2[512];
  32. int tt1, tt2, tnw;
  33. int pdata=-1;                // For passive mode
  34. struct FileInfoBlock *PermChkFib;
  35. struct muUserInfo *UserInfo;
  36.  
  37. long gethostname(char *,long len);
  38.  
  39. struct LineRead *LineRead;
  40.  
  41. /* Command table */
  42. static char *commands[] = {
  43.     "user",
  44.     "acct",
  45.     "pass",
  46.     "type",
  47.     "list",
  48.     "cwd",
  49.     "dele",
  50.     "name",
  51.     "quit",
  52.     "retr",
  53.     "stor",
  54.     "port",
  55.     "nlst",
  56.     "pwd",
  57.     "xpwd",            /* For compatibility with 4.2BSD */
  58.     "mkd ",
  59.     "xmkd",            /* For compatibility with 4.2BSD */
  60.     "xrmd",            /* For compatibility with 4.2BSD */
  61.     "rmd ",
  62.     "stru",
  63.     "mode",
  64.     "pasv",            /* Pasive mode */
  65.     NULL
  66. };
  67.  
  68. /* Response messages */
  69. static char binwarn[]   = "100 Warning: File %s appears to be BINARY\n";
  70. static char sending[]   = "150 Open %s for %s %s (%ld Bytes)\n";
  71. static char recving[]   = "150 Open %s for %s %s\n";
  72.  
  73. static char typeok[]    = "200 Type %s OK\n";
  74. static char mkdok[]     = "200 MKD ok\n";
  75. static char portok[]    = "200 Port command okay\n";
  76. static char okay[]      = "200 Ok\n";
  77. static char banner[]    = "220 %s FTP Ready - v%s\n";
  78. static char bye[]       = "221 Goodbye!\n";
  79. static char rxok[]      = "226 File received OK\n";
  80. static char txok[]      = "226 File sent OK\n";
  81. static char logged[]    = "230 %s Logged in, %s\n";
  82. static char loggeda[]   = "230 %s Logged in as anonymous, %s\n";
  83. static char deleok[]    = "250 File deleted\n";
  84. static char pwdmsg[]    = "257 \"%s\" is current directory\n";
  85.  
  86. static char givepass[]  = "331 Enter Password\n";
  87. static char givepasa[]  = "331 Please enter your email address '<user-id>@<host-name>'\n";
  88.  
  89. static char lowmem[]    = "421 System overloaded, try again later\n";
  90. static char noconn[]    = "425 Data connection reset\n";
  91.  
  92. static char unsupp[]    = "500 Unsupported command or option\n";
  93. static char badcmd[]    = "500 Unknown command\n";
  94. static char only8[]     = "501 Only logical bytesize 8 supported\n";
  95. static char badtype[]   = "501 Unknown type \"%s\"\n";
  96. static char badport[]   = "501 Bad port syntax\n";
  97. static char unimp[]     = "502 Command not yet implemented\n";
  98. static char userfirst[] = "503 Login with USER first.\n";
  99. static char notlog[]    = "530 Please log in with USER and PASS\n";
  100. static char noperm[]    = "550 Permission denied\n";
  101. static char cantopen[]  = "550 Can't read file \"%s\": %s\n";
  102. static char delefail[]  = "550 Delete failed: %s\n";
  103. static char writerr[]   = "552 Write error: %s\n";
  104. static char nodir[]     = "553 Can't read directory \"%s\": %s\n";
  105. static char cantmake[]  = "553 Can't create \"%s\": %s\n";
  106. static char notyet[]    = "555 Try Later : Access '%2d:00-%2d:59 %s' only\n";
  107. static char nopasv[]        = "425 Can't open passive connection\n";
  108. static char pasvcon[]        =    "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\n";
  109.  
  110. void CloseAll(void)
  111. {
  112.     if(UserInfo) muFreeUserInfo(UserInfo);
  113.     if(PermChkFib) FreeDosObject(DOS_FIB,PermChkFib);
  114.     if(LineRead) FreeMem(LineRead,sizeof(struct LineRead));
  115.     if(muBase) CloseLibrary((struct Library *)muBase);
  116.     
  117.     if(LogLevel>=20) AddLog("FTPDeamon Stopped",FindTask(NULL));
  118. }
  119.  
  120. void InitAll(void)
  121. {
  122.     atexit(CloseAll);
  123.     
  124.     SetProgramName("JoranFtpd");
  125.     muBase=(struct muBase *)OpenLibrary(MULTIUSERNAME,MULTIUSERVERSION);
  126.     if(muBase && !(UserInfo=muAllocUserInfo())) exit(20);
  127.     gethostname(Hostname,sizeof(Hostname));
  128.     if(!(LineRead=AllocMem(sizeof(struct LineRead),MEMF_ANY))) exit(20);
  129.     initLineRead(LineRead,server_socket,RL_LFREQLF,RL_BUFSIZE);
  130.     if(!(PermChkFib=AllocDosObject(DOS_FIB,NULL))) exit(20);
  131. }
  132.  
  133. /* replace terminating end of line marker(s) with null */
  134. void rip(char *s)
  135. {
  136.     char *cp;
  137.     if((cp = strchr(s,'\n')) != NULL) *cp = '\0';
  138.     if((cp = strchr(s,'\r')) != NULL) *cp = '\0';
  139. }
  140.  
  141. /* This checks the current time is in a preset Time-Window before
  142.    allowing a user to login */
  143. int timewind(int argc,char *argv[],void *p)
  144. {
  145.     char *now;
  146.     long t;
  147.     char *t1, *t2;
  148.  
  149.     t1 = strdup(curftwin);
  150.     *(t1 + 2) = '\0';
  151.     tt1 = atoi(t1);
  152.  
  153.     t2 = strdup(curftwin+2);
  154.     *(t2 + 2) = '\0';
  155.     tt2 = atoi(t2);
  156.  
  157.     time(&t);
  158.     now = ctime(&t) + 11;
  159.     *(now + 2) = '\0';
  160.     tnw = atoi(now);
  161.  
  162.     if(tt1 > tt2) {
  163.         if(((tnw >= tt1) && (tnw <= 23)) ||
  164.            ((tnw <= tt2) && (tnw >= 0)))
  165.             return 0;        /* right in time */
  166.     } else {
  167.         if((tnw >= tt1) && (tnw <= tt2))
  168.             return 0;        /* right in time */
  169.     }
  170.  
  171.     return 1;
  172. }
  173.  
  174. /* Return 1 if the file operation is allowed, 0 otherwise */
  175. int permcheck(char *path,int perms,int op,char *file)
  176. {
  177.     BPTR l;
  178.     BYTE prot;
  179.     
  180.     if(file == NULL || path == NULL)
  181.         return 0;    /* Probably hasn't logged in yet */
  182.  
  183.     /* The target file must be under the user's allowed search path */
  184.     if(strncmp(file,path,strlen(path)) != 0)
  185.         return 0;
  186.  
  187.     prot=-1;
  188. //    if(muBase & perms&FTP_MULTIUSER)
  189. //    {
  190.         // Check default protection
  191. //        if(l=Lock(file,ACCESS_READ))
  192. //        {
  193. //            if(Examine(l,PermChkFib))
  194. //            {
  195. //                if(UserInfo->uid==muNOBODYUID)
  196. //                {
  197. //                    
  198. //                }
  199. //                if(UserInfo->uid==PermChkFib->fib_OwnerUID)
  200. //                {
  201. //                }
  202. //                if(UserInfo->gid==PermChkFib->fib_GroupUID)
  203. //                {
  204. //                }
  205. //                
  206. //            }
  207. //            UnLock(l);
  208. //        }
  209. //    }
  210.     
  211.     if(l=Lock(file,ACCESS_READ)) UnLock(l);
  212.     
  213.     switch(op){
  214.         case RETR_CMD:
  215.             /* User must have permission to read files */
  216.             if(perms&FTP_READ && prot&FIBF_READ)
  217.                 return 1;
  218.             return 0;
  219.         case DELE_CMD:
  220.         case RMD_CMD:
  221.             /* User must have permission to (over)write files */
  222.             if(perms&FTP_WRITE && prot&FIBF_DELETE)
  223.                 return 1;
  224.             return 0;
  225.         case STOR_CMD:
  226.         case MKD_CMD:
  227.             /* User must have permission to (over)write files, or permission
  228.              * to create them if the file doesn't already exist
  229.              */
  230.             if(!l && perms&FTP_CREATE) return 1;
  231.             if(l && perms&FTP_WRITE && prot&FIBF_DELETE)
  232.                 return 1;
  233.             return 0;
  234.     }
  235.     return 0;    /* "can't happen" -- keep lint happy */
  236. }
  237.  
  238. /* Subroutine for logging in the user whose name is name and
  239.    password is pass.  The buffer path should be long enough to
  240.    keep a line from the userfile.  If pwdignore is true, the
  241.    password check will be overridden.  The return value is the
  242.    permissions field or -1 if the login failed.  Path is set to
  243.    point at the path field, and pwdignore will be true if no
  244.    particular password was needed for this user.
  245.  */
  246. int userlogin(char *name,char *pass,char **path,int len,int *pwdignore)
  247. {
  248.     char *cp,*cp1;
  249.     FILE *fp;
  250.     char *rest = NULL;
  251.     int anony, perm;
  252.     int unknown=FALSE;
  253.  
  254.     *pwdignore=!strcmp("ftp",name);
  255.     anony = *pwdignore;
  256.  
  257.     if((fp = fopen(Userfile,"r")) == NULL) return -1; /* Userfile doesn't exist */
  258.         
  259.     while(fgets(*path,len,fp),!feof(fp))
  260.     {
  261.         if(*path[0] == '#') continue;    /* Comment */
  262.         if((cp=strchr(*path,' '))==NULL) continue; /* Bogus entry */
  263.         *cp++ = '\0'; /* Now points to password */
  264.         
  265.         if(stricmp(name,*path)==0) break; /* Found user name */
  266.         if(stricmp("rest",*path)==0) rest=strdup(cp); /* remember default entry */
  267.     }
  268.     unknown=feof(fp);
  269.     if((rest==NULL) && unknown) 
  270.     {
  271.         /* User not in file, nor was anonymous */
  272.         fclose(fp);
  273.         return -1;
  274.     }
  275.      if(unknown)
  276.     {
  277.         /* restore default entry */
  278.         strcpy(cp = *path, rest);
  279.     }
  280.     fclose(fp);
  281.     
  282.     /* Look for space after password field in file */
  283.     if((cp1 = strchr(cp,' ')) == NULL) return -1; /* Invalid file entry */
  284.         
  285.     *cp1++ = '\0';    /* Now points to path field */
  286.     if(strcmp(cp,"*")!=0)
  287.     {
  288.         if(strcmp(cp,pass)!=0) return -1; /* Password required, but wrong one given */
  289.     }
  290.     if((cp = strchr(cp1,' ')) == NULL) return -1; /* Permission field missing */
  291.         
  292.     *cp++ = '\0';    /* now points to permission field */
  293.     perm = atoi(cp);
  294.     
  295.     if(unknown && (!muBase || !perm&FTP_MULTIUSER)) return -1;
  296.     
  297.     if(muBase && perm&FTP_MULTIUSER)
  298.     {
  299.         strncpy(UserInfo->UserID,name,muUSERIDSIZE);
  300.         if(!muGetUserInfo(UserInfo,muKeyType_UserID))
  301.         {
  302.             if(LogLevel>=10) AddLog("Unknown Us