LCOV - code coverage report
Current view: top level - tests - socks5.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 160 0.0 %
Date: 2016-11-29 14:54:18 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /* socks5.c - Check the SOCKS5 client feature
       2             :  * Copyright (C) 2015 g10 Code GmbH
       3             :  *
       4             :  * This file is part of Assuan.
       5             :  *
       6             :  * Assuan is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU Lesser General Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Assuan is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #ifdef HAVE_CONFIG_H
      21             : #include <config.h>
      22             : #endif
      23             : 
      24             : #include <stdio.h>
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <assert.h>
      28             : #ifdef HAVE_W32_SYSTEM
      29             : # ifdef HAVE_WINSOCK2_H
      30             : #  include <winsock2.h>
      31             : # endif
      32             : # include <windows.h>
      33             : #else /*!HAVE_W32_SYSTEM*/
      34             : # include <sys/types.h>
      35             : # include <sys/socket.h>
      36             : # include <netdb.h>
      37             : #endif /*!HAVE_W32_SYSTEM*/
      38             : 
      39             : #include "../src/assuan.h"
      40             : #include "common.h"
      41             : 
      42             : 
      43             : /*
      44             : 
      45             :      M A I N
      46             : 
      47             : */
      48             : int
      49           0 : main (int argc, char **argv)
      50             : {
      51           0 :   int last_argc = -1;
      52             :   gpg_error_t err;
      53           0 :   int only_v6 = 0;
      54           0 :   int only_v4 = 0;
      55           0 :   int use_tor = 0;
      56           0 :   int opt_have_proxy = 0;
      57           0 :   int disable_socks = 0;
      58           0 :   int opt_byname = 0;
      59           0 :   const char *user = NULL;
      60           0 :   const char *pass = NULL;
      61           0 :   assuan_fd_t sock = ASSUAN_INVALID_FD;
      62             :   estream_t infp, outfp;
      63             :   int c;
      64             :   int lf_seen;
      65             : 
      66           0 :   gpgrt_init ();
      67           0 :   if (argc)
      68             :     {
      69           0 :       log_set_prefix (*argv);
      70           0 :       argc--; argv++;
      71             :     }
      72           0 :   while (argc && last_argc != argc )
      73             :     {
      74           0 :       last_argc = argc;
      75           0 :       if (!strcmp (*argv, "--"))
      76             :         {
      77           0 :           argc--; argv++;
      78           0 :           break;
      79             :         }
      80           0 :       else if (!strcmp (*argv, "--help"))
      81             :         {
      82           0 :           puts (
      83             :                 "usage: ./socks5 [options] HOST PORT\n"
      84             :                 "\n"
      85             :                 "Options:\n"
      86             :                 "  --verbose        Show what is going on\n"
      87             :                 "  --use-tor        Use port 9050 instead of 1080\n"
      88             :                 "  --inet6-only     Use only IPv6\n"
      89             :                 "  --inet4-only     Use only IPv4\n"
      90             :                 "  --disable-socks  Connect w/o SOCKS\n"
      91             :                 "  --have-proxy     Check whether the proxy is available\n"
      92             :                 "  --byname         Use assuan_sock_connect_byname\n"
      93             :                 "  --user STRING    Use STRING as user for authentication\n"
      94             :                 "  --pass STRING    Use STRING as password for authentication\n"
      95             :                 );
      96           0 :           exit (0);
      97             :         }
      98           0 :       if (!strcmp (*argv, "--verbose"))
      99             :         {
     100           0 :           verbose = 1;
     101           0 :           argc--; argv++;
     102             :         }
     103           0 :       else if (!strcmp (*argv, "--debug"))
     104             :         {
     105           0 :           verbose = debug = 1;
     106           0 :           argc--; argv++;
     107             :         }
     108           0 :       else if (!strcmp (*argv, "-6") || !strcmp (*argv, "--inet6-only"))
     109             :         {
     110           0 :           only_v6 = 1;
     111           0 :           argc--; argv++;
     112             :         }
     113           0 :       else if (!strcmp (*argv, "-4") || !strcmp (*argv, "--inet4-only"))
     114             :         {
     115           0 :           only_v4 = 1;
     116           0 :           argc--; argv++;
     117             :         }
     118           0 :       else if (!strcmp (*argv, "--use-tor"))
     119             :         {
     120           0 :           use_tor = 1;
     121           0 :           argc--; argv++;
     122             :         }
     123           0 :       else if (!strcmp (*argv, "--disable-socks"))
     124             :         {
     125           0 :           disable_socks = 1;
     126           0 :           argc--; argv++;
     127             :         }
     128           0 :       else if (!strcmp (*argv, "--byname"))
     129             :         {
     130           0 :           opt_byname = 1;
     131           0 :           argc--; argv++;
     132             :         }
     133           0 :       else if (!strcmp (*argv, "--have-proxy"))
     134             :         {
     135           0 :           opt_have_proxy = 1;
     136           0 :           argc--; argv++;
     137             :         }
     138           0 :       else if (!strcmp (*argv, "--user"))
     139             :         {
     140           0 :           argc--; argv++;
     141           0 :           if (argc)
     142             :             {
     143           0 :               user = *argv;
     144           0 :               argc--; argv++;
     145             :             }
     146             :         }
     147           0 :       else if (!strcmp (*argv, "--pass"))
     148             :         {
     149           0 :           argc--; argv++;
     150           0 :           if (argc)
     151             :             {
     152           0 :               pass = *argv;
     153           0 :               argc--; argv++;
     154             :             }
     155             :         }
     156           0 :       else if (!strncmp (*argv, "--", 2))
     157             :         {
     158           0 :           log_error ("unknown option '%s'\n", *argv);
     159           0 :           exit (1);
     160             :         }
     161             :     }
     162             : 
     163           0 :   if (argc != 2 && !opt_have_proxy)
     164             :     {
     165           0 :       fputs ("usage: socks5 HOST PORT\n", stderr);
     166           0 :       exit (1);
     167             :     }
     168             : 
     169           0 :   assuan_set_assuan_log_prefix (log_prefix);
     170             : 
     171           0 :   if (!assuan_check_version (ASSUAN_VERSION))
     172           0 :     log_error ("assuan_check_version returned an error\n");
     173             : 
     174           0 :   assuan_sock_init ();
     175             : 
     176           0 :   if (!disable_socks
     177           0 :       && assuan_sock_set_flag (ASSUAN_INVALID_FD,
     178             :                                use_tor? "tor-mode":"socks", 1))
     179             :     {
     180           0 :       err = gpg_error_from_syserror ();
     181           0 :       log_fatal ("setting %s mode failed: %s\n",
     182             :                  use_tor? "TOR": "SOCKS", gpg_strerror (err));
     183             :     }
     184             : 
     185           0 :   if (opt_have_proxy)
     186             :     {
     187             :       char *cred;
     188             : 
     189           0 :       if (user || pass)
     190           0 :         cred = xstrconcat (user?user:"", ":", pass, NULL);
     191             :       else
     192           0 :         cred = NULL;
     193             : 
     194           0 :       sock = assuan_sock_connect_byname
     195             :         (NULL, 0, 0, cred, use_tor? ASSUAN_SOCK_TOR : ASSUAN_SOCK_SOCKS);
     196           0 :       if (sock == ASSUAN_INVALID_FD)
     197             :         {
     198           0 :           err = gpg_error_from_syserror ();
     199           0 :           log_error ("SOCKS proxy is not available (%s)\n", gpg_strerror (err));
     200           0 :           exit (1);
     201             :         }
     202           0 :       xfree (cred);
     203           0 :       assuan_sock_close (sock);
     204           0 :       if (verbose)
     205           0 :         log_info ("SOCKS proxy available\n");
     206           0 :       exit (0);
     207             :     }
     208           0 :   else if (opt_byname)
     209             :     {
     210             :       unsigned short port;
     211             :       char *cred;
     212             : 
     213           0 :       if (user || pass)
     214           0 :         cred = xstrconcat (user?user:"", ":", pass, NULL);
     215             :       else
     216           0 :         cred = NULL;
     217             : 
     218           0 :       port = strtoul (argv[1], NULL, 10);
     219             :       if (port < 0 || port > 65535)
     220             :         log_fatal ("port number out of range\n");
     221             : 
     222           0 :       sock = assuan_sock_connect_byname (argv[0], port, 0, cred,
     223             :                                          ASSUAN_SOCK_TOR);
     224           0 :       if (sock == ASSUAN_INVALID_FD)
     225             :         {
     226           0 :           err = gpg_error_from_syserror ();
     227           0 :           log_error ("assuan_sock_connect_byname (%s) failed: %s\n",
     228             :                      argv[0], gpg_strerror (err));
     229           0 :           exit (1);
     230             :         }
     231           0 :       xfree (cred);
     232             :     }
     233             :   else
     234             :     {
     235             : #ifdef HAVE_GETADDRINFO
     236             :       struct addrinfo hints, *res, *ai;
     237             :       int ret;
     238           0 :       int anyok = 0;
     239             : 
     240           0 :       memset (&hints, 0, sizeof (hints));
     241           0 :       hints.ai_socktype = SOCK_STREAM;
     242           0 :       ret = getaddrinfo (argv[0], argv[1], &hints, &res);
     243           0 :       if (ret)
     244             :         {
     245           0 :           log_error ("error resolving '%s': %s\n", argv[0], gai_strerror (ret));
     246           0 :           exit (1);
     247             :         }
     248             : 
     249           0 :       for (ai = res; ai; ai = ai->ai_next)
     250             :         {
     251           0 :           if (ai->ai_family == AF_INET && only_v6)
     252           0 :             continue;
     253           0 :           if (ai->ai_family == AF_INET6 && only_v4)
     254           0 :             continue;
     255             : 
     256           0 :           if (sock != ASSUAN_INVALID_FD)
     257           0 :             assuan_sock_close (sock);
     258           0 :           sock = assuan_sock_new (ai->ai_family, ai->ai_socktype,
     259             :                                   ai->ai_protocol);
     260           0 :           if (sock == ASSUAN_INVALID_FD)
     261             :             {
     262           0 :               err = gpg_error_from_syserror ();
     263           0 :               log_error ("error creating socket: %s\n", gpg_strerror (err));
     264           0 :               freeaddrinfo (res);
     265           0 :               exit (1);
     266             :             }
     267             : 
     268           0 :           if (assuan_sock_connect (sock,  ai->ai_addr, ai->ai_addrlen))
     269             :             {
     270           0 :               err = gpg_error_from_syserror ();
     271           0 :               log_error ("assuan_sock_connect (%s) failed: %s\n",
     272           0 :                          ai->ai_family == AF_INET6? "v6" :
     273           0 :                          ai->ai_family == AF_INET ? "v4" : "?",
     274             :                          gpg_strerror (err));
     275             :             }
     276             :           else
     277             :             {
     278           0 :               log_info ("assuan_sock_connect succeeded (%s)\n",
     279           0 :                         ai->ai_family == AF_INET6? "v6" :
     280           0 :                         ai->ai_family == AF_INET ? "v4" : "?");
     281           0 :               anyok = 1;
     282           0 :               break;
     283             :             }
     284             :         }
     285           0 :       freeaddrinfo (res);
     286           0 :       if (!anyok)
     287           0 :         exit (1);
     288             : #else /*!HAVE_GETADDRINFO*/
     289             :       (void)only_v4;
     290             :       (void)only_v6;
     291             :       fputs ("socks5: getaddrinfo not supported\n", stderr);
     292             :       exit (77); /* Skip test.  */
     293             : #endif /*!HAVE_GETADDRINFO*/
     294             :     }
     295             : 
     296           0 :   infp = es_fdopen_nc (sock, "rb");
     297           0 :   if (!infp)
     298             :     {
     299           0 :       err = gpg_error_from_syserror ();
     300           0 :       assuan_sock_close (sock);
     301           0 :       log_fatal ("opening inbound stream failed: %s\n", gpg_strerror (err));
     302             :     }
     303           0 :   outfp = es_fdopen (sock, "wb");
     304           0 :   if (!outfp)
     305             :     {
     306           0 :       err = gpg_error_from_syserror ();
     307           0 :       es_fclose (infp);
     308           0 :       assuan_sock_close (sock);
     309           0 :       log_fatal ("opening outbound stream failed: %s\n", gpg_strerror (err));
     310             :     }
     311           0 :   es_fputs ("GET / HTTP/1.0\r\n\r\n", outfp);
     312           0 :   if (es_fflush (outfp))
     313             :     {
     314           0 :       err = gpg_error_from_syserror ();
     315           0 :       log_error ("es_fflush failed: %s\n", gpg_strerror (err));
     316             :     }
     317           0 :   lf_seen = 0;
     318           0 :   while ((c = es_fgetc (infp)) != EOF)
     319             :     {
     320           0 :       if (c == '\r')
     321           0 :         continue;
     322           0 :       putchar (c);
     323           0 :       if (c == '\n')
     324             :         {
     325           0 :           if (lf_seen)
     326           0 :             break;
     327           0 :           lf_seen = 1;
     328             :         }
     329             :       else
     330           0 :         lf_seen = 0;
     331             :     }
     332           0 :   if (es_ferror (infp))
     333             :     {
     334           0 :       err = gpg_error_from_syserror ();
     335           0 :       log_error ("es_fgetc failed: %s\n", gpg_strerror (err));
     336             :     }
     337           0 :   es_fclose (infp);
     338           0 :   es_fclose (outfp);
     339             : 
     340           0 :   return errorcount ? 1 : 0;
     341             : }

Generated by: LCOV version 1.11