"Fossies" - the Fresh Open Source Software Archive

Member "HTTPing-2.9/socks5.c" (29 Oct 2022, 4334 Bytes) of package /linux/www/HTTPing-2.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "socks5.c" see the Fossies "Dox" file reference documentation.

    1 #include <libintl.h>
    2 #include <unistd.h>
    3 #include <stdio.h>
    4 #include <string.h>
    5 #include <sys/types.h>
    6 #include <sys/socket.h>
    7 #include <netinet/in.h>
    8 #include <sys/time.h>
    9 #include <time.h>
   10 #include <netdb.h>
   11 #include <arpa/inet.h>
   12 
   13 #include "error.h"
   14 #include "gen.h"
   15 #include "io.h"
   16 #include "res.h"
   17 #include "tcp.h"
   18 
   19 int socks5connect(int fd, struct addrinfo *ai, double timeout, const char *socks5_username, const char *socks5_password, const char *host, int port, char abort_on_resolve_failure)
   20 {
   21     struct sockaddr_in sai;
   22     uint32_t addr = 0;
   23     unsigned char io_buffer[256] = { 0 };
   24     int io_len = 0, rc = -1;
   25 
   26     if ((rc = connect_to(fd, ai, timeout, NULL, NULL, 0, NULL)) == -1)
   27         return rc;
   28 
   29     /* inform socks server about the auth. methods we support */
   30     if (socks5_username != NULL)
   31     {
   32         io_buffer[0] = 0x05;    /* version */
   33         io_buffer[1] = 2;   /* 2 authentication methods */
   34         io_buffer[2] = 0x00;    /* method 1: no authentication */
   35         io_buffer[3] = 0x02;    /* method 2: username/password */
   36         io_len = 4;
   37     }
   38     else
   39     {
   40         io_buffer[0] = 0x05;    /* version */
   41         io_buffer[1] = 1;   /* 2 authentication methods */
   42         io_buffer[2] = 0x00;    /* method 1: no authentication */
   43         io_len = 3;
   44     }
   45 
   46     if ((rc = mywrite(fd, (char *)io_buffer, io_len, timeout)) < 0)
   47         return rc;
   48 
   49     /* wait for reply telling selected authentication method */
   50     if ((rc = myread(fd, (char *)io_buffer, 2, timeout)) < 0)
   51         return rc;
   52 
   53     if (io_buffer[0] != 0x05)
   54     {
   55         set_error(gettext("socks5connect: reply with requested authentication method does not say version 5 (%02x)"), io_buffer[0]);
   56         return RC_INVAL;
   57     }
   58 
   59     if (io_buffer[1] == 0x00)
   60     {
   61         /* printf("socks5connect: \"no authentication at all\" selected by server\n"); */
   62     }
   63     else if (io_buffer[1] == 0x02)
   64     {
   65         /* printf("socks5connect: selected username/password authentication\n"); */
   66     }
   67     else
   68     {
   69         set_error(gettext("socks5connect: socks5 refuses our authentication methods: %02x"), io_buffer[1]);
   70         return RC_INVAL;
   71     }
   72 
   73     /* in case the socks5 server asks us to authenticate, do so */
   74     if (io_buffer[1] == 0x02)
   75     {
   76         int io_len = 0;
   77 
   78         if (socks5_username == NULL || socks5_password == NULL)
   79         {
   80             set_error(gettext("socks5connect: socks5 server requests username/password authentication"));
   81             return RC_INVAL;
   82         }
   83 
   84         io_buffer[0] = 0x01;    /* version */
   85         io_len = snprintf((char *)&io_buffer[1], sizeof io_buffer - 1, "%c%s%c%s", (int)strlen(socks5_username), socks5_username, (int)strlen(socks5_password), socks5_password);
   86 
   87         if ((rc = mywrite(fd, (char *)io_buffer, io_len + 1, timeout)) < 0)
   88         {
   89             set_error(gettext("socks5connect: failed transmitting username/password to socks5 server"));
   90             return rc;
   91         }
   92 
   93         if ((rc = myread(fd, (char *)io_buffer, 2, timeout)) < 0)
   94         {
   95             set_error(gettext("socks5connect: failed receiving authentication reply"));
   96             return rc;
   97         }
   98 
   99         if (io_buffer[1] != 0x00)
  100         {
  101             set_error(gettext("socks5connect: password authentication failed"));
  102             return RC_INVAL;
  103         }
  104     }
  105 
  106     /* ask socks5 server to associate with server */
  107     io_buffer[0] = 0x05;    /* version */
  108     io_buffer[1] = 0x01;    /* connect to */
  109     io_buffer[2] = 0x00;    /* reserved */
  110     io_buffer[3] = 0x01;    /* ipv4 */
  111 
  112     if (resolve_host_ipv4(host, &sai) == -1)
  113     {
  114         if (abort_on_resolve_failure)
  115             error_exit(gettext("Cannot resolve %s"), host);
  116 
  117         return RC_INVAL;
  118     }
  119 
  120     addr = ntohl(sai.sin_addr.s_addr);
  121 
  122     io_buffer[4] = (addr >> 24) & 255;
  123     io_buffer[5] = (addr >> 16) & 255;
  124     io_buffer[6] = (addr >>  8) & 255;
  125     io_buffer[7] = (addr      ) & 255;
  126 
  127     io_buffer[8] = (port >> 8) & 255;
  128     io_buffer[9] = (port     ) & 255;
  129 
  130     if ((rc = mywrite(fd, (char *)io_buffer, 10, timeout)) < 0)
  131     {
  132         set_error(gettext("socks5connect: failed to transmit associate request"));
  133         return rc;
  134     }
  135 
  136     if ((rc = myread(fd, (char *)io_buffer, 10, timeout)) < 0)
  137     {
  138         set_error(gettext("socks5connect: command reply receive failure"));
  139         return rc;
  140     }
  141 
  142     /* verify reply */
  143     if (io_buffer[0] != 0x05)
  144     {
  145         set_error(gettext("socks5connect: bind request replies with version other than 0x05 (%02x)"), io_buffer[0]);
  146         return RC_INVAL;
  147     }
  148 
  149     if (io_buffer[1] != 0x00)
  150     {
  151         set_error(gettext("socks5connect: failed to connect (%02x)"), io_buffer[1]);
  152         return RC_INVAL;
  153     }
  154 
  155     if (io_buffer[3] != 0x01)
  156     {
  157         set_error(gettext("socks5connect: only accepting bind-replies with IPv4 address (%02x)"), io_buffer[3]);
  158         return RC_INVAL;
  159     }
  160 
  161     return RC_OK;
  162 }