Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use oc_text_buf for auth postings
The less we manually screw around with fixed-sized string buffers, the
better.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Jul 24, 2014
1 parent 35a59dd commit 3e7ae7b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 70 deletions.
80 changes: 22 additions & 58 deletions auth.c
Expand Up @@ -41,65 +41,34 @@
#include "openconnect-internal.h"

static int xmlpost_append_form_opts(struct openconnect_info *vpninfo,
struct oc_auth_form *form, char *body, int bodylen);
struct oc_auth_form *form, struct oc_text_buf *body);
static int can_gen_tokencode(struct openconnect_info *vpninfo,
struct oc_auth_form *form, struct oc_form_opt *opt);
static int do_gen_tokencode(struct openconnect_info *vpninfo, struct oc_auth_form *form);

static int append_opt(char *body, int bodylen, char *opt, char *name)
static int append_opt(struct oc_text_buf *body, char *opt, char *name)
{
int len = strlen(body);
if (buf_error(body))
return buf_error(body);

if (len) {
if (len >= bodylen - 1)
return -ENOSPC;
body[len++] = '&';
}

while (*opt) {
if (isalnum((int)(unsigned char)*opt)) {
if (len >= bodylen - 1)
return -ENOSPC;
body[len++] = *opt;
} else {
if (len >= bodylen - 3)
return -ENOSPC;
sprintf(body+len, "%%%02x", (unsigned char)*opt);
len += 3;
}
opt++;
}
if (body->pos)
buf_append(body, "&");

if (len >= bodylen - 1)
return -ENOSPC;
body[len++] = '=';

while (name && *name) {
if (isalnum((int)(unsigned char)*name)) {
if (len >= bodylen - 1)
return -ENOSPC;
body[len++] = *name;
} else {
if (len >= bodylen - 3)
return -ENOSPC;
sprintf(body+len, "%%%02x", (unsigned char)*name);
len += 3;
}
name++;
}
body[len] = 0;
buf_append_urlencoded(body, opt);
buf_append(body, "=");
buf_append_urlencoded(body, name);

return 0;
}

static int append_form_opts(struct openconnect_info *vpninfo,
struct oc_auth_form *form, char *body, int bodylen)
struct oc_auth_form *form, struct oc_text_buf *body)
{
struct oc_form_opt *opt;
int ret;

for (opt = form->opts; opt; opt = opt->next) {
ret = append_opt(body, bodylen, opt->name, opt->value);
ret = append_opt(body, opt->name, opt->value);
if (ret)
return ret;
}
Expand Down Expand Up @@ -790,7 +759,7 @@ int process_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *for
* = OC_FORM_RESULT_LOGGEDIN, when form indicates that login was already successful
*/
int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *form,
char *request_body, int req_len, const char **method,
struct oc_text_buf *request_body, const char **method,
const char **request_body_type)
{
int ret;
Expand Down Expand Up @@ -835,8 +804,8 @@ int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *form
return ret;

ret = vpninfo->xmlpost ?
xmlpost_append_form_opts(vpninfo, form, request_body, req_len) :
append_form_opts(vpninfo, form, request_body, req_len);
xmlpost_append_form_opts(vpninfo, form, request_body) :
append_form_opts(vpninfo, form, request_body);
if (!ret) {
*method = "POST";
*request_body_type = "application/x-www-form-urlencoded";
Expand Down Expand Up @@ -932,7 +901,7 @@ static xmlDocPtr xmlpost_new_query(struct openconnect_info *vpninfo, const char
return NULL;
}

static int xmlpost_complete(xmlDocPtr doc, char *body, int bodylen)
static int xmlpost_complete(xmlDocPtr doc, struct oc_text_buf *body)
{
xmlChar *mem = NULL;
int len, ret = 0;
Expand All @@ -948,20 +917,15 @@ static int xmlpost_complete(xmlDocPtr doc, char *body, int bodylen)
return -ENOMEM;
}

if (len > bodylen)
ret = -E2BIG;
else {
memcpy(body, mem, len);
body[len] = 0;
}
buf_append_bytes(body, mem, len);

xmlFreeDoc(doc);
xmlFree(mem);

return ret;
}

int xmlpost_initial_req(struct openconnect_info *vpninfo, char *request_body, int req_len, int cert_fail)
int xmlpost_initial_req(struct openconnect_info *vpninfo, struct oc_text_buf *request_body, int cert_fail)
{
xmlNodePtr root, node;
xmlDocPtr doc = xmlpost_new_query(vpninfo, "init", &root);
Expand Down Expand Up @@ -992,15 +956,15 @@ int xmlpost_initial_req(struct openconnect_info *vpninfo, char *request_body, in
if (!node)
goto bad;
}
return xmlpost_complete(doc, request_body, req_len);
return xmlpost_complete(doc, request_body);

bad:
xmlpost_complete(doc, NULL, 0);
xmlpost_complete(doc, NULL);
return -ENOMEM;
}

static int xmlpost_append_form_opts(struct openconnect_info *vpninfo,
struct oc_auth_form *form, char *body, int bodylen)
struct oc_auth_form *form, struct oc_text_buf *body)
{
xmlNodePtr root, node;
xmlDocPtr doc = xmlpost_new_query(vpninfo, "auth-reply", &root);
Expand Down Expand Up @@ -1053,10 +1017,10 @@ static int xmlpost_append_form_opts(struct openconnect_info *vpninfo,
!xmlNewTextChild(root, NULL, XCAST("host-scan-token"), XCAST(vpninfo->csd_token)))
goto bad;

return xmlpost_complete(doc, body, bodylen);
return xmlpost_complete(doc, body);

bad:
xmlpost_complete(doc, NULL, 0);
xmlpost_complete(doc, NULL);
return -ENOMEM;
}

Expand Down
44 changes: 35 additions & 9 deletions http.c
Expand Up @@ -46,6 +46,27 @@ struct oc_text_buf *buf_alloc(void)
return calloc(1, sizeof(struct oc_text_buf));
}

void buf_append_urlencoded(struct oc_text_buf *buf, char *str)
{
while (str && *str) {
if (isalnum((int)(unsigned char)*str))
buf_append_bytes(buf, str, 1);
else
buf_append(buf, "%%%02x", (unsigned char)*str);
str++;
}
}

void buf_truncate(struct oc_text_buf *buf)
{
if (!buf)
return;

buf->pos = 0;
if (buf->data)
buf->data[0] = 0;
}

int buf_ensure_space(struct oc_text_buf *buf, int len)
{
int new_buf_len;
Expand Down Expand Up @@ -890,14 +911,17 @@ static void dump_buf(struct openconnect_info *vpninfo, char prefix, char *buf)
* >=0, on success, indicating the length of the data in *form_buf
*/
static int do_https_request(struct openconnect_info *vpninfo, const char *method,
const char *request_body_type, const char *request_body,
const char *request_body_type, struct oc_text_buf *request_body,
char **form_buf, int fetch_redirect)
{
struct oc_text_buf *buf;
int result, buflen;
int rq_retry;
int rlen, pad;

if (buf_error(request_body))
return buf_error(request_body);

redirected:
vpninfo->redirect_type = REDIR_TYPE_NONE;

Expand All @@ -920,7 +944,7 @@ static int do_https_request(struct openconnect_info *vpninfo, const char *method
add_common_headers(vpninfo, buf);

if (request_body_type) {
rlen = strlen(request_body);
rlen = request_body->pos;

/* force body length to be a multiple of 64, to avoid leaking
* password length. */
Expand All @@ -933,7 +957,7 @@ static int do_https_request(struct openconnect_info *vpninfo, const char *method
buf_append(buf, "\r\n");

if (request_body_type)
buf_append(buf, "%s", request_body);
buf_append_bytes(buf, request_body->data, request_body->pos);

if (vpninfo->port == 443)
vpn_progress(vpninfo, PRG_INFO, "%s https://%s/%s\n",
Expand Down Expand Up @@ -1042,7 +1066,7 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
char *form_buf = NULL;
struct oc_auth_form *form = NULL;
int result, buflen, tries;
char request_body[2048];
struct oc_text_buf *request_body = buf_alloc();
const char *request_body_type = "application/x-www-form-urlencoded";
const char *method = "POST";
char *orig_host = NULL, *orig_path = NULL, *form_path = NULL;
Expand All @@ -1069,7 +1093,7 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
* c) Three redirects without seeing a plausible login form
*/
newgroup:
result = xmlpost_initial_req(vpninfo, request_body, sizeof(request_body), 0);
result = xmlpost_initial_req(vpninfo, request_body, 0);
if (result < 0)
goto out;

Expand All @@ -1086,7 +1110,7 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
tries = 0;
vpninfo->xmlpost = 0;
request_body_type = NULL;
request_body[0] = 0;
buf_truncate(request_body);
method = "GET";
if (orig_host) {
openconnect_set_hostname(vpninfo, orig_host);
Expand Down Expand Up @@ -1150,7 +1174,7 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
_("Server requested SSL client certificate; none was configured\n"));
cert_failed = 1;
}
result = xmlpost_initial_req(vpninfo, request_body, sizeof(request_body), cert_failed);
result = xmlpost_initial_req(vpninfo, request_body, cert_failed);
if (result < 0)
goto fail;
continue;
Expand Down Expand Up @@ -1230,8 +1254,8 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)

/* Step 5: Ask the user to fill in the auth form; repeat as necessary */
while (1) {
request_body[0] = 0;
result = handle_auth_form(vpninfo, form, request_body, sizeof(request_body),
buf_truncate(request_body);
result = handle_auth_form(vpninfo, form, request_body,
&method, &request_body_type);
if (result < 0 || result == OC_FORM_RESULT_CANCELLED)
goto out;
Expand Down Expand Up @@ -1297,6 +1321,8 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
fetch_config(vpninfo);

out:
buf_free(request_body);

free (orig_host);
free (orig_path);

Expand Down
10 changes: 7 additions & 3 deletions openconnect-internal.h
Expand Up @@ -593,11 +593,13 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response,
struct oc_auth_form **form, int *cert_rq);
int process_auth_form(struct openconnect_info *vpninfo,
struct oc_auth_form *form);
int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *form,
char *request_body, int req_len, const char **method,
int handle_auth_form(struct openconnect_info *vpninfo,
struct oc_auth_form *form,
struct oc_text_buf *request_body, const char **method,
const char **request_body_type);
void free_auth_form(struct oc_auth_form *form);
int xmlpost_initial_req(struct openconnect_info *vpninfo, char *request_body, int req_len, int cert_fail);
int xmlpost_initial_req(struct openconnect_info *vpninfo,
struct oc_text_buf *request_body, int cert_fail);
int prepare_stoken(struct openconnect_info *vpninfo);

/* http.c */
Expand All @@ -608,6 +610,8 @@ void __attribute__ ((format (printf, 2, 3)))
void buf_append_bytes(struct oc_text_buf *buf, const void *bytes, int len);
void buf_append_base64(struct oc_text_buf *buf, const void *bytes, int len);
void *openconnect_base64_decode(int *len, const char *in);
void buf_truncate(struct oc_text_buf *buf);
void buf_append_urlencoded(struct oc_text_buf *buf, char *str);
int buf_error(struct oc_text_buf *buf);
int buf_free(struct oc_text_buf *buf);
char *openconnect_create_useragent(const char *base);
Expand Down

0 comments on commit 3e7ae7b

Please sign in to comment.