]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Loop when sending HTTP requests larger than the 16KiB SSL record max
authorDaniel Lenski <dlenski@gmail.com>
Wed, 29 Nov 2017 08:49:16 +0000 (00:49 -0800)
committerDavid Woodhouse <dwmw2@infradead.org>
Wed, 29 Nov 2017 09:27:04 +0000 (09:27 +0000)
A single SSL record can't contain >16KiB, so the HTTPS request buffer
may not get fully written if it's larger than this.

I discovered this frustrating bug while working on GlobalProtect HIP
support, which requires sending giant blobs of XML to the gateway.

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
http.c
openconnect-internal.h

diff --git a/http.c b/http.c
index 59f93e50f77247a799d518be53d5042a84a50be9..e53f3fce8aebc721bb82e049047330a30096bc67 100644 (file)
--- a/http.c
+++ b/http.c
@@ -818,7 +818,7 @@ int do_https_request(struct openconnect_info *vpninfo, const char *method,
        int result;
        int rq_retry;
        int rlen, pad;
-       int auth = 0;
+       int i, auth = 0;
        int max_redirects = 10;
 
        if (request_body_type && buf_error(request_body))
@@ -913,17 +913,22 @@ int do_https_request(struct openconnect_info *vpninfo, const char *method,
        if (vpninfo->dump_http_traffic)
                dump_buf(vpninfo, '>', buf->data);
 
-       result = vpninfo->ssl_write(vpninfo, buf->data, buf->pos);
-       if (rq_retry && result < 0) {
-               openconnect_close_https(vpninfo, 0);
-               goto retry;
+       for (i = 0; i < buf->pos; i += 16384) {
+               result = vpninfo->ssl_write(vpninfo, buf->data + i, MIN(buf->pos - i, 16384) );
+               if (result < 0) {
+                       if (rq_retry) {
+                               /* Retry if we failed to send the request on
+                                  an already-open connection */
+                               openconnect_close_https(vpninfo, 0);
+                               goto retry;
+                       }
+                       /* We'll already have complained about whatever offended us */
+                       goto out;
+               }
        }
-       if (result < 0)
-               goto out;
 
        result = process_http_response(vpninfo, 0, http_auth_hdrs, buf);
        if (result < 0) {
-               /* We'll already have complained about whatever offended us */
                goto out;
        }
        if (vpninfo->dump_http_traffic && buf->pos)
index b70085d2189bed16f1fb645681aafa8945cb73bb..5b9a8d6c555a71cedd45423e9e904dc243d1f6b4 100644 (file)
 #ifndef MAX
 #define MAX(x,y) ((x)>(y))?(x):(y)
 #endif
+#ifndef MIN
+#define MIN(x,y) ((x)<(y))?(x):(y)
+#endif
 /****************************************************************************/
 
 struct pkt {