Commit 3e7ae7b8 authored by David Woodhouse's avatar David Woodhouse

Use oc_text_buf for auth postings

The less we manually screw around with fixed-sized string buffers, the
better.
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 35a59dd9
......@@ -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;
}
......@@ -790,7 +759,7 @@ retry:
* = 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;
......@@ -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";
......@@ -932,7 +901,7 @@ bad:
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;
......@@ -948,12 +917,7 @@ 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);
......@@ -961,7 +925,7 @@ static int xmlpost_complete(xmlDocPtr doc, char *body, int bodylen)
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);
......@@ -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);
......@@ -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;
}
......
......@@ -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;
......@@ -890,7 +911,7 @@ 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;
......@@ -898,6 +919,9 @@ static int do_https_request(struct openconnect_info *vpninfo, const char *method
int rq_retry;
int rlen, pad;
if (buf_error(request_body))
return buf_error(request_body);
redirected:
vpninfo->redirect_type = REDIR_TYPE_NONE;
......@@ -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. */
......@@ -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",
......@@ -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;
......@@ -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;
......@@ -1086,7 +1110,7 @@ newgroup:
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);
......@@ -1150,7 +1174,7 @@ newgroup:
_("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;
......@@ -1230,8 +1254,8 @@ newgroup:
/* 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;
......@@ -1297,6 +1321,8 @@ newgroup:
fetch_config(vpninfo);
out:
buf_free(request_body);
free (orig_host);
free (orig_path);
......
......@@ -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 */
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment