Feature Request: HTTP proxy authentication
David Woodhouse
dwmw2 at infradead.org
Thu Jun 19 02:04:39 PDT 2014
On Thu, 2014-06-19 at 09:12 +0530, Marc-André Laverdière wrote:
>
> I discovered yesterday how rusty I got at C... oh well.
> Here are some of the changes I did, straight from the "I don't know
> what I'm doing dept."
Looks good; thanks. I'd actually already implemented the
username/password parsing for openconnect_set_http_proxy() but it was a
bit of a hack, just post-processing the "hostname" returned by the
standard URL parsing function and looking for the @ sign.
You've done a much better job, making internal_parse_url() do it sanely
and propagating that API change — and as an added bonus you've also made
it use the xmlParseUri() function instead of its own implementation. I
hadn't realised that was available.
There are *lots* of wheels reinvented in the OpenConnect code, which
always makes me sad, but often it's not avoidable. This one *was*
avoidable, and well done for spotting that.
(If you can find a suitable base64 encode/decode function that I can use
too, that'd make me even happier. OpenSSL gives me one, but not GnuTLS
or libxml2 AFAICT.)
It took me a while to work out what you'd changed, though. Instead of
complete files (which were so large that the mailing list didn't even
let them through), it's best to send a patch. That way, I don't have to
spend time trying to work out which historical version of the code you
*started* with, to tell your changes from all the other changes which
have been made since then.
Here's your work as a patch, which makes it easy to read and review
right here in the mail. When submitting a patch please also include a
Signed-Off-By: tag as described at
http://www.infradead.org/openconnect/contribute.html
Thanks again.
diff --git a/http.c b/http.c
index 323ff43..8b9d87f 100644
--- a/http.c
+++ b/http.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <libxml/uri.h>
#ifndef _WIN32
#include <pwd.h>
#endif
@@ -662,69 +663,65 @@ out:
#endif /* !_WIN32 */
}
-int internal_parse_url(char *url, char **res_proto, char **res_host,
- int *res_port, char **res_path, int default_port)
+int internal_parse_url(char *url, char **res_proto, char **res_host, int *res_port,
+ char **res_auth_uname, char **res_auth_pwd, char **res_path, int default_port)
{
- char *proto = url;
- char *host, *path, *port_str;
- int port;
-
- host = strstr(url, "://");
- if (host) {
- *host = 0;
- host += 3;
-
- if (!strcasecmp(proto, "https"))
- port = 443;
- else if (!strcasecmp(proto, "http"))
- port = 80;
- else if (!strcasecmp(proto, "socks") ||
- !strcasecmp(proto, "socks4") ||
- !strcasecmp(proto, "socks5"))
- port = 1080;
- else
- return -EPROTONOSUPPORT;
- } else {
- if (default_port) {
- proto = NULL;
- port = default_port;
- host = url;
- } else
- return -EINVAL;
- }
-
- path = strchr(host, '/');
- if (path)
- *(path++) = 0;
- port_str = strrchr(host, ':');
- if (port_str) {
- char *end;
- int new_port = strtol(port_str + 1, &end, 10);
-
- if (!*end) {
- *port_str = 0;
- port = new_port;
- }
- }
-
- if (res_proto)
- *res_proto = proto ? strdup(proto) : NULL;
- if (res_host)
- *res_host = strdup(host);
- if (res_port)
- *res_port = port;
- if (res_path)
- *res_path = (path && *path) ? strdup(path) : NULL;
-
- /* Undo the damage we did to the original string */
- if (port_str)
- *(port_str) = ':';
- if (path)
- *(path - 1) = '/';
- if (proto)
- *(host - 3) = ':';
- return 0;
+ int port = default_port;
+
+ xmlURIPtr uriInfo = xmlParseURI(url);
+ if (uriInfo == NULL || uriInfo->scheme == NULL || uriInfo->server == NULL)
+ return -EPROTONOSUPPORT;
+
+ *res_proto = strdup(uriInfo->scheme);
+
+ if (res_proto != NULL)
+ {
+ if (!strcasecmp(*res_proto, "https"))
+ port = 443;
+ else if (!strcasecmp(*res_proto, "http"))
+ port = 80;
+ else if (!strcasecmp(*res_proto, "socks") ||
+ !strcasecmp(*res_proto, "socks4") ||
+ !strcasecmp(*res_proto, "socks5"))
+ port = 1080;
+ else
+ return -EPROTONOSUPPORT;
+ }
+
+ if (res_port != NULL)
+ {
+ if (uriInfo->port >= 0)
+ port = uriInfo->port;
+ *res_port = port;
+ }
+
+ if (res_host != NULL)
+ *res_host = strdup(uriInfo->server);
+
+ //user information may contain the password too
+ if (res_auth_uname != NULL && res_auth_pwd != NULL && uriInfo->user != NULL)
+ {
+ char * copy = strdup(uriInfo->user);
+ char * separator = strchr(copy, ':');
+ if (separator == NULL)
+ *res_auth_uname = copy;
+ else
+ {
+ *res_auth_uname = copy;
+ *res_auth_pwd = separator ++;
+ *separator = '\0';
+ }
+ }
+
+ if (res_path != NULL && uriInfo->path != NULL)
+ {
+ *res_path = strdup(uriInfo->path);
+ }
+
+ xmlFreeURI(uriInfo);
+
+ return 0; //Success
}
static void clear_cookies(struct openconnect_info *vpninfo)
@@ -758,7 +755,7 @@ static int handle_redirect(struct openconnect_info *vpninfo)
free(vpninfo->urlpath);
vpninfo->urlpath = NULL;
- ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
+ ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, NULL, NULL, &vpninfo->urlpath, 0);
if (ret) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to parse redirected URL '%s': %s\n"),
@@ -1533,6 +1530,19 @@ static int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock)
return -EINVAL;
}
+ //Check for authentication demand from the proxy
+ //TODO her, here here!
+ if (result == 407)
+ {
+ //Step 1: extract the token(s) provided and the method(s) supported
+ //
+ //Step 2: encode the usernmae+password combination in base64
+ //
+ //Step 3: Add the tokens and auth info
+ //
+ //Step 4: Send to proxy and get response
+ }
+
if (result != 200) {
vpn_progress(vpninfo, PRG_ERR,
_("Proxy CONNECT request failed: %s\n"), buf);
@@ -1581,7 +1591,7 @@ int openconnect_set_http_proxy(struct openconnect_info *vpninfo, char *proxy)
vpninfo->proxy = NULL;
ret = internal_parse_url(url, &vpninfo->proxy_type, &vpninfo->proxy,
- &vpninfo->proxy_port, NULL, 80);
+ &vpninfo->proxy_port, &vpninfo->proxy_auth_uname, &vpninfo->proxy_auth_pwd, NULL, 80);
if (ret)
goto out;
diff --git a/library.c b/library.c
index ae91e8d..0a8ee3c 100644
--- a/library.c
+++ b/library.c
@@ -343,7 +343,7 @@ int openconnect_parse_url(struct openconnect_info *vpninfo, char *url)
vpninfo->urlpath = NULL;
ret = internal_parse_url(url, &scheme, &vpninfo->hostname,
- &vpninfo->port, &vpninfo->urlpath, 443);
+ &vpninfo->port, NULL, NULL, &vpninfo->urlpath, 443);
if (ret) {
vpn_progress(vpninfo, PRG_ERR,
--
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5745 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20140619/a8283de0/attachment-0001.bin>
More information about the openconnect-devel
mailing list