]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
First attempt at automatic proxy detection,
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Thu, 8 Dec 2005 23:10:22 +0000 (23:10 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Thu, 8 Dec 2005 23:10:22 +0000 (23:10 +0000)
Windows-only at this point.  Proxy settings
are taken from IE.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@846 e7ae566f-a301-0410-adde-c780ea21d3b5

Makefile.am
ieproxy.c [new file with mode: 0755]
ieproxy.h [new file with mode: 0755]
makefile.w32
options.c
proxy.c
proxy.h
syshead.h

index 424b167d05ed9a65d447845c291eee93d9a149aa..ebfa22d1fc0e9cad60888c6bce55871d55b0bceb 100644 (file)
@@ -127,7 +127,8 @@ EXTRA_DIST = \
        plugin \
         management \
         pkcs11-headers \
-       cryptoki-win32.h
+       cryptoki-win32.h \
+       ieproxy.c ieproxy.h
 
 dist-hook:
        cd $(distdir) && for i in $(EXTRA_DIST) ; do find $$i -name .svn -type d -prune -exec rm -rf '{}' ';' ; rm -f `find $$i -type f | grep -E '(^|\/)\.?\#|\~$$|\.s?o$$'` ; done
diff --git a/ieproxy.c b/ieproxy.c
new file mode 100755 (executable)
index 0000000..42b067b
--- /dev/null
+++ b/ieproxy.c
@@ -0,0 +1,137 @@
+/*
+ *  Copyright (C) 2004 Ewan Bhamrah Harley <code@ewan.info>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <WinInet.h>
+#include <malloc.h>
+
+LPCTSTR getIeHttpProxyError=NULL;
+
+/* getIeHttpProxy fetches the current IE proxy settings for http */
+
+LPCTSTR getIeHttpProxy()
+{
+  DWORD psize=0;
+  INTERNET_PROXY_INFO *pinfo;
+  LPTSTR proxyString;
+  LPTSTR p;
+  LPTSTR q;
+  unsigned int len;
+       
+  /* first see how big a buffer we need for the IPO structure */
+  InternetQueryOption(NULL, INTERNET_OPTION_PROXY, NULL, &psize);
+  if(!psize)
+  {
+    getIeHttpProxyError="InternetQueryOption failed to return buffer size";
+    return(NULL);
+  }
+
+  /* allocate memory for IPO */
+  pinfo =  malloc (psize*sizeof(TCHAR));
+  if (pinfo == NULL)
+  {
+    getIeHttpProxyError="malloc failed (1)";
+    return(NULL);
+  }
+
+  /* now run the real query */
+  if(!InternetQueryOption(NULL, INTERNET_OPTION_PROXY, (LPVOID) pinfo, &psize))
+  {
+    getIeHttpProxyError="InternetQueryOption() failed to find proxy info";
+    free(pinfo);
+    return(NULL);
+  }
+
+
+  /* see what sort of result we got */
+       
+  if(pinfo->dwAccessType == INTERNET_OPEN_TYPE_DIRECT)
+  {
+    /* No proxy configured */
+    free(pinfo);
+    return("");
+  }
+  else if(pinfo->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
+  {
+    /* we have a proxy - now parse result string */
+    /* if result string does NOT contain an '=' sign then */
+    /* there is a single proxy for all protocols          */
+    for (p=(LPTSTR)pinfo->lpszProxy; *p && *p != '='; p++);
+    if(!*p)
+    {
+      /* single proxy */
+      /* allocate a new string to return */
+      len = 1+strlen(pinfo->lpszProxy);
+      proxyString = malloc (len*sizeof(TCHAR));
+      if (proxyString == NULL)
+      {
+        getIeHttpProxyError="malloc failed (2)";
+        free(pinfo);
+        return(NULL);
+      }
+      strncpy(proxyString, pinfo->lpszProxy,len);
+      proxyString[len]=0;
+      free(pinfo);
+      return(proxyString);
+    }
+    else
+    {
+      /* multiple space seperated proxies defined in the form */
+      /* protocol=proxyhost[:port]                            */
+      /* we want the one marked "http=", if any.              */
+      p=(LPTSTR)pinfo->lpszProxy;
+      while(*p && strncmp(p, "http=", 5))
+      {
+        for(; *p && *p != ' '; p++);
+        if(*p) p++;
+      }
+      if(*p)
+      {
+        /* found the proxy */
+        p+=5;
+        for(q=p; *q && *q != ' '; q++);
+        /* allocate a buffer for the proxy information */
+        len=1+(q-p);
+        proxyString=malloc(len*sizeof(TCHAR));
+        if(proxyString==NULL)
+        {
+          getIeHttpProxyError="malloc failed (3)";
+          free(pinfo);
+          return(NULL);
+        }
+        strncpy(proxyString, p, len);
+        proxyString[len]=0;
+        free(pinfo);
+        return(proxyString);
+      }
+      else
+      {
+        /* No http proxy in list */
+        free(pinfo);
+        return("");
+      }
+    }
+  }
+  else
+  {
+    /* InternetQueryOption returned a proxy type we don't know about*/
+    getIeHttpProxyError="Unknown Proxy Type";
+    free(pinfo);
+    return(NULL);
+  }
+}
diff --git a/ieproxy.h b/ieproxy.h
new file mode 100755 (executable)
index 0000000..0786c05
--- /dev/null
+++ b/ieproxy.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (C) 2004 Ewan Bhamrah Harley <code@ewan.info>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __GETIEHTTPPROXY__
+#define __GETIEHTTPPROXY__
+extern LPTSTR getIeHttpProxyError;
+LPCTSTR getIeHttpProxy();
+#endif
index 4184504b380011e0f24ebf7e09cf052650e646c4..c612512a610815233ede50459d1c9bb15319bd01 100755 (executable)
@@ -49,7 +49,7 @@ INCLUDE_DIRS = -I${OPENSSL}/include -I${LZO}/include
 
 INCLUDE_DIRS_DMALLOC = ${INCLUDE_DIRS} -I${DMALLOC}
 
-LIBS = -llzo2 -lcrypt32 -lws2_32 -lgdi32 -liphlpapi -lwinmm
+LIBS = -llzo2 -lcrypt32 -lWinInet -lws2_32 -lgdi32 -liphlpapi -lwinmm
 
 LIBS_DMALLOC = ${LIBS} -ldmalloc
 
@@ -78,6 +78,7 @@ HEADERS = \
        fragment.h \
         gremlin.h \
        helper.h \
+       ieproxy.h \
        init.h \
        integer.h \
        interval.h \
@@ -136,6 +137,7 @@ OBJS =  base64.o \
         fragment.o \
        gremlin.o \
        helper.o \
+       ieproxy.o \
        init.o \
        interval.o \
         list.o \
index 9e38da6aefd26546d86028e333452199e20c481a..ebe61d02ce4c980019f15c0f5142169bd1c306c9 100644 (file)
--- a/options.c
+++ b/options.c
@@ -969,7 +969,7 @@ show_remote_list (const struct remote_list *l)
 }
 #endif
 
-#if defined(ENABLE_HTTP_PROXY) && defined (ENABLE_DEBUG)
+#if defined(ENABLE_HTTP_PROXY) && defined(ENABLE_DEBUG)
 static void
 show_http_proxy_options (const struct http_proxy_options *o)
 {
@@ -3676,23 +3676,58 @@ add_option (struct options *options,
       options->proto = proto;
     }
 #ifdef ENABLE_HTTP_PROXY
-  else if (streq (p[0], "http-proxy") && p[1] && p[2])
+  else if (streq (p[0], "http-proxy") && p[1])
     {
-      int port;
       struct http_proxy_options *ho;
 
       VERIFY_PERMISSION (OPT_P_GENERAL);
-      port = atoi (p[2]);
-      if (!legal_ipv4_port (port))
+
+      if (streq (p[1], "auto"))
        {
-         msg (msglevel, "Bad http-proxy port number: %s", p[2]);
-         goto err;
+         struct http_proxy_options hpo;
+         bool status;
+         char *error = NULL;
+
+         p[4] = p[3];
+         p[3] = p[2];
+         p[1] = p[2] = NULL;
+         CLEAR (hpo);
+         
+         status = get_http_proxy_settings (&hpo, &error, &options->gc);
+         if (status)
+           {
+             ho = init_http_options_if_undefined (options);
+             ho->server = hpo.server;
+             ho->port = hpo.port;
+           }
+         else
+           {
+             if (error)
+               msg (M_WARN, "http-proxy auto error: %s", error);
+             goto err;
+           }
        }
+      else
+       {
+         int port;
+         if (!p[2])
+           {
+             msg (msglevel, "http-proxy port number not defined");
+             goto err;
+           }
+         port = atoi (p[2]);
+         if (!legal_ipv4_port (port))
+           {
+             msg (msglevel, "Bad http-proxy port number: %s", p[2]);
+             goto err;
+           }
 
-      ho = init_http_options_if_undefined (options);
+         ho = init_http_options_if_undefined (options);
+
+         ho->server = p[1];
+         ho->port = port;
+       }
 
-      ho->server = p[1];
-      ho->port = port;
       if (p[3])
        {
          ho->auth_method_string = "basic";
@@ -3743,6 +3778,29 @@ add_option (struct options *options,
          msg (msglevel, "Bad http-proxy-option or missing parameter: '%s'", p[1]);
        }
     }
+  else if (streq (p[0], "show-http-proxy-settings"))
+    {
+      struct http_proxy_options po;
+      bool status;
+      char *error = NULL;
+
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      CLEAR (po);
+      status = get_http_proxy_settings (&po, &error, &options->gc);
+      if (status)
+       {
+         msg (M_INFO|M_NOPREFIX, "Server: %s", po.server);
+         msg (M_INFO|M_NOPREFIX, "Port: %d", po.port);
+       }
+      else
+       {
+         if (error)
+           msg (msglevel, "Proxy error: %s", error);
+         else
+           msg (msglevel, "Proxy settings are undefined");
+       }
+      openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
+    }  
 #endif
 #ifdef ENABLE_SOCKS
   else if (streq (p[0], "socks-proxy") && p[1])
diff --git a/proxy.c b/proxy.c
index 091173357c1354d1e1e69ccd7145f7de2d35795f..0cfd51ca99f8b3e1e1f319409099dc2c0236fdb3 100644 (file)
--- a/proxy.c
+++ b/proxy.c
 #include "proxy.h"
 #include "ntlm.h"
 
+#ifdef WIN32
+#include "ieproxy.h"
+#endif
+
 #include "memdbg.h"
 
+#ifdef WIN32
+
+bool
+get_http_proxy_settings (struct http_proxy_options *p, char **err, struct gc_arena *gc)
+{
+  bool ret = false;
+  const char *result;
+
+  p->server = NULL;
+  p->port = 0;
+  getIeHttpProxyError = NULL;
+  if (err)
+    *err = NULL;
+
+  result = getIeHttpProxy ();
+  if (result)
+    {
+      char addr_str[128];
+      char port_str[16];
+      struct buffer in;
+      buf_set_read (&in, (const uint8_t *)result, strlen (result));
+      if (buf_parse (&in, ':', addr_str, sizeof (addr_str))
+         && buf_parse (&in, ':', port_str, sizeof (port_str)))
+       {
+         p->server = string_alloc (addr_str, gc);
+         p->port = atoi (port_str);
+         ret = true;
+       }
+      free ((void *)result);
+    }
+  else if (getIeHttpProxyError)
+    {
+      if (err)
+       *err = string_alloc (getIeHttpProxyError, gc);
+    }
+  return ret;
+}
+
+#else
+
+bool
+get_http_proxy_settings (struct http_proxy_options *p, char **err, struct gc_arena *gc)
+{
+  if (err)
+    *err = string_alloc ("HTTP proxy detection not supported on this OS", gc);
+  return false;
+}
+
+#endif
+
 /* cached proxy username/password */
 static struct user_pass static_proxy_user_pass;
 
diff --git a/proxy.h b/proxy.h
index 9a3182684cb8a16dae5cdf8c86c3d7f3adc64b7e..5e7178cb740ba4c6dc9cc9d4a166e170936dc483 100644 (file)
--- a/proxy.h
+++ b/proxy.h
@@ -67,5 +67,7 @@ void establish_http_proxy_passthru (struct http_proxy_info *p,
 uint8_t *make_base64_string2 (const uint8_t *str, int str_len, struct gc_arena *gc);
 uint8_t *make_base64_string (const uint8_t *str, struct gc_arena *gc);
 
+bool get_http_proxy_settings (struct http_proxy_options *p, char **err, struct gc_arena *gc);
+
 #endif
 #endif
index d25b82c809ba015ffe82c53730f01f2f93c86d67..6426241e6676d9ea2dd64e44a1b3cbf3d74eb1f4 100644 (file)
--- a/syshead.h
+++ b/syshead.h
@@ -429,7 +429,7 @@ socket_defined (const socket_descriptor_t sd)
 /*
  * Should we include NTLM proxy functionality
  */
-#if defined(USE_CRYPTO) && defined (ENABLE_HTTP_PROXY)
+#if defined(USE_CRYPTO) && defined(ENABLE_HTTP_PROXY)
 #define NTLM 1
 #else
 #define NTLM 0