Skip to content

Commit

Permalink
Consolidate check_http_status from gpst.c and ppp.c
Browse files Browse the repository at this point in the history
This function checks a buffer for an unexpected HTTP status line ("HTTP/xxx
nnn ...") and returns the numeric status value (nnn) if found.

Also fixes a crash when GP config request ("/ssl-vpn/getconfig.esp") returns
no body at all.

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
  • Loading branch information
dlenski committed May 3, 2021
1 parent 19d9d1a commit d257a7e
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
15 changes: 10 additions & 5 deletions gpst.c
Expand Up @@ -650,7 +650,7 @@ static int gpst_get_config(struct openconnect_info *vpninfo)
/* XX: if our "cookie" is bogus (doesn't include at least 'user', 'authcookie',
* and 'portal' fields) the server will respond like this.
*/
if (result == -EINVAL && !strcmp(xml_buf, "errors getting SSL/VPN config"))
if (result == -EINVAL && xml_buf && !strcmp(xml_buf, "errors getting SSL/VPN config"))
result = -EPERM;
goto out;
}
Expand Down Expand Up @@ -741,10 +741,15 @@ static int gpst_connect(struct openconnect_info *vpninfo)
ret = vpninfo->ssl_gets(vpninfo, buf+sizeof(start_tunnel), sizeof(buf)-sizeof(start_tunnel));
ret = (ret>0 ? ret : 0) + sizeof(start_tunnel);
}
vpn_progress(vpninfo, PRG_ERR,
_("Got inappropriate HTTP GET-tunnel response: %.*s\n"), ret, buf);
/* XX: this is what GP servers return when they don't like the cookie */
ret = !strncmp(buf, "HTTP/1.1 502 ", 13) ? -EPERM : -EINVAL;
int status = check_http_status(buf, ret);
/* XX: GP servers return 502 when they don't like the cookie */
if (status == 502)
ret = -EPERM;
else {
vpn_progress(vpninfo, PRG_ERR, _("Got unexpected HTTP response: %.*s\n"),
ret, buf);
ret = -EINVAL;
}
}

if (ret < 0)
Expand Down
1 change: 1 addition & 0 deletions openconnect-internal.h
Expand Up @@ -1062,6 +1062,7 @@ int ppp_tcp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readabl
int ppp_udp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable);
int openconnect_ppp_new(struct openconnect_info *vpninfo, int encap, int want_ipv4, int want_ipv6);
int ppp_reset(struct openconnect_info *vpninfo);
int check_http_status(const char *buf, int len);

/* auth-globalprotect.c */
int gpst_obtain_cookie(struct openconnect_info *vpninfo);
Expand Down
25 changes: 15 additions & 10 deletions ppp.c
Expand Up @@ -1047,6 +1047,17 @@ static inline void add_ppp_header(struct pkt *p, struct oc_ppp *ppp, int proto)
p->ppp.hlen = p->data - ph;
}

int check_http_status(const char *buf, int len)
{
if (len >= 5 && !memcmp(buf, "HTTP/", 5)) {
const char *eol = memchr(buf, '\r', len) ?: memchr(buf, '\n', len);
const char *sp1 = memchr(buf, ' ', len);
const char *sp2 = sp1 ? memchr(sp1+1, ' ', len - (sp1-buf) + 1) : NULL;
return (sp1 && sp2 && (!eol || sp2<eol)) ? atoi(sp1+1) : 500;
}
return -EINVAL;
}

static int ppp_mainloop(struct openconnect_info *vpninfo, int dtls,
struct keepalive_info *kai, int *timeout, int readable)
{
Expand Down Expand Up @@ -1101,17 +1112,11 @@ static int ppp_mainloop(struct openconnect_info *vpninfo, int dtls,
* of the first packet
*/
if (ppp->check_http_response) {
int status = check_http_status((const char *)eh, len);
ppp->check_http_response = 0;
if (!memcmp(eh, "HTTP/", 5)) {
const char *sol = (const char *)eh;
const char *eol = memchr(sol, '\r', len) ?: memchr(sol, '\n', len);
const char *sp1 = memchr(sol, ' ', len);
const char *sp2 = memchr(sp1+1, ' ', len - (sp1-sol) + 1);
int status = sp1 && sp2 ? atoi(sp1+1) : -1;
if (eol)
len = eol - sol;
vpn_progress(vpninfo, PRG_ERR,
_("Got unexpected HTTP response: %.*s\n"), len, sol);
if (status >= 0) {
vpn_progress(vpninfo, PRG_ERR,_("Got unexpected HTTP response: %.*s\n"),
len, (const char *)eh);
vpninfo->quit_reason = "Received HTTP response (not a PPP packet)";
return (status >= 400 && status <= 499) ? -EPERM : -EINVAL;
}
Expand Down

0 comments on commit d257a7e

Please sign in to comment.