[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