/* 
 * ftelnetd - fake telnet daemon
 * 
 * fake_get_login.c
 * Fakes the telnetd and router with its banner and data, which will be sent
 * after the three-way-handshake and which will be sent before RST!
 *
 * Tue Dec 12 22:47:31 CET 2006
 *
 * by Levent Kayan
 * levent[at]corehack[dot]org
 * www.corehack.org
 */

#include "ftelnetd.h"
#include "sighandle.h"
#include "banner.h"
#include "ferror.h"
#include "wrapper.h"
#include "log.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


/* max username and password length to read */
#define MAX_CHAR  24

/* fake mode */
extern int mode;
extern int connfd;

/* timeout messages and RST*/
void alarm_handle()
{
   xwrite(connfd, banner[mode].timeout_msg,
          strlen(banner[mode].timeout_msg));
   exit(EXIT_SUCCESS);
}

/* sends given telnet data and banner message */
int fake_banner_msg(int connfd)
{
   /* telnet protocol handling and banner message */
   xwrite(connfd, banner[mode].telnet_data, strlen(banner[mode].telnet_data));
   
   return 1;
}

/* sends user string and gets user */
char *fake_get_user(int connfd) 
{
	char *user = NULL;
   
   /* we don't want to handle this, if $device doesn't need a user */
   if (banner[mode].user_retries > 0) {
      /* sending user string, look at banner_t in banner.c! */
      xwrite(connfd, banner[mode].user_string, 
             strlen(banner[mode].user_string));

      /* user timeout */
      signal(SIGALRM, alarm_handle);
      alarm(banner[mode].time_out);
  
      user = xmalloc(MAX_CHAR);
      /* get user :) */
      get_line(connfd, user, MAX_CHAR, 0xff);
   }

   return user;
}

/* sends pass string and gets pass */
char *fake_get_pass(int connfd)
{
	char *pass = NULL;
   
   /* sending pass string, look at banner_t in banner.h! */
   xwrite(connfd, banner[mode].pass_string, strlen(banner[mode].pass_string));
   pass = xmalloc(MAX_CHAR);
   
   /* if mode is cisco, then we have to call our alarm_handle() for the
    * passsword timeout handle */
   if (mode == 1) {
      signal(SIGALRM, alarm_handle);
      alarm(banner[mode].time_out);
   }
   
   /* get pass :) */
   get_line(connfd, pass, MAX_CHAR, banner[mode].echo_char);
   
   return pass;
}

/* sends "access denied" message */
int fake_access_denied_msg(int connfd)
{
   /* fake "access denied" message -> saying, that the passes were wrong ;) */
   xwrite(connfd, banner[mode].ad_msg, strlen(banner[mode].ad_msg));
   
   return 1;
}

int fake_login(struct sockaddr_in caddr, int connfd)
{
   char *user = NULL;
   char *pass = NULL;
   char *ipaddr = NULL;
   uint16_t port = 0;
   int i = 0, j;
   int limit = 0;

   ipaddr = inet_ntoa(caddr.sin_addr);
   port = ntohs(caddr.sin_port); 
   
   fake_banner_msg(connfd);
   
   /* some devices don't need a user */
   limit = (banner[mode].user_retries == 0 ? 1 : banner[mode].user_retries);
   for (i = 0; i < limit; i++) {
      user = fake_get_user(connfd);
      for (j = 0; j < banner[mode].pass_retries; j++) {
         pass = fake_get_pass(connfd);
			log_login(user, pass, ipaddr, port);
         free(pass);
         /* how many time "pass wrong"-messages should be send? */
         if ((j + 1) % banner[mode].timeout_flag == 0) {
            fake_access_denied_msg(connfd);
         }
      }
      free(user);
   }
   /* RST, close connection */
   xshutdown(connfd, SHUT_RDWR);
   
   return 1;
}

/* EOF */


syntax highlighted by Code2HTML, v. 0.9.1