"Fossies" - the Fresh Open Source Software Archive

Member "scanssh-2.1/socks.c" (5 Nov 2004, 11426 Bytes) of package /linux/privat/old/scanssh-2.1.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.

    1 /*
    2  * Copyright 2000-2004 (c) Niels Provos <provos@citi.umich.edu>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/types.h>
   29 
   30 #ifdef HAVE_CONFIG_H
   31 #include "config.h"
   32 #endif
   33 
   34 #include <sys/tree.h>
   35 #include <sys/queue.h>
   36 #include <sys/socket.h>
   37 #include <sys/time.h>
   38 #include <netinet/in.h>
   39 
   40 #include <stdlib.h>
   41 #include <stdio.h>
   42 #include <errno.h>
   43 #include <string.h>
   44 #include <signal.h>
   45 #include <err.h>
   46 
   47 #include <event.h>
   48 #include <dnet.h>
   49 
   50 #include "scanssh.h"
   51 #include "socks.h"
   52 
   53 #ifdef DEBUG
   54 extern int debug;
   55 #define DFPRINTF(x) if (debug) fprintf x
   56 #else
   57 #define DFPRINTF(x)
   58 #endif
   59 
   60 extern rand_t *ss_rand;
   61 
   62 void socks_init(struct bufferevent *bev, struct argument *arg);
   63 void socks_finalize(struct bufferevent *bev, struct argument *arg);
   64 
   65 void socks5_readcb(struct bufferevent *bev, void *parameter);
   66 void socks5_writecb(struct bufferevent *bev, void *parameter);
   67 void socks5_errorcb(struct bufferevent *bev, short what, void *parameter);
   68 
   69 void socks4_readcb(struct bufferevent *bev, void *parameter);
   70 void socks4_writecb(struct bufferevent *bev, void *parameter);
   71 void socks4_errorcb(struct bufferevent *bev, short what, void *parameter);
   72 
   73 char *words[] = {
   74     "eerily",
   75     "bloodthirster",
   76     "negligence",
   77     "uncooping",
   78     "outsubtle",
   79     "saturnize",
   80     "unconclusiveness",
   81     "optological",
   82     "malabathrum",
   83     "leiomyosarcoma",
   84     "gristmill",
   85     "offendible",
   86     "pretyphoid",
   87     "banjo",
   88     "cossaean",
   89     "panhuman",
   90     "relive",
   91     "unquakerlike",
   92     "stupefier",
   93     "unkilled"
   94 };
   95 
   96 struct addr *socks_dst_addr = NULL;
   97 
   98 void
   99 socks_resolveaddress(char *name, ip_addr_t *address)
  100 {
  101     struct addrinfo ai, *aitop;
  102 
  103     if (socks_dst_addr != NULL) {
  104         memcpy(address, &socks_dst_addr->addr_ip, sizeof(ip_addr_t));
  105         return;
  106     }
  107 
  108     memset(&ai, 0, sizeof (ai));
  109     ai.ai_family = AF_INET;
  110     ai.ai_socktype = 0;
  111     ai.ai_flags = 0;
  112 
  113     if (getaddrinfo(name, NULL, &ai, &aitop) != 0)
  114         err(1, "%s: getaddrinfo failed: %s", __func__, name);
  115 
  116     if ((socks_dst_addr = calloc(1, sizeof(struct addr))) == NULL)
  117         err(1, "%s: calloc", __func__);
  118 
  119     addr_ston(aitop->ai_addr, socks_dst_addr);
  120     freeaddrinfo(aitop);
  121 
  122     memcpy(address, &socks_dst_addr->addr_ip, sizeof(ip_addr_t));
  123 }
  124 
  125 char *
  126 socks_getword(void)
  127 {
  128     int off = rand_uint16(ss_rand) % (sizeof(words)/sizeof(char *));
  129 
  130     return words[off];
  131 }
  132 
  133 void
  134 socks_makeurl(struct socks_state *socks)
  135 {
  136     char *word = socks_getword();
  137 
  138     socks->port = 80;
  139     socks->word = word;
  140     snprintf(socks->domain, sizeof(socks->domain), "www.google.com");
  141 }
  142 
  143 int
  144 socks_getaddress(struct bufferevent *bev, uint8_t type)
  145 {
  146     uint8_t length;
  147     char *name;
  148 
  149     switch (type) {
  150     case SOCKS_ADDR_IPV4:
  151         if (EVBUFFER_LENGTH(bev->input) < 4)
  152             return (-1);
  153         evbuffer_drain(bev->input, 4);
  154         break;
  155 
  156     case SOCKS_ADDR_NAME:
  157         bufferevent_read(bev, &length, sizeof(length));
  158         if (EVBUFFER_LENGTH(bev->input) < length)
  159             return (-1);
  160         if ((name = malloc(length + 1)) == NULL)
  161             err(1, "%s: malloc", __func__);
  162         bufferevent_read(bev, name, length);
  163         name[length] = '\0';
  164         DFPRINTF((stderr, "Got: %s\n", name));
  165         free(name);
  166         break;
  167 
  168     default:
  169         return (-1);
  170     }
  171 
  172     /* Now get the port number */
  173     if (EVBUFFER_LENGTH(bev->input) < 2)
  174         return (-1);
  175 
  176     evbuffer_drain(bev->input, 2);
  177     return (0);
  178 }
  179 
  180 void
  181 socks_bufferanalyse(struct bufferevent *bev, struct argument *arg)
  182 {
  183     struct evbuffer *input = EVBUFFER_INPUT(bev);
  184     struct socks_state *socks = arg->a_state;
  185     size_t off;
  186     char response[32];
  187     char *p;
  188     
  189     if (!socks->gotheaders) {
  190         while ((p = evbuffer_find(input, "\n", 1)) != NULL) {
  191             off = (size_t)p - (size_t)EVBUFFER_DATA(input) + 1;
  192             if (off > 0 && *(p-1) == '\r')
  193                 *(p-1) = '\0';
  194             *p = '\0';
  195 
  196             if (strlen(EVBUFFER_DATA(input)) == 0) {
  197                 socks->gotheaders = 1;
  198                 evbuffer_drain(input, off);
  199                 break;
  200             } else {
  201                 DFPRINTF((stderr, "Header: %s\n",
  202                          EVBUFFER_DATA(input)));
  203             }
  204             evbuffer_drain(input, off);
  205         }
  206     }
  207 
  208     if (!socks->gotheaders)
  209         return;
  210 
  211     if (evbuffer_find(input, "\r\n", 2) == NULL)
  212         return;
  213 
  214     if (evbuffer_find(input, socks->word, strlen(socks->word)) != NULL) {
  215         snprintf(response, sizeof(response),
  216             "SOCKS v%d", socks->version);
  217         socks->success = 1;
  218                
  219     } else {
  220         snprintf(response, sizeof(response),
  221             "bad SOCKS v%d", socks->version);
  222     }
  223     postres(arg, response);
  224     scanhost_return(bev, arg, 1);
  225 }
  226 
  227 /* Scanner related functions */
  228 
  229 void 
  230 socks_init(struct bufferevent *bev, struct argument *arg)
  231 {
  232     arg->a_flags = 0;
  233     if ((arg->a_state = calloc(1, sizeof(struct socks_state))) == NULL)
  234         err(1, "%s: calloc", __func__);
  235 }
  236 
  237 void 
  238 socks_finalize(struct bufferevent *bev, struct argument *arg)
  239 {
  240     free(arg->a_state);
  241     arg->a_state = NULL;
  242     arg->a_flags = 0;
  243 }
  244 
  245 void
  246 socks5_readcb(struct bufferevent *bev, void *parameter)
  247 {
  248     struct argument *arg = parameter;
  249     struct socks_state *socks = arg->a_state;
  250     uint8_t version[2];
  251     struct socks5_cmd cmd;
  252     uint8_t reply[4];
  253     
  254     DFPRINTF((stderr, "%s: called\n", __func__));
  255 
  256     switch (arg->a_flags) {
  257     case SOCKS_WAITING_RESPONSE:
  258         if (EVBUFFER_LENGTH(bev->input) != 2)
  259             goto error;
  260 
  261         bufferevent_read(bev, version, sizeof(version));
  262         DFPRINTF((stderr, "version: %d, response: %d\n",
  263             version[0], version[1]));
  264 
  265         socks->version = version[0];
  266         socks->method = version[1];
  267         if (socks->version != 4 && socks->version != 5)
  268             goto error;
  269         if (socks->method != 0)
  270             goto error;
  271         
  272         socks_makeurl(socks);
  273 
  274         /* Now write our request */
  275         cmd.version = SOCKS_VERSION5;
  276         cmd.command = SOCKS_CMD_CONNECT;
  277         cmd.reserved = 0;
  278         cmd.addrtype = SOCKS_ADDR_IPV4;
  279         socks_resolveaddress(socks->domain, &cmd.address.s_addr);
  280         cmd.dstport = htons(socks->port);
  281         bufferevent_write(bev, &cmd, 4 + 4 + 2);
  282 
  283         bufferevent_disable(bev, EV_READ);
  284         arg->a_flags = SOCKS_SENDING_COMMAND;
  285         break;
  286 
  287     case SOCKS_WAITING_COMMANDRESPONSE:
  288         if (EVBUFFER_LENGTH(bev->input) < sizeof(reply))
  289             goto error;
  290         bufferevent_read(bev, reply, sizeof(reply));
  291         DFPRINTF((stderr, "Version: %d, Reply: %d\n",
  292             reply[0], reply[1]));
  293 
  294         if (socks->version != reply[0])
  295             goto error;
  296 
  297         switch (reply[1]) {
  298         case SOCKS5_RESP_SUCCESS:
  299             break;
  300         case SOCKS5_RESP_FAILURE:
  301             postres(arg, "<error: server failure>");
  302             goto done;
  303         case SOCKS5_RESP_FORBIDDEN:
  304             postres(arg, "<error: forbidden>");
  305             goto done;
  306         case SOCKS5_RESP_NETUNREACH:
  307         case SOCKS5_RESP_HOSTUNREACH:
  308             postres(arg, "<error: unreachable>");
  309             goto done;
  310         default:
  311             postres(arg, "<error: response>");
  312             goto done;
  313         }
  314 
  315         /* Success, now look at address type */
  316         if (socks_getaddress(bev, reply[3]) == -1)
  317             goto error;
  318 
  319         arg->a_flags = SOCKS_SENDING_WEBREQUEST;
  320         bufferevent_disable(bev, EV_READ);
  321 
  322         http_makerequest(bev, arg, socks->word, 0);
  323         break;
  324 
  325     case SOCKS_READING_RESPONSE:
  326         socks_bufferanalyse(bev, arg);
  327         break;
  328 
  329     default:
  330         break;
  331     }
  332 
  333     return;
  334 
  335  error:
  336     postres(arg, "<socks5 proxy read error>");
  337  done:
  338     scanhost_return(bev, arg, 0);
  339 }
  340 
  341 void
  342 socks5_writecb(struct bufferevent *bev, void *parameter)
  343 {
  344     struct argument *arg = parameter;
  345     uint8_t version[3] = { 0x05, 0x01, 0x00 };
  346 
  347     DFPRINTF((stderr, "%s: called\n", __func__));
  348 
  349     switch (arg->a_flags) {
  350     case 0:
  351         arg->a_flags = SOCKS_WAITING_RESPONSE;
  352         bufferevent_write(bev, version, sizeof(version));
  353         break;
  354     case SOCKS_SENDING_COMMAND:
  355         arg->a_flags = SOCKS_WAITING_COMMANDRESPONSE;
  356         bufferevent_enable(bev, EV_READ);
  357         break;
  358     case SOCKS_SENDING_WEBREQUEST:
  359         arg->a_flags = SOCKS_READING_RESPONSE;
  360         bufferevent_enable(bev, EV_READ);
  361         break;
  362     default:
  363         break;
  364     }
  365 }
  366 
  367 void
  368 socks5_errorcb(struct bufferevent *bev, short what, void *parameter)
  369 {
  370     struct argument *arg = parameter;
  371 
  372     DFPRINTF((stderr, "%s: called\n", __func__));
  373 
  374     postres(arg, "<socks5 proxy error>");
  375     scanhost_return(bev, arg, 0);
  376 }
  377 
  378 void
  379 socks4_readcb(struct bufferevent *bev, void *parameter)
  380 {
  381     struct argument *arg = parameter;
  382     struct socks_state *socks = arg->a_state;
  383     struct socks4_cmd reply;
  384     
  385     DFPRINTF((stderr, "%s: called\n", __func__));
  386 
  387     switch (arg->a_flags) {
  388     case SOCKS_WAITING_COMMANDRESPONSE:
  389         if (EVBUFFER_LENGTH(bev->input) < sizeof(reply))
  390             goto error;
  391         bufferevent_read(bev, &reply, sizeof(reply));
  392         DFPRINTF((stderr, "Version: %d, Reply: %d\n",
  393             reply.version, reply.command));
  394 
  395         if (0 != reply.version)
  396             goto error;
  397 
  398         switch (reply.command) {
  399         case SOCKS4_RESP_SUCCESS:
  400             break;
  401         case SOCKS4_RESP_FAILURE:
  402             postres(arg, "<socks4 proxy error: server failure>");
  403             goto done;
  404         case SOCKS4_RESP_NOIDENT:
  405             postres(arg, "<socks4 proxy error: no ident>");
  406             goto done;
  407         case SOCKS4_RESP_BADIDENT:
  408             postres(arg, "<socks4 proxy error: bad ident>");
  409             goto done;
  410         default:
  411             postres(arg, "<socks4 proxy error: response>");
  412             goto done;
  413         }
  414 
  415         arg->a_flags = SOCKS_SENDING_WEBREQUEST;
  416         bufferevent_disable(bev, EV_READ);
  417 
  418         http_makerequest(bev, arg, socks->word, 0);
  419         break;
  420 
  421     case SOCKS_READING_RESPONSE:
  422         socks_bufferanalyse(bev, arg);
  423         break;
  424 
  425     default:
  426         break;
  427     }
  428 
  429     return;
  430 
  431  error:
  432     postres(arg, "<socks4 proxy error>");
  433  done:
  434     scanhost_return(bev, arg, 0);
  435 }
  436 
  437 void
  438 socks4_writecb(struct bufferevent *bev, void *parameter)
  439 {
  440     struct argument *arg = parameter;
  441     struct socks_state *socks = arg->a_state;
  442     struct socks4_cmd cmd;
  443 
  444     socks->version = 4;
  445     socks->method = 0;
  446     
  447     DFPRINTF((stderr, "%s: called\n", __func__));
  448 
  449     switch (arg->a_flags) {
  450     case 0:
  451         /* Request the connection to be made */
  452         socks_makeurl(socks);
  453 
  454         cmd.version = SOCKS_VERSION4;
  455         cmd.command = SOCKS_CMD_CONNECT;
  456         cmd.dstport = htons(socks->port);
  457         socks_resolveaddress(socks->domain, &cmd.address.s_addr);
  458 
  459         bufferevent_write(bev, &cmd, sizeof(cmd));
  460         bufferevent_write(bev, socks->word, strlen(socks->word) + 1);
  461 
  462         arg->a_flags = SOCKS_WAITING_COMMANDRESPONSE;
  463         bufferevent_enable(bev, EV_READ);
  464         break;
  465     case SOCKS_SENDING_WEBREQUEST:
  466         arg->a_flags = SOCKS_READING_RESPONSE;
  467         bufferevent_enable(bev, EV_READ);
  468         break;
  469     default:
  470         break;
  471     }
  472 }
  473 
  474 void
  475 socks4_errorcb(struct bufferevent *bev, short what, void *parameter)
  476 {
  477     struct argument *arg = parameter;
  478 
  479     DFPRINTF((stderr, "%s: called\n", __func__));
  480 
  481     postres(arg, "<socks4 proxy error>");
  482     scanhost_return(bev, arg, 0);
  483 }