home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / hacking / internet / circ01.sh / Circ / sock2.c < prev   
Encoding:
C/C++ Source or Header  |  1993-08-11  |  16.8 KB  |  586 lines

  1. /* Nathan Laredo - "Green" - gt7080a@prism.gatech.edu */
  2. /* mini-client, semi-raw input, formatted output */
  3. /* supports none of pre-2.7.2 protocol in formatting */
  4. /* the documentation takes up lots of the space here */
  5.  
  6. /* modified Apr 21, 1993 "xxx".  Changed to a special- */
  7. /* purpose encryption program                          */
  8.  
  9. #include <stdio.h>
  10. #ifdef pyr
  11. #include <strings.h>
  12. #else
  13. #include <string.h>
  14. #endif
  15. #include <errno.h>
  16. #include <sys/types.h>
  17. #include <sys/time.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <netdb.h>
  21. #include "sock.h"
  22.  
  23. char *encode(),*decode();
  24. char *en_crypt(),*de_crypt(); /* external, in crypt.c */
  25.  
  26. #define KEYLEN  24+1
  27. #define MAXKEYS 30
  28. #define HUGE 1024
  29. #define SECKEY  "secret"      /* secret key file,  should be a variable */
  30.  
  31. char keys[MAXKEYS][KEYLEN];   /* keys           */
  32. unsigned int  sers[MAXKEYS];           /* serial numbers */
  33.  
  34. int s,d;                      /* IRC socket, DCC socket      */ 
  35. char buf[512];                /* global text data buffer     */
  36. char curchan[256];          /* current active channel      */
  37. char localhost[64];          /* the local machine's name    */
  38. int dcchost,dccsock;          /* for implementing DCC         */
  39. char dccbuf[2048];          /* buffer for incomming         */
  40. char dccname[512];          /* filename for dcc transfer   */
  41. unsigned long int dcclength;  /* dcc reply/check         */
  42. char inputbuf[512];          /* buffer for user input         */
  43. char IRCNAME[32];          /* storage for current nick    */
  44. fd_set readfs, orig;
  45. int sok=1;            /* socket ok flag */
  46.  
  47. char *token[1024]; /* worst case: 1 2 3 4 5 .. etc 512 chars */
  48.  
  49. /* casecmp(a,b)
  50.      a,b - null terminated strings.
  51.        does a non-case sensitive compare
  52.  */
  53. #define To_lower(a)    (isupper(a)?tolower(a):(a))
  54.  
  55. casecmp(a,b)
  56. char *a,*b;
  57. {
  58.   while(*a && *b) 
  59.     if(To_lower(*a) != To_lower(*b)) 
  60.       return (*b-*a);   /* doesnt really matter if they are diff cases here*/
  61.     else {
  62.       a++,b++;
  63.     }
  64.   return(0);
  65. }
  66.  
  67. /* asctobin(str,len)
  68.      str - ascii string (null terminated)
  69.      len - int *,   RETURN length of binary block
  70.      returns:  char * to binary block data in static storage.
  71.        coding:
  72.          high nybble - 'a'=0 to 'p'=15
  73.          low nybble  - 'A'=0 to 'P'=15
  74.       NULL returned for bad encoding. 
  75.  */
  76. char *asctobin(str,len)
  77. char *str;
  78. int *len;
  79. {
  80.   static char buf[HUGE];
  81.   char a,b;
  82.   int i;
  83.  
  84.   for(i=0;;) {
  85.     a=*str++;
  86.     while(a==' '||a=='\n') a=*str++;
  87.     b=*str++;
  88.     if(a=='\0' || b=='\0') {
  89.       *len=i;
  90.       return(buf);
  91.     }
  92.     if (a<'a'||a>'p' || b<'A'||b>'P') 
  93.       return(0);
  94.     buf[i++] = ((a-'a')<<4)|(b-'A');
  95.   }
  96. }
  97.  
  98. /* bintoasc(str,len)
  99.       str - a pointer to a binary block
  100.       len - length of binary block in bytes
  101.       return - char * to a string that is ascii, null-terminated
  102.         coding -
  103.            high nybble  'a'=0 to 'p'=15
  104.            low nybble   'A'=0 to 'P'=15
  105.  */
  106. char *bintoasc(str,len)
  107. int len;
  108. char *str;
  109. {
  110.   static char buf[HUGE];
  111.   int i;
  112.   
  113.   for(i=0;len-- >0;str++) {
  114.     buf[i++]=((*str&0xf0)>>4) + 'a';
  115.     buf[i++]=(*str&0xf) + 'A'; 
  116.   }
  117.   buf[i]='\0';
  118.   return(buf);
  119. }
  120.  
  121. /* encode(str)
  122.      str - an ascii null-terminated string 
  123.      returned - char * an encoded null terminated ascii string
  124.      encoding:
  125.        CLIPPER:xxxx:yyyyyyyyyyyyy
  126.           xxxx - serial number of key used
  127.           yyyyy- ascii coded, encrypted text message
  128.  */
  129. char *encode(str)
  130. char *str;
  131. {
  132.   int l,ser,a;
  133.   static char buf[HUGE];
  134.   char *p;
  135.  
  136.   set_key(keys[0]);          /* use our key and our serial number */
  137.   a=strlen(str)-1;
  138.   if(str[a]=='\n') str[a]='\0';
  139.   str[a++]='\0';
  140.   p=en_crypt(str ,a,&l);
  141.   sprintf(buf,"CLIPPER:%d:",sers[0]);
  142.   strcat(buf,bintoasc(p,l));
  143.   strcat(buf,"\n");
  144.   return(buf);
  145. }
  146.  
  147. /*  decode(ar,len)
  148.       ar - array of words like argv[]
  149.       len - number of words,  like argc
  150.       return - char * to a decoded ascii null-termianted string
  151.        coding:  see encode()
  152.        error codes are returned as human readable strings.
  153.  
  154.         CLIPPER:xxxx:yyyyyy
  155.             x - ascii serial number
  156.             y - ascii encoded binary data, crypted
  157.         SKPJACK:xxxx:yyyy:zzzz
  158.             x - nick name of destination
  159.             y - serial number of key being received
  160.             z - ascii encoded binary data,  encrypted with rsa
  161.                 in 'nick's public key ,  contains the key
  162.                 needed to read messages from nick
  163.  */
  164. char *decode(ar,len)
  165. char *ar[];
  166. int len;
  167. {
  168.   char *p;      /* lots of chars */
  169.   static char buf[HUGE];
  170.   int i,ser,l,a,itsakey=0;
  171.   
  172.   buf[0]='\0';
  173.   for(i=0;i<len;i++) {    /* put it into a single string */
  174.     strcat(buf,ar[i]); 
  175.     strcat(buf," ");      /* spaces seperate tokens */
  176.   }
  177.   if(strncmp(buf,"SKPJACK:",8)==0) 
  178.     itsakey=1;                          /* someones sending a key */
  179.   else if(strncmp(buf,"CLIPPER:",8))   
  180.       return(0);                    /* not encoded */
  181.   for(i=8;buf[i]!=':'&&buf[i]!='\0';i++);  /* jump past ser # */
  182.   if(buf[i]!=':') {
  183.     return("*Badly Formed*\n");
  184.   }
  185.   buf[i++]='\0';
  186.   ser=atoi(buf+8);                          /* this is ser # */
  187.  
  188.   if(itsakey && casecmp(buf+8,IRCNAME)==0) {      /* new key sent to us */
  189.     ser=atoi(buf+i);
  190.     for(;buf[i]!=':'&&buf[i]!='\0';i++) ;
  191.     if(buf[i++]!=':') return("*Newkey: badly formed*");
  192.     p=asctobin(buf+i,&len);
  193.     if(!p) 
  194.       return("*new key: bad coding*");
  195.     memcpy(buf,p,len);         /* copy binary data */
  196.     if(do_rsa(SECKEY,buf,len,HUGE)<0) 
  197.       return("*new key: couldnt decrypt (rsa)*");
  198.     for(i=0;i<MAXKEYS;i++) 
  199.       if(sers[i]==0 || sers[i]==ser) break;
  200.     if(i==MAXKEYS) return ("*new key: out of table entries*");
  201.                     /* *never* receive a key we already have */
  202.                     /* this could be a trick                 */
  203.     if(sers[i]==ser) return("*new key: already have it!*");
  204.     sers[i]= ser;
  205.     memcpy(keys[i],buf,KEYLEN);
  206.     return("*New Key installed*");
  207.   }
  208. if (itsakey) printf("Saw key for %s\n",buf+8);
  209.   if (itsakey) return("*Key received, but not for us*");
  210.  
  211.   /* else its a message , try to decode */  
  212.   a=key(ser);                               /* find the key */
  213.   if(a==-1) return("*Dont Have the Key*\n");
  214.   set_key(keys[a]);
  215.   p=asctobin(buf+i,&len);                   /* decrypt it */
  216.   if(!p) return("*Bad Encoding*");
  217.   sprintf(buf,"<E> %s",de_crypt(p,len,&l));
  218.   return(buf);
  219. }
  220.  
  221. /*  key(ser)
  222.       ser = serial number 
  223.       returned - index to the key with serial number ser, else -1 
  224.  */
  225. int key(ser)
  226. int ser;
  227. {
  228.   int i;
  229.  
  230.   for(i=0;i<MAXKEYS;i++)
  231.     if(ser == sers[i]) return(i);
  232.   return(-1);
  233. }
  234.  
  235. /* sendkey(line)
  236.      line - char *,  everything after  /key on the command line
  237.        parsed to 'nick' and the optional 'filename'
  238.        filename is set to nick if it doesnt exist.
  239.      encodes our key and serial number with nick's public
  240.      key and sends it over the current channel for him
  241.      to receive 
  242.  */
  243. sendkey(line)     /* handle  /key nick [filename]   */
  244. char *line;
  245. {
  246.   char *file,*nick,*p;
  247.   char buf[1024];
  248.   int len;
  249.  
  250.   while(*line==' ') line++;
  251.   nick=line;
  252.   while(*line!=' '&&*line!='\0'&&*line!='\n') line++; 
  253.   if(*line=='\n') *line='\0';
  254.   if(*line=='\0') 
  255.     file=nick;
  256.   else {
  257.     *line++='\0';
  258.     file=line;
  259.     while(*line!=' '&&*line!='\0'&&*line!='\n') line++; 
  260.     *line='\0';
  261.   }
  262.   if(*nick=='\0') {
  263.     printf("*ERROR*  nick missing,  /key nick [file]");
  264.     return;
  265.   }
  266.  
  267.   memcpy(buf,keys[0],KEYLEN);
  268.   len=do_rsa(file,buf,KEYLEN,1024);
  269.   if(len<0)  {
  270.     printf("*ERROR* dont have public key for %s\n",file);
  271.     return;                 /* couldnt send it, RSA failed */
  272.   }
  273.   p=bintoasc(buf,len);
  274.   sprintf(buf,"PRIVMSG %s SKPJACK:%s:%d:%s\n",
  275.           curchan,nick,sers[0],p);
  276.   writeln(buf);     /* send it to irc */
  277. }
  278.  
  279.  
  280. int call_socket(hostname)
  281.   char *hostname;
  282. {
  283.   struct sockaddr_in sa;
  284.   struct hostent     *hp;
  285.   int    a, s;
  286.  
  287.   bzero(&sa, sizeof(sa));
  288.   sa.sin_family = AF_INET;
  289.   sa.sin_addr.s_addr = inet_addr(hostname);
  290.   if (sa.sin_addr.s_addr ==-1) {
  291.     if ((hp=gethostbyname(hostname))==NULL) {
  292.       errno=ECONNREFUSED;
  293.       return(-1);
  294.     }
  295.     sa.sin_family = hp->h_addrtype;
  296.     bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
  297.   }
  298.   sa.sin_port = htons((u_short)DEFAULTPORT);
  299.  
  300.   if((s=socket(sa.sin_family, SOCK_STREAM, 0)) < 0)
  301.     return(-1);
  302.   if(connect(s, &sa, sizeof(sa)) < 0) {
  303.     close(s);
  304.     return(-1);
  305.   }
  306.   return(s);
  307. }
  308.  
  309. int dcc_socket(host,sock)
  310. unsigned long int host;
  311. int sock;
  312. {
  313. struct sockaddr_in sa;
  314. int    a, d;
  315.  
  316.   bzero(&sa, sizeof(sa));
  317.   bcopy(&host, (char *)&sa.sin_addr, sizeof(host));
  318.   sa.sin_family = AF_INET;
  319.   sa.sin_port = htons((u_short)sock);
  320.  
  321.   if((d=socket(PF_INET, SOCK_STREAM, 0)) < 0)
  322.     return(-1);
  323.   if(connect(s, &sa, sizeof(sa)) < 0) {
  324.     close(d);
  325.     return(-1);
  326.   }
  327. return(d);
  328. }
  329.  
  330.  
  331. int readln(buf)
  332.   char *buf;
  333. {
  334.   int to=0;
  335.   char c;
  336.   do { /* will never overflow 'cause 
  337.     server can't send more than 512 bytes */
  338.       if(read(s, &c, 1)<1) return(0);
  339.       buf[to++] = c;
  340.   } while (c != '\n');
  341.   buf[to-1] = '\0';
  342.   return(1);
  343. }
  344.  
  345. int writeln(buf)
  346.   char *buf;
  347. {
  348.   int to=0;
  349.   if( write(s, buf, strlen(buf)) < to )
  350.     return(0);
  351.   return(1);
  352. }
  353.  
  354. int dcc_getblock(so,fi)
  355. char *so,*fi;
  356. { char r;
  357.    if (r=read(so, dccbuf, 2048)) {
  358.         dcclength += r;
  359.         printf("[%08x]",dcclength);
  360.         write(so, htons((unsigned long int) dcclength), sizeof(dcclength));
  361.         write(fi, dccbuf, r);
  362.     return(1);
  363.         } /* if block is still there */
  364.     close(fi); close(so);
  365.     printf("DCC successful!\n");
  366.     return (0); /* done */
  367. }
  368.  
  369. dojoin() /* had to separate because the language is dumb */
  370. {
  371.     if(strcmp(token[0],IRCNAME)==0) {
  372.       printf("*** Current channel is now %s",token[2]);
  373.       strcpy(curchan,token[2]);
  374.       } /* case change current channel (nick=ircnick) */
  375.     else printf("*** %s has joined channel %s",token[0],token[2]);
  376. } /* end of dojoin */
  377.  
  378. dopart() /* see above */
  379. {
  380.     if(strcmp(token[0],IRCNAME)==0) {
  381.       if(strcmp(curchan,token[2])==0) { /* yur leaving your curent channel */
  382.         printf("*** Current channel is now invalid until you use join");
  383. /* you could probably implement a get last channel in if you wanted */
  384.         strcpy(curchan,"=invalid"); /* literally :-) */
  385.         } /* case invalidate current channel */
  386.       } /* damn I hate this */
  387.     else printf("*** %s has left channel %s",token[0],token[2]);
  388. } /* end of part garbage */
  389.  
  390. donick()
  391. {
  392. if(strcmp(token[0],IRCNAME)==0) { strcpy(IRCNAME,token[2]);
  393.     printf("*** You have changed your nickname to %s", token[2]);
  394.     } /* if you're doing this to yourself */
  395.     else printf("*** %s is now known as %s",token[0],token[2]);
  396. } /* I hate this language - if only it could read my mind */
  397.  
  398. doprivmsg(tokencount)
  399. int tokencount;
  400. { int i;
  401.   char *p;
  402.  
  403.     if(*(++token[3])=='\01') /* ctcp reply */
  404.       printf("*** CTCP MESSAGE FROM %s: ",token[0]);
  405.     else {
  406.       printf("<%s-%s> ",token[0],token[2]);
  407. /* decrypt here */
  408.       p=decode(token+3,tokencount-3);
  409.       if(p) {               /* if not encoded drop through */
  410.         printf("%s",p);
  411.         return;
  412.       }
  413.     }
  414.     for(i=3;i<tokencount; i++) printf("%s ",token[i]);
  415.  
  416. /*  DO CTCP GOES HERE (INCLUDES DCC)  */
  417. } /* privmsg */
  418.  
  419. donotice(tokencount)
  420. int tokencount;
  421. { int i;
  422.     if(*(++token[3])=='\01') /* ctcp reply */
  423.       printf("*** CTCP REPLY FROM %s: ",token[0]);
  424.     /* if there's a . in nick we KNOW it's not a user */
  425.     else if (strchr(token[0],'.')==0) printf("-%s- ",token[0]);
  426.     for(i=3;i<tokencount; i++) printf("%s ",token[i]);
  427. } /* notice */
  428.  
  429. int spitout(servstr) /* filter line to make more pleasing and spit out */
  430. char *servstr;
  431. { int i;
  432.   char *temp;
  433.   int tokencount=0;
  434.   if (strncmp(servstr,"PING",4)==0) { /* make pings/pongs transparent */
  435.     temp=strncpy(servstr,"PO",2);
  436.     return(writeln(strcat(temp,"\n"))); /* needs new line-gone before */
  437.   }
  438.   /* tokenize */
  439.   token[0]=strtok(servstr," "); tokencount++;
  440.   while(token[tokencount++]=strtok(NULL, " "));
  441.   tokencount -= 1; /* need to fix for newline */
  442.   /* each token contains exactly one word, and only one now */
  443.   if(*token[0] != ':') { /* notice message from server usually */
  444.     for(i=0;i<tokencount; i++) printf("%s ",token[i]);
  445.     printf("\n");
  446.     return(0);
  447.     } /* if first char not : */
  448.   else token[0]++; /* point at next char past colon */
  449.   if(temp=strchr(token[0],'!')) *temp='\0'; /* strip address if there */
  450.  
  451. /* main parsing stuff - follows parse.c in ircII pretty closely */
  452.  
  453.   if(strcmp(token[1],"PRIVMSG")==0) doprivmsg(tokencount);
  454.   else if(strcmp(token[1],"NOTICE")==0) donotice(tokencount);
  455.   else if(strlen(token[1])==3)  /* server message, just print */
  456.     for(i=3;i<tokencount; i++) printf("%s ",token[i]);
  457.   else if(strcmp(token[1],"JOIN")==0) dojoin();
  458.   else if(strcmp(token[1],"PART")==0) dopart();
  459.   else if(strcmp(token[1],"QUIT")==0) {
  460.     printf("*** signoff (%s)",token[0]);
  461.     for(i=2;i<tokencount; i++) printf(" %s",token[i]);
  462.     } /* if someone's leaving irc */ 
  463.   else if(strcmp(token[1],"TOPIC")==0) {
  464.     printf("*** %s has changed the topic on %s to",token[0],token[2]);
  465.     for(i=3;i<tokencount; i++) printf(" %s",token[i]); }
  466.   else if(strcmp(token[1],"INVITE")==0)
  467.     printf("*** You have been invited to join channel %s by %s",token[2],
  468.         token[0]);
  469.   else if(strcmp(token[1],"NICK")==0) donick();
  470.   else if(strcmp(token[1],"KILL")==0) /* Hmmm, never got one, but hell */
  471.     printf("*** %s killed by %s",token[2],token[0]);
  472.   else if(strcmp(token[1],"MODE")==0) /* well, there are mode changes */
  473.     printf("*** Mode change on %s by %s to %s",token[2],token[0],token[3]);
  474.   else if(strcmp(token[1],"KICK")==0)
  475.     printf("*** %s has kicked %s from %s",token[0], token[2], token[3]);
  476.   else if(strncmp(token[1],"ERROR",5)==0) {
  477.     printf("*** ERROR:");
  478.     for(i=2;i<tokencount; i++) printf(" %s",token[i]); }
  479.   else /* if all else fails */
  480.   { printf("***"); for(i=0;i<tokencount; i++) printf(" %s",token[i]); }
  481. putchar('\n'); /* if you get a blank line at this point this code sucks */
  482. return(0);
  483. }
  484.  
  485. int dottyinput()
  486. {
  487.    char c;
  488.   int to=0;
  489.   do {
  490.   if(read(1, &c, 1)<1) return(0);
  491.     inputbuf[to++] = c;
  492.    } while (c != '\n');
  493.    inputbuf[to] = '\0';
  494.    if (inputbuf[0]==COMMANDCHAR){
  495.      if(strncmp(inputbuf+1,"key",3)==0)
  496.        sendkey(inputbuf+4);
  497.      else
  498.        writeln(inputbuf+1);
  499.    }
  500.    else {
  501.  
  502. /* encrypt here */
  503.    sprintf(buf,"PRIVMSG %s %s",curchan,encode(inputbuf));
  504.    writeln(buf);
  505.    } /* no cmd character tried default */
  506.    return(1);
  507. }
  508.  
  509. main(argc, argv)
  510.   int argc;
  511.   char **argv;
  512. {
  513.   char hostname[64];
  514.   char *logfile=NULL;
  515.   int c, errflag;
  516.   extern int optind, opterr;
  517.   extern char *optarg;
  518.   char line[512];
  519.  
  520.   int i;
  521.  
  522.   /* pick random 8 bit key -> K           */
  523.   /* encrypt  crypt(K,K) -> serial number */
  524.   /* pick random 8 bits  L                */
  525.   /* encrypt  crypt(L,K) -> our DES key   */
  526.   srand(time(0));
  527.   for(i=0;i<KEYLEN;i++)
  528.     keys[0][i]= (char)((rand()&0xff00)>>8);
  529.   set_key(keys[0]);
  530.   en_crypt(keys[0],KEYLEN,&i);
  531.   sers[0] = (int) *((int *)keys[0]);  /* pick serial number */
  532.   /* if(sers[0]<0) sers[0]=-sers[0];     /* problem with negative ser #'s */
  533.   for(i=0;i<KEYLEN;i++)
  534.     keys[0][i]= (char)((rand()&0xff00)>>8);
  535.   en_crypt(keys[0],KEYLEN,&i);
  536.  
  537.   if(getenv("IRCNICK")==NULL || getenv("LOGNAME")==NULL || 
  538.      getenv("IRCNAME")==NULL) {
  539.   printf("The following settings in your environment are not set properly:\n");
  540.   if (getenv("IRCNICK")==NULL) printf("IRCNICK should be set with a nick\n");
  541.   if (getenv("LOGNAME")==NULL) printf("LOGNAME should contain user id\n");
  542.   if (getenv("IRCNAME")==NULL) printf("IRCNAME should contain real name\n");
  543.   exit(0);
  544.   }
  545. if(argc>1) { /* assume only one param, hostname */
  546.   if (strchr(argv[1],'.')==0) { /* shouldn't a host have a period? */
  547.     fprintf(stderr,"usage: %s ircservername initialchannel\n", argv[0]);
  548.    exit(0); }
  549.   strcpy(hostname,argv[1]); }
  550.   else strcpy(hostname,DEFAULTSERVER);
  551.   gethostname(localhost, 64);
  552.   if ((s=call_socket(hostname))==-1) {
  553.     fprintf(stderr, "Could not connect to %s, aborting\n", hostname);
  554.     exit(0);
  555.   }
  556.   sprintf(buf, "NICK %s\n", getenv("IRCNICK"));
  557.   writeln(buf);
  558.   sprintf(buf, "USER %s 1 1 %s\n", getenv("LOGNAME"), getenv("IRCNAME"));
  559.   writeln(buf);
  560.   strcpy(curchan,"=invalid");
  561.   strncpy(IRCNAME,getenv("IRCNICK"),sizeof(IRCNAME));
  562.   if(argc>2) /* well we'll call this the channel to join */
  563.   { sprintf(buf, "JOIN %s\n", argv[2]); writeln(buf); }
  564.   if(argc>3) { /* assume you don't know what the hell you want */
  565.     fprintf(stderr,"usage: %s ircservername initialchannel\n", argv[0]);
  566.     exit(0); }
  567.   FD_ZERO(&readfs);
  568.   FD_SET(s,&readfs);
  569.   FD_SET(1,&readfs);
  570.   orig = readfs;
  571.   while(sok) {
  572. /* notice how when one character is there, we assume a whole line is
  573.    waiting for us to read.  This is because we're doing cooked i/o to
  574.    keep resources minimal */
  575.     if(select(FD_SETSIZE, &readfs, NULL, NULL, NULL)) {
  576.     if(FD_ISSET(1,&readfs)) if(!dottyinput()) return(1);
  577.     if(FD_ISSET(s,&readfs)) { 
  578.     sok = readln(line); 
  579.     if (sok) spitout(line);
  580.     } /* if s */
  581.     } /* if select */
  582. readfs = orig;
  583. }
  584.   return(1); /* assume that these files will be properly closed */
  585. }
  586.