/*
 * 
 * default_accounts
 *
 * This plugin was written by Renaud Deraison and is released
 * under the GPL
 *
 */

#include <includes.h>

#define NAME "default system accounts"
#define DESC "Several operating systems come with default\n\
accounts that have no or simple passwords.\n\
This plugin will attempt to connect to the remote host\n\
on the telnet port and will attempt to find those weak\n\
accounts"
#define COPYRIGHT "no copyright"
#define SUMM "telnet to the remote host and guess login/passwords"


#define OK_WITH_PASS 1
#define OK_WITHOUT_PASS 2

struct accounts {
    char * login;
    char * password;
    };
    
char init_telnet_session(int sock);
void send_data(int sock, char * data, int echo);
void send_return(int soc);
int read_line(int sock, char * buf, int len);
int accept_telnet_session(struct arglist * env);
int try_account(struct arglist * env, char * login, char * pass);

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, "Misc.");
	return(0);
}


PlugExport int plugin_run(struct arglist * env);
PlugExport int plugin_run(struct arglist * env)
{
#define NUM_ACCOUNTS 17
         struct accounts accounts[] = {{"guest", "guest"},
         			       {"EZsetup", ""},
                                       {"demos", ""},
                                       {"OutOfBox", ""},
                                       {"4Dgifts", ""},
                                       {"root", "root"},
                                       {"system", "manager"},
                                       {"lp", ""},
                                       {"sync", ""},
                                       {"date", ""},
                                       {"jack", ""},
                                       {"jill", ""},
                                       {"backdoor", ""},
                                       {"tutor", ""},
                                       {"tour", ""},
                                       {"root", "hello"}, /* these two work quite    */
                                       {"toto", "toto"}}; /* often here in France :) */
                                       
        int i = 0;                          
        if(host_get_port_state(env, 23)<=0)return(0);
        if(!accept_telnet_session(env))return(0);
        
        
        /* ok. The remote host accepts telnet sessions... 
           we are going to attempt to guess several well
           known accounts
         */
       for(i=0;i<NUM_ACCOUNTS;i++)
        {
         int code = try_account(env, accounts[i].login, accounts[i].password);
         switch(code)
         {
          case OK_WITHOUT_PASS :
          {
           char * report = emalloc(255);
           sprintf(report, "The user account \"%s\" has NO password", accounts[i].login);
           post_hole(env, 23, report);
           efree(&report);
          }
          break;
          
          case OK_WITH_PASS :
          {
           char * report = emalloc(255);
           sprintf(report, "The account %s/%s is valid !", accounts[i].login,
           		accounts[i].password);
           post_hole(env, 23, report);
           efree(&report);
          }
          break;
          
          default :
          break;
        }
      }   
		
     return(0);
}



char init_telnet_session(int sock)
{ 
 /* very simple here... we just say "WON'T" to every option */
 unsigned char iac, code, option;
 iac = 255;
 
 while(iac == 255)
 {
   recv(sock, &iac, 1,0);
   if(iac!=255)break;
   recv(sock, &code, 1,0);
   recv(sock, &option, 1,0);
   code = 252; /* WONT */
   send(sock, &iac, 1,0);
   send(sock,&code, 1,0);
   send(sock, &option, 1,0);
  }
  return(iac);
}


void send_data(int sock, char * data, int echo)
{
 int i = 0;
 unsigned char c;
 while(data[i])
 {
  send(sock, &data[i], 1,0);
  if(echo){recv(sock, &c, 1, 0);}
  i++;
 }
}


void send_return(int soc)
{
 char s[2];
 s[0] = 13;
 s[1] = 0;
 send(soc, s, 2, 0);
 recv(soc, s, 2, 0);
}


int read_line(int sock, char * buf, int len)
{
int i =0;
 int ok = 0; 
 char c;
 
 bzero(buf, len);
 while(!ok)
 {
  int a = 0;
  ioctl(sock, FIONREAD, &a);
  if(!a)ok = 1;
  else
  {
  recv(sock, &c, 1, 0);
  buf[i++] = c;
  if(!c || (c=='\n')|| (i>=len))ok = 1;
  }
  }
  return(0);
}


int accept_telnet_session(struct arglist * env)
{
 int soc = open_sock_tcp(env, 23);
 char c;
 char * buf;
 int ok = 0;

 if(soc<0)return(0);
 c = init_telnet_session(soc);
 buf = emalloc(255);
 buf[0]=c;
 read_line(soc, buf+1, 255);
 while(!ok)
 {
  int i;
  int d;
  for(i=0;i<strlen(buf);i++)buf[i]=tolower(buf[i]);
  if(strstr(buf, "login:"))ok = 1;
  else {
   d = read_line(soc, buf, 255);
   }
 }
 shutdown(soc, 2);
 close(soc);
 efree(&buf);
 return(ok);
}



int try_account(struct arglist * env, char * login, char * pass)
{
 char * buf = emalloc(255);
 int soc = open_sock_tcp(env, 23);
 int ok = 0;
 int i;
 int n = 0;
 if(soc<0)return(0);
 
 
 buf[0] = init_telnet_session(soc);
 read_line(soc, buf+1, 255);
 while(!ok && (n<4))
 {
  if(!strlen(buf)){
  	n++;
        sleep(1);
        }
  for(i=0;i<strlen(buf);i++)buf[i] = tolower(buf[i]);
  if(strstr(buf, "login:"))ok=1;
  else read_line(soc, buf, 255);
 }
 
 if(ok)
 {
  send_data(soc, login, 1);
  send_return(soc);
  bzero(buf, 255);
  recv(soc, buf, 255,0);
  
  for(i=0;i<strlen(buf);i++)buf[i] = tolower(buf[i]);
  if(!strstr(buf, "password:"))
  {
   efree(&buf);
   shutdown(soc, 2);
   return(OK_WITHOUT_PASS);
  }
  send_data(soc, pass, 0);
  send_return(soc);
  bzero(buf, 255);
  recv(soc, buf, 255,0);
  for(i=0;i<strlen(buf);i++)buf[i] = tolower(buf[i]);
  if((!strstr(buf, "incorrect"))&&(
     (!strstr(buf, "denied")))&&(strlen(buf)>5)){
    efree(&buf);
    shutdown(soc, 2);
    return(OK_WITH_PASS);
    }
   }
  efree(&buf);
  shutdown(soc, 2);
  return(0);
}
  
   
 
 
