Advertisement
Guest User

Untitled

a guest
Jul 2nd, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.65 KB | None | 0 0
  1.  
  2. /*
  3.  
  4. stupid-ftpd.c
  5. ------------
  6.  
  7.  
  8. Main program. Bind/Listen/Accept routines.
  9.  
  10. */
  11.  
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <errno.h>
  18.  
  19. #include <signal.h>
  20. #ifdef __CYGWIN__
  21. #include <winsock2.h>
  22. #else
  23. #include <unistd.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <netdb.h>
  27. #define INVALID_SOCKET -1
  28. #endif
  29. #include <sys/wait.h>
  30. #include <time.h>
  31. #include <sys/time.h>
  32. #include <syslog.h>
  33. #include "stupid-ftpd.h"
  34. #include "ftpdconfig.h"
  35. #include "ftpcommand.h"
  36. #include "servercommand.h"
  37. #include "ftperror.h"
  38. #include "ls.h"
  39.  
  40. #define REACTION_TIME 1L
  41.  
  42. child_t *pchild[HARD_USERLIMIT];
  43.  
  44. int server_socket=0;
  45. int serverstop=0;
  46. int reinit=1;
  47.  
  48.  
  49. /* prototypes */
  50.  
  51. void init_login(void);
  52. void check_timeouts(void);
  53. void cleanchild(int);
  54. void listener_loop(void);
  55. void startserver(void);
  56. int process_banned(int,char *);
  57. void do_changeroot(void);
  58. void do_writepidfile(void);
  59.  
  60. int process_banned(int sock,char *host) {
  61. int n;
  62. char buffer[128];
  63.  
  64. for (n=0;n<bancount;n++)
  65. if (list_match(host,banlist[n])) {
  66. #ifdef DEBUG
  67. fprintf(stderr,"Ban hit '%s'\n",host);
  68. #endif
  69. if (banmessage[0]!=0) {
  70. sprintf(buffer,"540 %s\r\n",banmessage);
  71. write(sock,buffer,strlen(buffer));
  72. }
  73. close(sock);
  74. return 1;
  75. }
  76.  
  77. return 0;
  78. }
  79.  
  80. void init_login(void) {
  81. int nr,sock,sock_size;
  82. char buffer[128];
  83. struct sockaddr_in sa;
  84. struct hostent *hp;
  85. unsigned char *i;
  86.  
  87. sock_size=sizeof(sa);
  88. if ((sock=accept(server_socket,(struct sockaddr *)&sa,&sock_size))<0) {
  89. if (!daemonmode)
  90. printf("Error: accept failed.\n");
  91. return;
  92. }
  93.  
  94. for (nr=0;nr<maxusers;nr++)
  95. if (!pchild[nr]->sock) break;
  96. if (nr>=maxusers) {
  97. if (!daemonmode) {
  98. printf("Info: Server is full.\n");
  99. out_prompt();
  100. }
  101. sprintf(buffer,"530 Server is busy, sorry.\r\n");
  102. write(sock,buffer,strlen(buffer));
  103. close(sock);
  104. return;
  105. }
  106. i=(unsigned char *)&sa.sin_addr;
  107.  
  108. pchild[nr]->userip[0]=*i++;
  109. pchild[nr]->userip[1]=*i++;
  110. pchild[nr]->userip[2]=*i++;
  111. pchild[nr]->userip[3]=*i++;
  112.  
  113. sprintf(buffer,"%d.%d.%d.%d",
  114. pchild[nr]->userip[0],pchild[nr]->userip[1],
  115. pchild[nr]->userip[2],pchild[nr]->userip[3]);
  116.  
  117. if (process_banned(sock,buffer)) return;
  118.  
  119. hp=gethostbyaddr((char *)&sa.sin_addr,sizeof(long int),AF_INET);
  120. if (hp!=NULL) {
  121. strncpy(pchild[nr]->url,hp->h_name,sizeof(pchild[nr]->url)-1);
  122. *(pchild[nr]->url+strlen(hp->h_name))=0;
  123. } else strcpy(pchild[nr]->url,"unknown");
  124.  
  125. if (process_banned(sock,pchild[nr]->url)) return;
  126.  
  127. pchild[nr]->sock=sock;
  128. pchild[nr]->idletime=time(NULL);
  129. strcpy(pchild[nr]->reldir,"/");
  130. strcpy(pchild[nr]->rootdir,"???*???"); /* better */
  131. pchild[nr]->state=USR_USER;
  132. pchild[nr]->resume=0;
  133. pchild[nr]->pasvsock=0;
  134. pchild[nr]->pid=0;
  135. pchild[nr]->dataport=0;
  136. pchild[nr]->perm=PERM_NONE;
  137. if (!daemonmode) {
  138. printf("User %d, connected (IP: %d.%d.%d.%d).\n",nr+1,
  139. pchild[nr]->userip[0],
  140. pchild[nr]->userip[1],
  141. pchild[nr]->userip[2],
  142. pchild[nr]->userip[3]);
  143. out_prompt();
  144. }
  145.  
  146. user_return(nr,RET_220);
  147. }
  148.  
  149. void check_timeouts(void)
  150. {
  151. int n;
  152. time_t t;
  153.  
  154. /* check the timeouts of all 3 phases */
  155. t=time(NULL);
  156. for (n=0;n<maxusers;n++) {
  157. if (pchild[n]->sock) {
  158. switch (pchild[n]->state) {
  159. case USR_ONLINE:
  160. if (pchild[n]->pid==0 || waitpid(pchild[n]->pid,NULL,WNOHANG)<0) {
  161. pchild[n]->pid=0;
  162. if (idletimeout && t-pchild[n]->idletime>=idletimeout) {
  163. handle_timeout(n);
  164. }
  165. } else pchild[n]->idletime=t;
  166. break;
  167. case USR_USER:
  168. case USR_PASS:
  169. if (t-pchild[n]->idletime>=logintimeout) handle_timeout(n);
  170. break;
  171. default: /* better */
  172. handle_suspects(n);
  173. break;
  174. }
  175. }
  176. }
  177. }
  178.  
  179. void cleanchild(int nr) {
  180. #ifdef WAIT_DEBUG
  181. pid_t proc;
  182.  
  183. fprintf(stderr,"\nEntered in cleanchild\n");
  184.  
  185. while ((proc=wait3(NULL, WNOHANG, NULL)) > 0);
  186.  
  187. fprintf(stderr,"\nLeft cleanchild\n");
  188. #else
  189. while (wait3(NULL, WNOHANG, NULL) > 0);
  190. #endif
  191. #ifdef __SVR4
  192. sigset(SIGCHLD,cleanchild);
  193. #else
  194. signal(SIGCHLD,cleanchild);
  195. #endif
  196. }
  197.  
  198. void listener_loop(void)
  199. {
  200. int i,n,addr;
  201. unsigned int sock_size;
  202. fd_set fds;
  203. struct timeval tv;
  204. char cmd[1024];
  205. struct sockaddr_in sa;
  206. #ifdef __CYGWIN__
  207. WORD verreq;
  208. WSADATA wsadata;
  209. #endif
  210.  
  211. /* catch broken pipe ! */
  212.  
  213. #ifdef __SVR4
  214. sigignore(SIGPIPE);
  215. sigset(SIGCHLD,cleanchild);
  216. #else
  217. signal(SIGPIPE,SIG_IGN);
  218. signal(SIGCHLD,cleanchild);
  219. #endif
  220.  
  221. /*
  222. myip=getmyip();
  223. if (myip==NULL) {
  224. printf("Determining localhost-IP failed.\n");
  225. exit(1);
  226. }
  227.  
  228. #ifdef DEBUG
  229. printf("My IP is: %d.%d.%d.%d\n",
  230. myip[0],myip[1],myip[2],myip[3]);
  231. #endif
  232. */
  233.  
  234. /* server init */
  235.  
  236. #ifdef __CYGWIN__
  237. verreq=MAKEWORD(1,1);
  238. i=WSAStartup(verreq,&wsadata);
  239. if (i!=0) {
  240. printf("Error: winsock-lib couldn't be initialized.");
  241. }
  242. #endif
  243.  
  244. if (!daemonmode)
  245. printf("Starting server ... ");
  246. if ((server_socket=socket(PF_INET,SOCK_STREAM,0))==INVALID_SOCKET) {
  247. #ifdef __CYGWIN__
  248. i=WSAGetLastError();
  249. #else
  250. i=errno;
  251. #endif
  252. printf("Error: could not create server socket (%d).\n",i);
  253. exit(1);
  254. }
  255.  
  256. i=1;
  257. if (setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(void *)&i,sizeof(i))<0)
  258. printf("setsockopt failed.\n");
  259.  
  260. sock_size=sizeof(struct sockaddr_in);
  261. memset(&sa,0,sock_size);
  262.  
  263. sa.sin_family=PF_INET;
  264. sa.sin_port=htons(serverport);
  265. addr=INADDR_ANY;
  266. memcpy(&sa.sin_addr.s_addr,&addr,sizeof(int));
  267.  
  268. if (bind(server_socket,(struct sockaddr *)&sa,sock_size)<0) {
  269. printf("Error: bind failed.\n");
  270. printf(" port %i already in use ?\n",serverport);
  271. printf(" exit(1)\n");
  272. exit(1);
  273. }
  274.  
  275. if (listen(server_socket,5)<0) {
  276. printf("Error: listen failed.\n");
  277. exit(1);
  278. }
  279.  
  280. if (!daemonmode) {
  281. printf("OK\n\n");
  282. out_prompt();
  283. }
  284.  
  285. #ifdef DEBUG
  286. printf("Listening ...\n");
  287. #endif
  288.  
  289. serverstop=0;
  290. while (!serverstop) {
  291. FD_ZERO(&fds);
  292. if (!daemonmode) FD_SET(1,&fds);
  293. FD_SET(server_socket,&fds);
  294. for (i=0;i<maxusers;i++)
  295. if (pchild[i]->sock)
  296. FD_SET(pchild[i]->sock,&fds);
  297.  
  298. /* memset(&tv,0,sizeof(struct timeval)); */
  299. tv.tv_sec=REACTION_TIME;tv.tv_usec=0L;
  300. n=select(32+maxusers*4,&fds,NULL,NULL,&tv);
  301.  
  302. if (n<0) {
  303. if (errno==EINTR) continue;
  304. if (
  305. #ifdef __CYGWIN__
  306. 1) {
  307. i=WSAGetLastError();
  308. #else
  309. !daemonmode) {
  310. i=errno;
  311. #endif
  312. fprintf(stderr,"*** Fehler: select (ret: %d,errno=%d).\n",n,i);
  313. }
  314. exit(1);
  315. }
  316.  
  317. if (!daemonmode)
  318. if (FD_ISSET(1,&fds)) {
  319. i=read(1,cmd,sizeof(cmd));
  320. if (i<1) continue;
  321. cmd[i-1]=0;
  322. execcmd(cmd);
  323. if (serverstop) break;
  324. out_prompt();
  325. }
  326.  
  327. if (FD_ISSET(server_socket,&fds)) init_login();
  328.  
  329. for (i=0;i<maxusers;i++) {
  330. if (pchild[i]->sock) {
  331. if (FD_ISSET(pchild[i]->sock,&fds))
  332. serve_child(i);
  333. }
  334. }
  335.  
  336. check_timeouts();
  337. }
  338.  
  339. close(server_socket);
  340. #ifdef __CYGWIN__
  341. WSACleanup();
  342. #endif
  343.  
  344. if (!daemonmode)
  345. printf("Server stopped.\n");
  346. }
  347.  
  348. void startserver(void)
  349. {
  350. int n;
  351.  
  352. if (logfile) fprintf(logfile,"Server restarted.\n");
  353. for (n=0;n<maxusers;n++) {
  354. pchild[n]=(child_t *)malloc(sizeof(child_t));
  355. pchild[n]->sock=0;
  356. }
  357.  
  358. listener_loop();
  359. }
  360.  
  361. void do_writepidfile() {
  362. /* PID-file processing */
  363. if ( fpid != NULL ) {
  364. fprintf(fpid,"%d\n",(int)getpid());
  365. fflush(fpid);
  366. fclose(fpid);
  367. }
  368. }
  369.  
  370. void do_changeroot() {
  371.  
  372. if (realchangeroot) {
  373.  
  374. if (getuid()!=0) {
  375. realchangeroot=0;
  376. if (!daemonmode) printf("Chroot only works with root privileges.\n");
  377. return;
  378. }
  379.  
  380. chdir(serverroot);
  381. chroot(serverroot);
  382. }
  383. }
  384.  
  385. int main(int argc,char **argv)
  386. {
  387. int n;
  388.  
  389. openlog("FTP server", 0, LOG_DAEMON);
  390. syslog(LOG_INFO, "daemon is started");
  391.  
  392. for (n=0;n<HARD_USERLIMIT;n++)
  393. pchild[n]=(child_t *)NULL;
  394. for (n=0;n<LOGININFO_COUNT;n++)
  395. logininfo[n]=(logininfo_t *)NULL;
  396.  
  397. parsecmdline(argc,argv);
  398.  
  399. while (reinit) {
  400. reinit=0;
  401. preinit();
  402.  
  403. if (readini()<0) exit(1);
  404. if (!checkconf()) exit(1);
  405.  
  406. do_writepidfile();
  407. do_changeroot();
  408.  
  409. if (daemonmode)
  410. {
  411. if (fork()==0)
  412. {
  413. startserver();
  414. }
  415. exit(0); /* better be sure */
  416. }
  417. else startserver();
  418.  
  419. for (n=0;n<maxusers;n++)
  420. if (pchild[n]) {
  421. free(pchild[n]);
  422. pchild[n]=(child_t *)NULL;
  423. }
  424. for (n=0;n<logininfocount;n++)
  425. if (logininfo[n]) {
  426. free(logininfo[n]);
  427. logininfo[n]=(logininfo_t *)NULL;
  428. }
  429. }
  430. exit(0);
  431. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement