00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 char *FtpdVersion = "2.00";
00025
00026 #include <sys/types.h>
00027 #include <signal.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <ctype.h>
00031 #include <string.h>
00032 #include <time.h>
00033 #include <unistd.h>
00034 #include <net/gen/in.h>
00035 #include <net/gen/tcp.h>
00036
00037 #include "ftpd.h"
00038 #include "access.h"
00039 #include "file.h"
00040 #include "net.h"
00041
00042 _PROTOTYPE(static void init, (void));
00043 _PROTOTYPE(static int doHELP, (char *buff));
00044 _PROTOTYPE(static int doNOOP, (char *buff));
00045 _PROTOTYPE(static int doUNIMP, (char *buff));
00046 _PROTOTYPE(static int getline, (char *line, int len));
00047
00048 FILE *msgfile = (FILE *)NULL;
00049
00050
00051 #define INACTIVITY_TIMEOUT 60*5
00052
00053 char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
00054 char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
00055 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
00056
00057 char line[512];
00058
00059 int type, format, mode, structure;
00060 int ftpdata_fd = -1;
00061 int loggedin, gotuser, anonymous;
00062 char username[80];
00063 char anonpass[128];
00064 char newroot[128];
00065
00066 ipaddr_t myipaddr, rmtipaddr, dataaddr;
00067 tcpport_t myport, rmtport, dataport;
00068
00069 char myhostname[256], rmthostname[256];
00070
00071 #define FTPD_LOG "/usr/adm/ftpd.log"
00072 #define FTPD_MSG "/etc/ftpd_msg"
00073
00074 FILE *logfile;
00075
00076 int timeout = 0;
00077
00078 _PROTOTYPE(static int doHELP, (char *buff));
00079 _PROTOTYPE(int readline, (char **args));
00080 _PROTOTYPE(void Timeout, (int sig));
00081 _PROTOTYPE(int main, (int argc, char *argv[]));
00082
00083 struct commands {
00084 char *name;
00085 _PROTOTYPE(int (*func), (char *buff));
00086 };
00087
00088 struct commands commands[] = {
00089 "ABOR", doUNIMP,
00090 "ACCT", doUNIMP,
00091 "ALLO", doALLO,
00092 "APPE", doAPPE,
00093 "CDUP", doCDUP,
00094 "CWD", doCWD,
00095 "DELE", doDELE,
00096 "HELP", doHELP,
00097 "LIST", doLIST,
00098 "MDTM", doMDTM,
00099 "MKD", doMKD,
00100 "MODE", doMODE,
00101 "NLST", doNLST,
00102 "NOOP", doNOOP,
00103 "PASS", doPASS,
00104 "PASV", doPASV,
00105 "PORT", doPORT,
00106 "PWD", doPWD,
00107 "QUIT", doQUIT,
00108 "REIN", doUNIMP,
00109 "REST", doREST,
00110 "RETR", doRETR,
00111 "RMD", doRMD,
00112 "RNFR", doRNFR,
00113 "RNTO", doRNTO,
00114 "SITE", doSITE,
00115 "SIZE", doSIZE,
00116 "SMNT", doUNIMP,
00117 "STAT", doSTAT,
00118 "STOR", doSTOR,
00119 "STOU", doSTOU,
00120 "STRU", doSTRU,
00121 "SYST", doSYST,
00122 "TYPE", doTYPE,
00123 "USER", doUSER,
00124 "XCUP", doCDUP,
00125 "XCWD", doCWD,
00126 "XMKD", doMKD,
00127 "XPWD", doPWD,
00128 "XRMD", doRMD,
00129 "", (int (*)())0
00130 };
00131
00132 static void init()
00133 {
00134 loggedin = 0;
00135 gotuser = 0;
00136 anonymous = 0;
00137 newroot[0] = '\0';
00138 type = TYPE_A;
00139 format = 0;
00140 mode = MODE_S;
00141 structure = 0;
00142 ftpdata_fd = -1;
00143 username[0] = '\0';
00144 anonpass[0] = '\0';
00145 }
00146
00147
00148 static int doNOOP(buff)
00149 char *buff;
00150 {
00151 printf("200 NOOP to you too!\r\n");
00152
00153 return(GOOD);
00154 }
00155
00156
00157 static int doHELP(buff)
00158 char *buff;
00159 {
00160 struct commands *cmd;
00161 char star;
00162 int i;
00163 char *space = " ";
00164
00165 printf("214-Here is a list of available ftp commands\r\n");
00166 printf(" Those with '*' are not yet implemented.\r\n");
00167
00168 i = 0;
00169 for(cmd = commands; *cmd->name != '\0'; cmd++) {
00170 if(cmd->func == doUNIMP)
00171 star = '*';
00172 else
00173 star = ' ';
00174 printf(" %s%c%s", cmd->name, star, space + strlen(cmd->name));
00175 if(++i == 6) {
00176 printf("\r\n");
00177 i = 0;
00178 }
00179 }
00180
00181 if(i)
00182 printf("\r\n");
00183
00184 printf("214 That's all the help you get.\r\n");
00185
00186 return(GOOD);
00187 }
00188
00189
00190 static int doUNIMP(buff)
00191 char *buff;
00192 {
00193 printf("502 Command \"%s\" not implemented!\r\n", line);
00194
00195 return(GOOD);
00196 }
00197
00198
00199 void cvtline(args)
00200 char **args;
00201 {
00202 char *p;
00203
00204 p = line + strlen(line);
00205 while(--p >= line)
00206 if(*p == '\r' || *p == '\n' || isspace(*p))
00207 *p = '\0';
00208 else
00209 break;
00210
00211 p = line;
00212
00213 #ifdef DEBUG
00214 logit("COMMAND", line);
00215 #endif
00216
00217 while(*p && !isspace(*p)) {
00218 *p = toupper(*p);
00219 p++;
00220 }
00221
00222 if(*p) {
00223 *p = '\0';
00224 p++;
00225 while(*p && isspace(*p))
00226 p++;
00227 }
00228
00229 *args = p;
00230
00231 return;
00232 }
00233
00234 static int getline(line, len)
00235 char *line;
00236 int len;
00237 {
00238 int s;
00239 int gotcr;
00240
00241
00242 len--;
00243
00244
00245 if(len < 1)
00246 return(-1);
00247
00248 gotcr = 0;
00249 while(len-- > 0) {
00250 s = read(0, line, 1);
00251 if(s != 1)
00252 return(-1);
00253 if(*line == '\n')
00254 break;
00255 gotcr = (*line == '\r');
00256 line++;
00257 }
00258 if(gotcr)
00259 --line;
00260
00261 *line = '\0';
00262
00263 return(0);
00264 }
00265
00266 int readline(args)
00267 char **args;
00268 {
00269 if(getline(line, sizeof(line)))
00270 return(BAD);
00271
00272 cvtline(args);
00273
00274 return(GOOD);
00275 }
00276
00277
00278 void Timeout(sig)
00279 int sig;
00280 {
00281 timeout = 1;
00282
00283 printf("421 Inactivity timer expired.\r\n");
00284 }
00285
00286
00287 void logit(type, parm)
00288 char *type;
00289 char *parm;
00290 {
00291 time_t now;
00292 struct tm *tm;
00293
00294 if(logfile == (FILE *)NULL)
00295 return;
00296
00297 time(&now);
00298 tm = localtime(&now);
00299 fprintf(logfile, "%4d%02d%02d%02d%02d%02d ",
00300 1900+tm->tm_year,
00301 tm->tm_mon + 1,
00302 tm->tm_mday,
00303 tm->tm_hour, tm->tm_min, tm->tm_sec);
00304 fprintf(logfile, "%s %s %s %s %s\n",
00305 rmthostname, username, anonymous ? anonpass : username, type, parm);
00306 fflush(logfile);
00307 }
00308
00309 void showmsg(reply, filename)
00310 char *reply;
00311 char *filename;
00312 {
00313 FILE *mfp;
00314 char *pe;
00315 static char mline[256];
00316
00317 if(filename == (char *)NULL)
00318 mfp = msgfile;
00319 else
00320 mfp = fopen(filename, "r");
00321
00322 if(mfp == (FILE *)NULL)
00323 return;
00324
00325 while(fgets(mline, sizeof(mline), mfp) != (char *)NULL) {
00326 pe = mline + strlen(mline);
00327 while(--pe >= mline)
00328 if(*pe == '\r' || *pe == '\n')
00329 *pe = '\0';
00330 else
00331 break;
00332 printf("%s- %s\r\n", reply, mline);
00333 }
00334
00335 if(filename != (char *)NULL)
00336 fclose(mfp);
00337 }
00338
00339 int main(argc, argv)
00340 int argc;
00341 char *argv[];
00342 {
00343 struct commands *cmd;
00344 char *args;
00345 int status;
00346 time_t now;
00347 struct tm *tm;
00348 int s;
00349
00350 GetNetInfo();
00351
00352
00353 if((logfile = fopen(FTPD_LOG, "r")) != (FILE *)NULL) {
00354 fclose(logfile);
00355 logfile = fopen(FTPD_LOG, "a");
00356 }
00357
00358
00359 msgfile = fopen(FTPD_MSG, "r");
00360
00361
00362 init();
00363
00364
00365 logit("CONNECT", "");
00366
00367
00368 time(&now);
00369 tm = localtime(&now);
00370 printf("220 FTP service (Ftpd %s) ready on %s at ",
00371 FtpdVersion, myhostname);
00372 printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
00373 tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
00374 tm->tm_hour, tm->tm_min, tm->tm_sec,
00375 tzname[tm->tm_isdst]);
00376 fflush(stdout);
00377
00378
00379 while(1) {
00380 signal(SIGALRM, Timeout);
00381 alarm(INACTIVITY_TIMEOUT);
00382 if(readline(&args) != GOOD) {
00383 if(!timeout)
00384 printf("221 Control connection closing (EOF).\r\n");
00385 break;
00386 }
00387 alarm(0);
00388 for(cmd = commands; *cmd->name != '\0'; cmd++)
00389 if(!strcmp(line, cmd->name))
00390 break;
00391 if(*cmd->name != '\0')
00392 status = (*cmd->func)(args);
00393 else {
00394 printf("500 Command \"%s\" not recognized.\r\n", line);
00395 status = GOOD;
00396 }
00397 fflush(stdout);
00398 if(status != GOOD)
00399 break;
00400 }
00401
00402 CleanUpPasv();
00403
00404 return(-1);
00405 }