PageRenderTime 68ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/commands/ftpd200/ftpd.c

http://github.com/vivekp/minix-nbsd
C | 410 lines | 306 code | 66 blank | 38 comment | 49 complexity | 5b9837b0a31b0e374c14b1dc8e312535 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause
  1. /* ftpd.c Copyright 1992-2000 by Michael Temari All Rights Reserved
  2. *
  3. * ftpd An FTP server program for use with Minix.
  4. *
  5. * Usage: Minix usage: tcpd ftp ftpd
  6. *
  7. * 06/14/92 Tnet Release Michael Temari
  8. * 01/15/96 0.30 Michael Temari
  9. * 01/25/96 0.90 Michael Temari
  10. * 03/17/96 0.91 Michael Temari
  11. * 06/27/96 0.92 Michael Temari
  12. * 07/02/96 0.93 Michael Temari
  13. * 07/15/96 0.94 Michael Temari
  14. * 08/27/96 0.95 Michael Temari
  15. * 02/09/97 0.96 Michael Temari
  16. * 02/10/97 0.97 Michael Temari
  17. * 09/25/97 0.98 Michael Temari
  18. * 03/10/00 0.99 Michael Temari, <Michael@TemWare.Com>
  19. * 12/12/03 1.00 Michael Temari, <Michael@TemWare.Com>
  20. * 02/06/05 1.01 Michael Temari, <Michael@TemWare.Com>
  21. * 02/12/05 2.00 Michael Temari, <Michael@TemWare.Com>
  22. */
  23. char *FtpdVersion = "2.00";
  24. #include <sys/types.h>
  25. #include <signal.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include <string.h>
  30. #include <time.h>
  31. #include <unistd.h>
  32. #include <net/gen/in.h>
  33. #include <net/gen/tcp.h>
  34. #include "ftpd.h"
  35. #include "access.h"
  36. #include "file.h"
  37. #include "net.h"
  38. #ifdef __NBSD_LIBC
  39. /* Already declared in stdio.h */
  40. #define getline ftpd_getline
  41. #endif
  42. _PROTOTYPE(static void init, (void));
  43. _PROTOTYPE(static int doHELP, (char *buff));
  44. _PROTOTYPE(static int doNOOP, (char *buff));
  45. _PROTOTYPE(static int doUNIMP, (char *buff));
  46. _PROTOTYPE(static int getline, (char *line, int len));
  47. FILE *msgfile = (FILE *)NULL;
  48. /* The following defines the inactivity timeout in seconds */
  49. #define INACTIVITY_TIMEOUT 60*5
  50. char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  51. char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  52. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  53. char line[512];
  54. int type, format, mode, structure;
  55. int ftpdata_fd = -1;
  56. int loggedin, gotuser, anonymous;
  57. char username[80];
  58. char anonpass[128];
  59. char newroot[128];
  60. ipaddr_t myipaddr, rmtipaddr, dataaddr;
  61. tcpport_t myport, rmtport, dataport;
  62. char myhostname[256], rmthostname[256];
  63. #define FTPD_LOG "/usr/adm/ftpd.log"
  64. #define FTPD_MSG "/etc/ftpd_msg"
  65. FILE *logfile;
  66. int timeout = 0;
  67. _PROTOTYPE(static int doHELP, (char *buff));
  68. _PROTOTYPE(int readline, (char **args));
  69. _PROTOTYPE(void Timeout, (int sig));
  70. _PROTOTYPE(int main, (int argc, char *argv[]));
  71. struct commands {
  72. char *name;
  73. _PROTOTYPE(int (*func), (char *buff));
  74. };
  75. struct commands commands[] = {
  76. "ABOR", doUNIMP,
  77. "ACCT", doUNIMP,
  78. "ALLO", doALLO,
  79. "APPE", doAPPE,
  80. "CDUP", doCDUP,
  81. "CWD", doCWD,
  82. "DELE", doDELE,
  83. "HELP", doHELP,
  84. "LIST", doLIST,
  85. "MDTM", doMDTM,
  86. "MKD", doMKD,
  87. "MODE", doMODE,
  88. "NLST", doNLST,
  89. "NOOP", doNOOP,
  90. "PASS", doPASS,
  91. "PASV", doPASV,
  92. "PORT", doPORT,
  93. "PWD", doPWD,
  94. "QUIT", doQUIT,
  95. "REIN", doUNIMP,
  96. "REST", doREST,
  97. "RETR", doRETR,
  98. "RMD", doRMD,
  99. "RNFR", doRNFR,
  100. "RNTO", doRNTO,
  101. "SITE", doSITE,
  102. "SIZE", doSIZE,
  103. "SMNT", doUNIMP,
  104. "STAT", doSTAT,
  105. "STOR", doSTOR,
  106. "STOU", doSTOU,
  107. "STRU", doSTRU,
  108. "SYST", doSYST,
  109. "TYPE", doTYPE,
  110. "USER", doUSER,
  111. "XCUP", doCDUP,
  112. "XCWD", doCWD,
  113. "XMKD", doMKD,
  114. "XPWD", doPWD,
  115. "XRMD", doRMD,
  116. "", (int (*)())0
  117. };
  118. static void init()
  119. {
  120. loggedin = 0;
  121. gotuser = 0;
  122. anonymous = 0;
  123. newroot[0] = '\0';
  124. type = TYPE_A;
  125. format = 0;
  126. mode = MODE_S;
  127. structure = 0;
  128. ftpdata_fd = -1;
  129. username[0] = '\0';
  130. anonpass[0] = '\0';
  131. }
  132. /* nothing, nada, zilch... */
  133. static int doNOOP(buff)
  134. char *buff;
  135. {
  136. printf("200 NOOP to you too!\r\n");
  137. return(GOOD);
  138. }
  139. /* giv'em help, what a USER! */
  140. static int doHELP(buff)
  141. char *buff;
  142. {
  143. struct commands *cmd;
  144. char star;
  145. int i;
  146. char *space = " ";
  147. printf("214-Here is a list of available ftp commands\r\n");
  148. printf(" Those with '*' are not yet implemented.\r\n");
  149. i = 0;
  150. for(cmd = commands; *cmd->name != '\0'; cmd++) {
  151. if(cmd->func == doUNIMP)
  152. star = '*';
  153. else
  154. star = ' ';
  155. printf(" %s%c%s", cmd->name, star, space + strlen(cmd->name));
  156. if(++i == 6) {
  157. printf("\r\n");
  158. i = 0;
  159. }
  160. }
  161. if(i)
  162. printf("\r\n");
  163. printf("214 That's all the help you get.\r\n");
  164. return(GOOD);
  165. }
  166. /* not implemented */
  167. static int doUNIMP(buff)
  168. char *buff;
  169. {
  170. printf("502 Command \"%s\" not implemented!\r\n", line);
  171. return(GOOD);
  172. }
  173. /* convert line for use */
  174. void cvtline(args)
  175. char **args;
  176. {
  177. char *p;
  178. p = line + strlen(line);
  179. while(--p >= line)
  180. if(*p == '\r' || *p == '\n' || isspace(*p))
  181. *p = '\0';
  182. else
  183. break;
  184. p = line;
  185. #ifdef DEBUG
  186. logit("COMMAND", line);
  187. #endif
  188. while(*p && !isspace(*p)) {
  189. *p = toupper(*p);
  190. p++;
  191. }
  192. if(*p) {
  193. *p = '\0';
  194. p++;
  195. while(*p && isspace(*p))
  196. p++;
  197. }
  198. *args = p;
  199. return;
  200. }
  201. static int getline(line, len)
  202. char *line;
  203. int len;
  204. {
  205. int s;
  206. int gotcr;
  207. /* leave room for at end for null */
  208. len--;
  209. /* got to be able to put in at least 1 character */
  210. if(len < 1)
  211. return(-1);
  212. gotcr = 0;
  213. while(len-- > 0) {
  214. s = read(0, line, 1);
  215. if(s != 1)
  216. return(-1);
  217. if(*line == '\n')
  218. break;
  219. gotcr = (*line == '\r');
  220. line++;
  221. }
  222. if(gotcr)
  223. --line;
  224. *line = '\0';
  225. return(0);
  226. }
  227. int readline(args)
  228. char **args;
  229. {
  230. if(getline(line, sizeof(line)))
  231. return(BAD);
  232. cvtline(args);
  233. return(GOOD);
  234. }
  235. /* signal handler for inactivity timeout */
  236. void Timeout(sig)
  237. int sig;
  238. {
  239. timeout = 1;
  240. printf("421 Inactivity timer expired.\r\n");
  241. }
  242. /* logit */
  243. void logit(type, parm)
  244. char *type;
  245. char *parm;
  246. {
  247. time_t now;
  248. struct tm *tm;
  249. if(logfile == (FILE *)NULL)
  250. return;
  251. time(&now);
  252. tm = localtime(&now);
  253. fprintf(logfile, "%4d%02d%02d%02d%02d%02d ",
  254. 1900+tm->tm_year,
  255. tm->tm_mon + 1,
  256. tm->tm_mday,
  257. tm->tm_hour, tm->tm_min, tm->tm_sec);
  258. fprintf(logfile, "%s %s %s %s %s\n",
  259. rmthostname, username, anonymous ? anonpass : username, type, parm);
  260. fflush(logfile);
  261. }
  262. void showmsg(reply, filename)
  263. char *reply;
  264. char *filename;
  265. {
  266. FILE *mfp;
  267. char *pe;
  268. static char mline[256];
  269. if(filename == (char *)NULL)
  270. mfp = msgfile;
  271. else
  272. mfp = fopen(filename, "r");
  273. if(mfp == (FILE *)NULL)
  274. return;
  275. while(fgets(mline, sizeof(mline), mfp) != (char *)NULL) {
  276. pe = mline + strlen(mline);
  277. while(--pe >= mline)
  278. if(*pe == '\r' || *pe == '\n')
  279. *pe = '\0';
  280. else
  281. break;
  282. printf("%s- %s\r\n", reply, mline);
  283. }
  284. if(filename != (char *)NULL)
  285. fclose(mfp);
  286. }
  287. int main(argc, argv)
  288. int argc;
  289. char *argv[];
  290. {
  291. struct commands *cmd;
  292. char *args;
  293. int status;
  294. time_t now;
  295. struct tm *tm;
  296. int s;
  297. GetNetInfo();
  298. /* open transfer log file if it exists */
  299. if((logfile = fopen(FTPD_LOG, "r")) != (FILE *)NULL) {
  300. fclose(logfile);
  301. logfile = fopen(FTPD_LOG, "a");
  302. }
  303. /* open login msg file */
  304. msgfile = fopen(FTPD_MSG, "r");
  305. /* Let's initialize some stuff */
  306. init();
  307. /* Log the connection */
  308. logit("CONNECT", "");
  309. /* Tell 'em we are ready */
  310. time(&now);
  311. tm = localtime(&now);
  312. printf("220 FTP service (Ftpd %s) ready on %s at ",
  313. FtpdVersion, myhostname);
  314. printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
  315. tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
  316. tm->tm_hour, tm->tm_min, tm->tm_sec,
  317. tzname[tm->tm_isdst]);
  318. fflush(stdout);
  319. /* Loop here getting commands */
  320. while(1) {
  321. signal(SIGALRM, Timeout);
  322. alarm(INACTIVITY_TIMEOUT);
  323. if(readline(&args) != GOOD) {
  324. if(!timeout)
  325. printf("221 Control connection closing (EOF).\r\n");
  326. break;
  327. }
  328. alarm(0);
  329. for(cmd = commands; *cmd->name != '\0'; cmd++)
  330. if(!strcmp(line, cmd->name))
  331. break;
  332. if(*cmd->name != '\0')
  333. status = (*cmd->func)(args);
  334. else {
  335. printf("500 Command \"%s\" not recognized.\r\n", line);
  336. status = GOOD;
  337. }
  338. fflush(stdout);
  339. if(status != GOOD)
  340. break;
  341. }
  342. CleanUpPasv();
  343. return(-1);
  344. }