[PATCH 02/24] http: Split HTTP redirect and cookie clear logic into helper functions

Kevin Cernekee cernekee at gmail.com
Sat Nov 3 13:22:44 EDT 2012


This makes openconnect_obtain_cookie() shorter, and easier to follow.

Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
 http.c |  189 +++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 103 insertions(+), 86 deletions(-)

diff --git a/http.c b/http.c
index 38fc9a5..1df6488 100644
--- a/http.c
+++ b/http.c
@@ -591,6 +591,104 @@ int internal_parse_url(char *url, char **res_proto, char **res_host,
 	return 0;
 }
 
+static void clear_cookies(struct openconnect_info *vpninfo)
+{
+	struct vpn_option *opt, *next;
+
+	for (opt = vpninfo->cookies; opt; opt = next) {
+		next = opt->next;
+
+		free(opt->option);
+		free(opt->value);
+		free(opt);
+	}
+	vpninfo->cookies = NULL;
+}
+
+/* Return value:
+ *  < 0, on error
+ *  = 0, on success (go ahead and retry with the latest vpninfo->{hostname,urlpath,port,...})
+ */
+static int handle_redirect(struct openconnect_info *vpninfo)
+{
+	if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
+		/* New host. Tear down the existing connection and make a new one */
+		char *host;
+		int port;
+		int ret;
+
+		free(vpninfo->urlpath);
+		vpninfo->urlpath = NULL;
+
+		ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
+		if (ret) {
+			vpn_progress(vpninfo, PRG_ERR,
+				     _("Failed to parse redirected URL '%s': %s\n"),
+				     vpninfo->redirect_url, strerror(-ret));
+			free(vpninfo->redirect_url);
+			vpninfo->redirect_url = NULL;
+			return ret;
+		}
+
+		if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
+			free(vpninfo->hostname);
+			vpninfo->hostname = host;
+			vpninfo->port = port;
+
+			/* Kill the existing connection, and a new one will happen */
+			free(vpninfo->peer_addr);
+			vpninfo->peer_addr = NULL;
+			openconnect_close_https(vpninfo, 0);
+			clear_cookies(vpninfo);
+		} else
+			free(host);
+
+		free(vpninfo->redirect_url);
+		vpninfo->redirect_url = NULL;
+
+		return 0;
+	} else if (strstr(vpninfo->redirect_url, "://")) {
+		vpn_progress(vpninfo, PRG_ERR,
+			     _("Cannot follow redirection to non-https URL '%s'\n"),
+			     vpninfo->redirect_url);
+		free(vpninfo->redirect_url);
+		vpninfo->redirect_url = NULL;
+		return -EINVAL;
+	} else if (vpninfo->redirect_url[0] == '/') {
+		/* Absolute redirect within same host */
+		free(vpninfo->urlpath);
+		vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
+		free(vpninfo->redirect_url);
+		vpninfo->redirect_url = NULL;
+		return 0;
+	} else {
+		char *lastslash = NULL;
+		if (vpninfo->urlpath)
+			lastslash = strrchr(vpninfo->urlpath, '/');
+		if (!lastslash) {
+			free(vpninfo->urlpath);
+			vpninfo->urlpath = vpninfo->redirect_url;
+			vpninfo->redirect_url = NULL;
+		} else {
+			char *oldurl = vpninfo->urlpath;
+			*lastslash = 0;
+			vpninfo->urlpath = NULL;
+			if (asprintf(&vpninfo->urlpath, "%s/%s",
+				     oldurl, vpninfo->redirect_url) == -1) {
+				int err = -errno;
+				vpn_progress(vpninfo, PRG_ERR,
+					     _("Allocating new path for relative redirect failed: %s\n"),
+					     strerror(-err));
+				return err;
+			}
+			free(oldurl);
+			free(vpninfo->redirect_url);
+			vpninfo->redirect_url = NULL;
+		}
+		return 0;
+	}
+}
+
 /* Return value:
  *  < 0, on error
  *  > 0, no cookie (user cancel)
@@ -598,7 +696,7 @@ int internal_parse_url(char *url, char **res_proto, char **res_host,
  */
 int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
 {
-	struct vpn_option *opt, *next;
+	struct vpn_option *opt;
 	char buf[MAX_BUF_LEN];
 	char *form_buf = NULL;
 	int result, buflen;
@@ -676,92 +774,11 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
 
 	if (result != 200 && vpninfo->redirect_url) {
 	redirect:
-		if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
-			/* New host. Tear down the existing connection and make a new one */
-			char *host;
-			int port;
-			int ret;
-
-			free(vpninfo->urlpath);
-			vpninfo->urlpath = NULL;
-
-			ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
-			if (ret) {
-				vpn_progress(vpninfo, PRG_ERR,
-					     _("Failed to parse redirected URL '%s': %s\n"),
-					     vpninfo->redirect_url, strerror(-ret));
-				free(vpninfo->redirect_url);
-				vpninfo->redirect_url = NULL;
-				free(form_buf);
-				return ret;
-			}
-
-			if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
-				free(vpninfo->hostname);
-				vpninfo->hostname = host;
-				vpninfo->port = port;
-
-				/* Kill the existing connection, and a new one will happen */
-				free(vpninfo->peer_addr);
-				vpninfo->peer_addr = NULL;
-				openconnect_close_https(vpninfo, 0);
-
-				for (opt = vpninfo->cookies; opt; opt = next) {
-					next = opt->next;
-
-					free(opt->option);
-					free(opt->value);
-					free(opt);
-				}
-				vpninfo->cookies = NULL;
-			} else
-				free(host);
-
-			free(vpninfo->redirect_url);
-			vpninfo->redirect_url = NULL;
-
+		result = handle_redirect(vpninfo);
+		if (result == 0)
 			goto retry;
-		} else if (strstr(vpninfo->redirect_url, "://")) {
-			vpn_progress(vpninfo, PRG_ERR,
-				     _("Cannot follow redirection to non-https URL '%s'\n"),
-				     vpninfo->redirect_url);
-			free(vpninfo->redirect_url);
-			vpninfo->redirect_url = NULL;
-			free(form_buf);
-			return -EINVAL;
-		} else if (vpninfo->redirect_url[0] == '/') {
-			/* Absolute redirect within same host */
-			free(vpninfo->urlpath);
-			vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
-			free(vpninfo->redirect_url);
-			vpninfo->redirect_url = NULL;
-			goto retry;
-		} else {
-			char *lastslash = NULL;
-			if (vpninfo->urlpath)
-				lastslash = strrchr(vpninfo->urlpath, '/');
-			if (!lastslash) {
-				free(vpninfo->urlpath);
-				vpninfo->urlpath = vpninfo->redirect_url;
-				vpninfo->redirect_url = NULL;
-			} else {
-				char *oldurl = vpninfo->urlpath;
-				*lastslash = 0;
-				vpninfo->urlpath = NULL;
-				if (asprintf(&vpninfo->urlpath, "%s/%s",
-					     oldurl, vpninfo->redirect_url) == -1) {
-					int err = -errno;
-					vpn_progress(vpninfo, PRG_ERR,
-						     _("Allocating new path for relative redirect failed: %s\n"),
-						     strerror(-err));
-					return err;
-				}
-				free(oldurl);
-				free(vpninfo->redirect_url);
-				vpninfo->redirect_url = NULL;
-			}
-			goto retry;
-		}
+		free(form_buf);
+		return result;
 	}
 	if (!form_buf || result != 200) {
 		vpn_progress(vpninfo, PRG_ERR,
-- 
1.7.10.4




More information about the openconnect-devel mailing list