/*
 * ftp_get_file
 *
 * This plugin attempts to retrieve /etc/passwd, and warns the user 
 * if the accounts of this file have encrypted passwd, and if 
 * there are others accounts than the system ones...
 *
 * This plugin was written by Renaud Deraison and is 
 * distributed under the GPL
 */
#include <includes.h>

#define NAME "ftp get /etc/passwd"
#define DESCRIPTION "\
Some badly configured ftp servers are displaying the\n\
actual /etc/passwd file to the world. This gives away\n\
sensitive informations such as the user names, and even\n\
sometimes their encrypted passwd\n\n\
Risk factor : medium/high"
#define COPYRIGHT "this plugin is distributed under the GPL"
#define SUMMARY "reads /etc/passwd via ftp"



PlugExport int plugin_init(struct arglist *desc);
PlugExport int plugin_init(struct arglist *desc)
{
        plug_set_name(desc, NAME);
        plug_set_description(desc, DESCRIPTION);
        plug_set_summary(desc, SUMMARY);
        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[2];
 char * buffer;
 char *t=NULL, *t2;
 fd_set read_set;
 struct timeval tv = {2,0};
 struct sockaddr_in addr;
 int finished = 0;
 char * report;
 int a = 1;
 if(!plug_get_key(args, "ftp/anonymous_access"))return(0);
 if(host_get_port_state(args, 21)<=0)return(0);
 if((soc[0] = open_sock_tcp(args, 21))<0)return(0);
 if(ftp_log_in(soc[0], "anonymous", "joe@"))return(0);
 if(ftp_get_pasv_address(soc[0], &addr))return(0);
 send(soc[0], "TYPE I\n", 7, 0);
 buffer = emalloc(255);
 recv_line(soc[0], buffer, 255);
 send(soc[0], "RETR /etc/passwd\n", 17, 0);
 soc[1] = socket(AF_INET, SOCK_STREAM, 0);
 if(connect(soc[1], (struct sockaddr *)&addr, sizeof(struct sockaddr_in)))
 return(0);
 bzero(buffer, 255);

 recv_line(soc[0], buffer, 255);
 if(strncmp(buffer, "150", 3))return(0);

 while(!finished)
 {
 if(a)
  {
   bzero(buffer, 255);
   recv(soc[1], buffer, 255, 0);
   if(t){
     t2 = emalloc(strlen(t)+strlen(buffer)+1);
     sprintf(t2, "%s%s", t, buffer);
     efree(&t);
     t = t2;
     }
   else
     {
     t2 = emalloc(strlen(buffer)+1);
     sprintf(t2, "%s", buffer);
     t = t2;
     }
   finished = 1;
   ioctl(soc[1], FIONREAD, &a);
  }
 else finished = 1;
 
 }
 
  
 if(dangerous_password_file(t))
 {
  char * report = emalloc(255+strlen(t));
  sprintf(report, "\
The file /etc/passwd obtained via anonymous FTP\n\
seems to give away too much informations. You should\n\
change it as soon as possible :\n%s\n", t);
  post_hole(args, 21, report);
  efree(&report);
 }
 if(t)efree(&t);
 return(0);
}


int dangerous_password_file(char * passwd)
{
 char * safe_accounts[] = {"root", "toor", "daemon", "operator", "bin", 
 			   "games", "news", "man", "uucp", "xten", "pop",
                           "nobody", "ftp", "adm", "lp", "sync", "shutdown",
                           "halt", "mail", "postmaster"};
 
 int ok = 1;
 char * passwd_2 = emalloc(strlen(passwd)+1);
 
 strncpy(passwd_2, passwd, strlen(passwd));
 passwd = passwd_2;
 
 while(ok)
 {
  char * t = strchr(passwd, '\n');
  char * passwd_field;
  if(!t)break;
  t[0] = 0;
  passwd_field = strchr(passwd, ':');
  if(passwd_field)
  {
   int i;
   int j = 0;
   char * next;
   passwd_field[0]=0;
   passwd_field++;
   for(i=0;i<20;i++)if(!strcmp(passwd, safe_accounts[i]))j++;
   if(!j)ok=0;
   next = strchr(passwd_field, ':');
   if(next){
    next[0]=0;
    if(strlen(passwd_field)>1)ok = 0;
    }
  }
  else break;
  passwd = t+1;
 }
 return(ok?0:1);
}
  
 
