home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / junkbust / win / socks4.c < prev    next >
C/C++ Source or Header  |  1998-10-30  |  4KB  |  176 lines

  1. char *socks4_rcs = "$Id: socks4.c,v 1.10 1997/09/11 18:35:41 ACJC Exp $";
  2. /* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation.
  3.  * Distributed under the GNU General Public License; see the README file.
  4.  * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html
  5.  */
  6.  
  7.  
  8.  
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <errno.h>
  12.  
  13. #ifdef _WIN32
  14. #include <io.h>
  15. #include <windows.h>
  16. #else
  17. #include <unistd.h>
  18. #include <netinet/in.h>
  19. #endif
  20.  
  21. #ifdef REGEX
  22. #include <gnu_regex.h>
  23. #endif
  24.  
  25. #include "jcc.h"
  26.  
  27. #define SOCKS_REQUEST_GRANTED        90
  28. #define SOCKS_REQUEST_REJECT        91
  29. #define SOCKS_REQUEST_IDENT_FAILED    92
  30. #define SOCKS_REQUEST_IDENT_CONFLICT    93
  31.  
  32. /* structure of a socks client operation */
  33. struct socks_op {
  34.     unsigned char vn;        /* socks version number */
  35.     unsigned char cd;        /* command code        */
  36.     unsigned char dstport[2];    /* destination port    */
  37.     unsigned char dstip[4];        /* destination address    */
  38.     unsigned char userid;        /* first byte of userid    */
  39.     /* more bytes of the userid follow, terminated by a NULL    */
  40. };
  41.  
  42. /* structure of a socks server reply */
  43. struct socks_reply {
  44.     unsigned char vn;        /* socks version number */
  45.     unsigned char cd;        /* command code        */
  46.     unsigned char dstport[2];    /* destination port    */
  47.     unsigned char dstip[4];        /* destination address    */
  48. };
  49.  
  50. static char socks_userid[] = "anonymous";
  51.  
  52. int
  53. socks4_connect(struct gateway *gw, struct http_request *http, struct client_state *csp)
  54. {
  55.     unsigned char cbuf[BUFSIZ];
  56.     unsigned char sbuf[BUFSIZ];
  57.     struct socks_op    *c = (struct socks_op    *)cbuf;
  58.     struct socks_reply *s = (struct socks_reply *)sbuf;
  59.     int web_server_addr;
  60.     int n, csiz, sfd, target_port;
  61.     int err = 0;
  62.     char *errstr, *target_host;
  63.  
  64.     if((gw->gateway_host == NULL) || (*gw->gateway_host == '\0')) {
  65.         if(DEBUG(CON)) fprintf(logfp,
  66.             " socks4_connect: NULL gateway host specified\n");
  67.         err = 1;
  68.     }
  69.  
  70.     if(gw->gateway_port <= 0) {
  71.         if(DEBUG(CON)) fprintf(logfp,
  72.             " socks4_connect: invalid gateway port specified\n");
  73.         err = 1;
  74.     }
  75.  
  76.     if(err) {
  77.         errno = EINVAL;
  78.         return(-1);
  79.     }
  80.  
  81.     if(gw->forward_host) {
  82.         target_host = gw->forward_host;
  83.         target_port = gw->forward_port;
  84.     } else {
  85.         target_host = http->host;
  86.         target_port = http->port;
  87.     }
  88.  
  89.     /* build a socks request for connection to the web server */
  90.  
  91.     strcpy((char *)&(c->userid), socks_userid);
  92.  
  93.     csiz = sizeof(*c) + sizeof(socks_userid) - 1;
  94.  
  95.     switch(gw->type) {
  96.     case SOCKS_4:
  97.         web_server_addr = htonl(atoip(target_host));
  98.         break;
  99.     case SOCKS_4A:
  100.         web_server_addr = 0x00000001;
  101.         n = csiz + strlen(target_host) + 1;
  102.         if(n > sizeof(cbuf)) {
  103.             errno = EINVAL;
  104.             return(-1);
  105.         }
  106.         strcpy(((char *)cbuf) + csiz, http->host);
  107.         csiz = n;
  108.         break;
  109.     }
  110.  
  111.     c->vn         = 4;
  112.     c->cd         = 1;
  113.     c->dstport[0] = (target_port      >> 8) & 0xff;
  114.     c->dstport[1] = (target_port          ) & 0xff;
  115.     c->dstip[0]   = (web_server_addr >> 24) & 0xff;
  116.     c->dstip[1]   = (web_server_addr >> 16) & 0xff;
  117.     c->dstip[2]   = (web_server_addr >>  8) & 0xff;
  118.     c->dstip[3]   = (web_server_addr      ) & 0xff;
  119.  
  120.     /* pass the request to the socks server */
  121.     sfd = connect_to(gw->gateway_host, gw->gateway_port, csp);
  122.  
  123.     if(sfd < 0) {
  124.         return(-1);
  125.     }
  126.  
  127.     if((n = write_socket(sfd, c, csiz)) != csiz) {
  128.         if(DEBUG(CON)) {
  129.             fprintf(logfp, "SOCKS4 negotiation write failed...");
  130.         }
  131.         close_socket(sfd);
  132.         return(-1);
  133.     }
  134.  
  135.     if((n = read_socket(sfd, sbuf, sizeof(sbuf))) != sizeof(*s)) {
  136.         if(DEBUG(CON)) {
  137.             fprintf(logfp, "SOCKS4 negotiation read failed...");
  138.         }
  139.         close_socket(sfd);
  140.         return(-1);
  141.     }
  142.  
  143.     switch(s->cd) {
  144.     case SOCKS_REQUEST_GRANTED:
  145.         return(sfd);
  146.         break;
  147.     case SOCKS_REQUEST_REJECT:
  148.         errstr = "SOCKS request rejected or failed";
  149.         errno = EINVAL;
  150.         break;
  151.     case SOCKS_REQUEST_IDENT_FAILED:
  152.         errstr = "SOCKS request rejected because "
  153.              "SOCKS server cannot connect to identd on the client";
  154.         errno = EACCES;
  155.         break;
  156.     case SOCKS_REQUEST_IDENT_CONFLICT:
  157.         errstr = "SOCKS request rejected because "
  158.              "the client program and identd report "
  159.              "different user-ids";
  160.         errno = EACCES;
  161.         break;
  162.     default:
  163.         errstr = (char *) cbuf;
  164.         errno = ENOENT;
  165.         sprintf(errstr,
  166.             "SOCKS request rejected for reason code %d\n", s->cd);
  167.     }
  168.  
  169.     if(DEBUG(CON)) {
  170.         fprintf(logfp, " socks4_connect: %s ...", errstr);
  171.     }
  172.  
  173.     close_socket(sfd);
  174.     return(-1);
  175. }
  176.