http: Fix memory leak in do_https_request()

Returning after a redirect can leak the oc_text_buf struct:

    ==5844== 4,120 (24 direct, 4,096 indirect) bytes in 1 blocks are definitely lost in loss record 47 of 50
    ==5844==    at 0x4C29DB4: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==5844==    by 0x4E3CFDF: do_https_request (http.c:929)
    ==5844==    by 0x4E3D485: openconnect_obtain_cookie (http.c:1117)
    ==5844==    by 0x403135: main (main.c:1038)

So make sure we call buf_free() first.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
http: Call buf_truncate() before appending XML POST data

If the buffer isn't cleared, openconnect may send garbled requests.  For
instance, this is what happened when it tried to send a
<client-cert-fail/> response:

    > <?xml version="1.0" encoding="UTF-8"?>
    > <config-auth client="vpn" type="init"><version who="vpn">v6.00-27-gd6ce12e-dirty</version><device-id>win</device-id><group-access>https://asa</group-access></config-auth>
    > <?xml version="1.0" encoding="UTF-8"?>
    > <config-auth client="vpn" type="init"><version who="vpn">v6.00-27-gd6ce12e-dirty</version><device-id>win</device-id><group-access>https://asa</group-access><client-cert-fail/></config-auth>

    < <?xml version="1.0" encoding="UTF-8"?>
    < <config-auth client="vpn" type="complete">
    < <version who="sg">8.4(4)5</version>
    < <error id="98" param1="" param2="">VPN Server could not parse request.</error>
    < </config-auth>
    XML response has no "auth" node

...and then it fell back to non-xmlpost mode, a regression from v6.00.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
http: Don't leak orig_host or orig_path

Commit 35a59dd9f (Clean up return paths in openconnect_obtain_cookie())
moved the free()ing of these buffers to the end of the function.  But
they should also be freed on each "newgroup" loop iteration, or else this
happens:

    ==9457== 2 bytes in 2 blocks are definitely lost in loss record 1 of 50
    ==9457==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==9457==    by 0x565FD81: strdup (strdup.c:43)
    ==9457==    by 0x4E3D582: openconnect_obtain_cookie (http.c:1089)
    ==9457==    by 0x403135: main (main.c:1038)
    ==9457==
    ==9457== 12 bytes in 3 blocks are definitely lost in loss record 10 of 50
    ==9457==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==9457==    by 0x565FD81: strdup (strdup.c:43)
    ==9457==    by 0x4E3D56E: openconnect_obtain_cookie (http.c:1088)
    ==9457==    by 0x403135: main (main.c:1038)

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
http: Fix CSD https requests

If request_body is NULL, buf_error(request_body) will return -ENOMEM to
indicate an allocation failure.  This is a good thing if we just called
buf_alloc(), but it is a bad thing if we aren't actually passing in a
request_body pointer.

The CSD GET requests pass in a NULL request_body and request_body_type:

    result = do_https_request(vpninfo, "GET", NULL, NULL, &form_buf, 0);

so this change is needed to restore proper CSD operation.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Add inet_pton() compatibility for Windows

Windows XP doesn't have it, so just wrap WSAStringToAddressA().

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Make buf_append_urlencoded() more conservative about non-ASCII chars.

Windows isalnum() will return TRUE for odd things depending on the code page.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Move buf_append_utf16le() to http.c and make it non-static

We'll want to use this for coping with Windows "Unicode" functions.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Use "Unicode" versions of SSPI functions

Start making it "Unicode"-clean. Admittedly this is largely theoretical
in this patch because it's vanishingly unlikely that the hostname will
be non-ASCII, but it's a good place to start.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Add buf_append_from_utf16le() which appends UTF-8 to the buffer

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Handle non-ASCII tun device names under Windows

Most of the calls here can remain resolutely ASCII-only, since the registry
key names aren't going to contain arbitrary characters. The cosmetic device
name, on the other hand, does need to be obtained as "Unicode" and converted
to UTF-8.

We can't just use WideCharToMultiByte here because it doesn't exist on
older versions of Windows (yay!).

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Print name of Windows tun device not devname

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Use read_stdin() instead of fgets() in certificate validation

Now we can make read_stdin() do UTF-8 conversion for legacy environments...

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Export asprintf() and vasprintf() compatibility functions

We'll want this for legacy charset handling.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Refactor read_stdin() a little to prepare for charset conversion

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Attempt to convert output to locale charset from UTF-8

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Convert to UTF-8 when reading from stdin

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Separate read_stdin() implementations for Windows vs. POSIX

They're about to get even *more* different...

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Handle UTF-8 input on Windows

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Handle UTF-8 output on Windows too

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Fixes for buf_append_utf16le()

Make it set buf_error() when it returns -EINVAL, to ensure callers will
catch the problem. Previously, ntlm_set_string_binary() and  sspi_setup()
would not have noticed.

Also, NUL-terminate the buffer. Not accounting for it, but just putting
two zero bytes after the string so that it can be used as a
NUL-terminated (wchar_t *). Not entirely sure how sspi_setup() was
working before this, except perhaps pure luck.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>