Skip to content

Latest commit

 

History

History
1434 lines (1259 loc) · 36.8 KB

http.c

File metadata and controls

1434 lines (1259 loc) · 36.8 KB
 
Oct 1, 2008
Oct 1, 2008
1
/*
Nov 20, 2008
Nov 20, 2008
2
* OpenConnect (SSL + DTLS) VPN client
Oct 1, 2008
Oct 1, 2008
3
*
Jan 26, 2015
Jan 26, 2015
4
* Copyright © 2008-2015 Intel Corporation.
Apr 9, 2009
Apr 9, 2009
5
* Copyright © 2008 Nick Andrew <nick@nick-andrew.net>
Oct 1, 2008
Oct 1, 2008
6
*
Nov 20, 2008
Nov 20, 2008
7
8
9
* Author: David Woodhouse <dwmw2@infradead.org>
*
* This program is free software; you can redistribute it and/or
Oct 4, 2008
Oct 4, 2008
10
* modify it under the terms of the GNU Lesser General Public License
Nov 20, 2008
Nov 20, 2008
11
* version 2.1, as published by the Free Software Foundation.
Oct 1, 2008
Oct 1, 2008
12
*
Nov 20, 2008
Nov 20, 2008
13
* This program is distributed in the hope that it will be useful, but
Oct 4, 2008
Oct 4, 2008
14
15
16
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
Oct 1, 2008
Oct 1, 2008
17
18
*/
Jul 1, 2014
Jul 1, 2014
19
20
#include <config.h>
Jun 30, 2021
Jun 30, 2021
21
22
23
24
#include "openconnect-internal.h"
#include <libxml/uri.h>
Oct 1, 2008
Oct 1, 2008
25
26
#include <unistd.h>
#include <fcntl.h>
Jun 30, 2021
Jun 30, 2021
27
Oct 1, 2008
Oct 1, 2008
28
#include <time.h>
Jun 1, 2009
Jun 1, 2009
29
#include <string.h>
Oct 1, 2008
Oct 1, 2008
30
#include <ctype.h>
May 29, 2012
May 29, 2012
31
32
33
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
Oct 28, 2012
Oct 28, 2012
34
#include <stdarg.h>
Oct 1, 2008
Oct 1, 2008
35
Jun 18, 2014
Jun 18, 2014
36
37
static int proxy_write(struct openconnect_info *vpninfo, char *buf, size_t len);
static int proxy_read(struct openconnect_info *vpninfo, char *buf, size_t len);
Feb 22, 2010
Feb 22, 2010
38
Oct 1, 2008
Oct 1, 2008
39
/*
Apr 9, 2009
Apr 9, 2009
40
* We didn't really want to have to do this for ourselves -- one might have
Oct 1, 2008
Oct 1, 2008
41
42
43
44
45
46
* thought that it would be available in a library somewhere. But neither
* cURL nor Neon have reliable cross-platform ways of either using a cert
* from the TPM, or just reading from / writing to a transport which is
* provided by their caller.
*/
Jan 26, 2015
Jan 26, 2015
47
48
int http_add_cookie(struct openconnect_info *vpninfo, const char *option,
const char *value, int replace)
Nov 6, 2009
Nov 6, 2009
49
{
Jan 15, 2014
Jan 15, 2014
50
struct oc_vpn_option *new, **this;
Nov 6, 2009
Nov 6, 2009
51
52
53
54
if (*value) {
new = malloc(sizeof(*new));
if (!new) {
Sep 22, 2011
Sep 22, 2011
55
56
vpn_progress(vpninfo, PRG_ERR,
_("No memory for allocating cookies\n"));
Nov 6, 2009
Nov 6, 2009
57
58
59
60
61
return -ENOMEM;
}
new->next = NULL;
new->option = strdup(option);
new->value = strdup(value);
Nov 6, 2009
Nov 6, 2009
62
63
64
65
66
67
if (!new->option || !new->value) {
free(new->option);
free(new->value);
free(new);
return -ENOMEM;
}
Nov 6, 2009
Nov 6, 2009
68
69
70
} else {
/* Kill cookie; don't replace it */
new = NULL;
Feb 28, 2015
Feb 28, 2015
71
72
73
/* This would be meaningless */
if (!replace)
return -EINVAL;
Nov 6, 2009
Nov 6, 2009
74
75
76
}
for (this = &vpninfo->cookies; *this; this = &(*this)->next) {
if (!strcmp(option, (*this)->option)) {
Jan 26, 2015
Jan 26, 2015
77
78
79
80
81
82
if (!replace) {
free(new->value);
free(new->option);
free(new);
return 0;
}
Nov 6, 2009
Nov 6, 2009
83
84
85
86
87
/* Replace existing cookie */
if (new)
new->next = (*this)->next;
else
new = (*this)->next;
Mar 10, 2013
Mar 10, 2013
88
Nov 6, 2009
Nov 6, 2009
89
90
91
92
93
94
95
96
97
98
99
100
101
102
free((*this)->option);
free((*this)->value);
free(*this);
*this = new;
break;
}
}
if (new && !*this) {
*this = new;
new->next = NULL;
}
return 0;
}
Apr 22, 2022
Apr 22, 2022
103
104
105
106
107
108
109
110
111
112
113
const char *http_get_cookie(struct openconnect_info *vpninfo, const char *name)
{
struct oc_vpn_option *this;
for (this = vpninfo->cookies; this; this = this->next) {
if (!strcmp(this->option, name))
return this->value;
}
return NULL;
}
Mar 29, 2021
Mar 29, 2021
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* Some protocols use an "authentication cookie" which needs
* to be split into multiple HTTP cookies. (For example, oNCP
* 'DSSignInUrl=/; DSID=xxx; DSFirstAccess=xxx; DSLastAccess=xxx')
* Process those into vpninfo->cookies.
*/
int internal_split_cookies(struct openconnect_info *vpninfo, int replace, const char *def_cookie)
{
char *p = vpninfo->cookie;
while (p && *p) {
char *semicolon = strchr(p, ';');
char *equals;
if (semicolon)
*semicolon = 0;
equals = strchr(p, '=');
if (equals) {
*equals = 0;
http_add_cookie(vpninfo, p, equals+1, replace);
*equals = '=';
} else if (def_cookie) {
/* XX: assume this represents a single cookie's value */
http_add_cookie(vpninfo, def_cookie, p, replace);
} else {
vpn_progress(vpninfo, PRG_ERR, _("Invalid cookie '%s'\n"), p);
return -EINVAL;
}
p = semicolon;
if (p) {
*p = ';';
p++;
while (*p && isspace((int)(unsigned char)*p))
p++;
}
}
return 0;
}
Apr 15, 2021
Apr 15, 2021
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
int urldecode_inplace(char *p)
{
char *q;
if (!p)
return -EINVAL;
for (q = p; *p; p++, q++) {
if (*p == '+') {
*q = ' ';
} else if (*p == '%' && isxdigit((int)(unsigned char)p[1]) &&
isxdigit((int)(unsigned char)p[2])) {
*q = unhex(p + 1);
p += 2;
} else
*q = *p;
}
*q = 0;
return 0;
}
Sep 13, 2019
Sep 13, 2019
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/* Read one HTTP header line into hdrbuf, potentially allowing for
* continuation lines. Will never leave a character in 'nextchar' when
* an empty line (signifying end of headers) is received. Will only
* return success when hdrbuf is valid. */
static int read_http_header(struct openconnect_info *vpninfo, char *nextchar,
struct oc_text_buf *hdrbuf, int allow_cont)
{
int eol = 0;
int ret;
char c;
buf_truncate(hdrbuf);
c = *nextchar;
if (c) {
*nextchar = 0;
goto skip_first;
}
while (1) {
ret = vpninfo->ssl_read(vpninfo, &c, 1);
if (ret < 0)
return ret;
if (ret != 1)
return -EINVAL;
/* If we were looking for a continuation line and didn't get it,
* stash the character we *did* get into *nextchar for next time. */
if (eol && c != ' ' && c != '\t') {
*nextchar = c;
return buf_error(hdrbuf);
}
eol = 0;
skip_first:
if (c == '\n') {
if (!buf_error(hdrbuf) && hdrbuf->pos &&
hdrbuf->data[hdrbuf->pos - 1] == '\r') {
hdrbuf->pos--;
hdrbuf->data[hdrbuf->pos] = 0;
}
/* For a non-empty header line, see if there's a continuation */
if (allow_cont && hdrbuf->pos) {
eol = 1;
continue;
}
return buf_error(hdrbuf);
}
buf_append_bytes(hdrbuf, &c, 1);
}
return buf_error(hdrbuf);
}
Jan 9, 2010
Jan 9, 2010
231
232
233
#define BODY_HTTP10 -1
#define BODY_CHUNKED -2
Jan 26, 2015
Jan 26, 2015
234
235
236
int process_http_response(struct openconnect_info *vpninfo, int connect,
int (*header_cb)(struct openconnect_info *, char *, char *),
struct oc_text_buf *body)
Oct 1, 2008
Oct 1, 2008
237
{
Sep 13, 2019
Sep 13, 2019
238
239
struct oc_text_buf *hdrbuf = buf_alloc();
char nextchar = 0;
Jan 9, 2010
Jan 9, 2010
240
241
int bodylen = BODY_HTTP10;
int closeconn = 0;
Jul 24, 2014
Jul 24, 2014
242
int result;
Sep 13, 2019
Sep 13, 2019
243
int ret = -EINVAL;
Oct 1, 2008
Oct 1, 2008
244
245
int i;
Jul 24, 2014
Jul 24, 2014
246
247
buf_truncate(body);
Oct 11, 2019
Oct 11, 2019
248
249
250
251
/* Ensure it has *something* in it, so that we can dereference hdrbuf->data
* later without checking (for anything except buf_error(hdrbuf), which is
* what read_http_header() uses for its return code anyway). */
buf_append_bytes(hdrbuf, "\0", 1);
Jan 3, 2010
Jan 3, 2010
252
cont:
Sep 13, 2019
Sep 13, 2019
253
254
255
ret = read_http_header(vpninfo, &nextchar, hdrbuf, 0);
if (ret) {
vpn_progress(vpninfo, PRG_ERR, _("Error reading HTTP response: %s\n"),
Oct 9, 2019
Oct 9, 2019
256
strerror(-ret));
Sep 13, 2019
Sep 13, 2019
257
goto err;
Oct 1, 2008
Oct 1, 2008
258
259
}
Sep 13, 2019
Sep 13, 2019
260
if (!strncmp(hdrbuf->data, "HTTP/1.0 ", 9))
Oct 1, 2008
Oct 1, 2008
261
closeconn = 1;
Mar 10, 2013
Mar 10, 2013
262
Sep 13, 2019
Sep 13, 2019
263
264
if ((!closeconn && strncmp(hdrbuf->data, "HTTP/1.1 ", 9)) ||
!(result = atoi(hdrbuf->data + 9))) {
Sep 22, 2011
Sep 22, 2011
265
vpn_progress(vpninfo, PRG_ERR,
Sep 13, 2019
Sep 13, 2019
266
267
268
_("Failed to parse HTTP response '%s'\n"), hdrbuf->data);
ret = -EINVAL;
goto err;
Oct 1, 2008
Oct 1, 2008
269
270
}
Jul 24, 2014
Jul 24, 2014
271
vpn_progress(vpninfo, (result == 200 || result == 407) ? PRG_DEBUG : PRG_INFO,
Sep 13, 2019
Sep 13, 2019
272
_("Got HTTP response: %s\n"), hdrbuf->data);
Oct 1, 2008
Oct 1, 2008
273
274
/* Eat headers... */
Sep 13, 2019
Sep 13, 2019
275
while (1) {
Oct 1, 2008
Oct 1, 2008
276
char *colon;
Sep 13, 2019
Sep 13, 2019
277
char *hdrline;
Oct 1, 2008
Oct 1, 2008
278
Sep 13, 2019
Sep 13, 2019
279
280
281
ret = read_http_header(vpninfo, &nextchar, hdrbuf, 1);
if (ret) {
vpn_progress(vpninfo, PRG_ERR, _("Error reading HTTP response: %s\n"),
Oct 9, 2019
Oct 9, 2019
282
strerror(-ret));
Sep 13, 2019
Sep 13, 2019
283
goto err;
Oct 1, 2008
Oct 1, 2008
284
}
Sep 13, 2019
Sep 13, 2019
285
286
287
288
289
290
291
292
/* Empty line ends headers */
if (!hdrbuf->pos)
break;
hdrline = hdrbuf->data;
colon = strchr(hdrline, ':');
Oct 1, 2008
Oct 1, 2008
293
if (!colon) {
Sep 22, 2011
Sep 22, 2011
294
vpn_progress(vpninfo, PRG_ERR,
Sep 13, 2019
Sep 13, 2019
295
_("Ignoring unknown HTTP response line '%s'\n"), hdrline);
Oct 1, 2008
Oct 1, 2008
296
297
298
299
300
301
continue;
}
*(colon++) = 0;
if (*colon == ' ')
colon++;
Aug 7, 2010
Aug 7, 2010
302
303
/* Handle Set-Cookie first so that we can avoid printing the
webvpn cookie in the verbose debug output */
Sep 13, 2019
Sep 13, 2019
304
if (!strcasecmp(hdrline, "Set-Cookie")) {
Aug 7, 2010
Aug 7, 2010
305
char *semicolon = strchr(colon, ';');
Sep 15, 2011
Sep 15, 2011
306
307
const char *print_equals;
char *equals = strchr(colon, '=');
Aug 7, 2010
Aug 7, 2010
308
309
310
311
312
if (semicolon)
*semicolon = 0;
if (!equals) {
Sep 22, 2011
Sep 22, 2011
313
vpn_progress(vpninfo, PRG_ERR,
Sep 13, 2019
Sep 13, 2019
314
315
316
_("Invalid cookie offered: %s\n"), hdrline);
ret = -EINVAL;
goto err;
Aug 7, 2010
Aug 7, 2010
317
318
319
320
}
*(equals++) = 0;
print_equals = equals;
Nov 30, 2010
Nov 30, 2010
321
322
/* Don't print the webvpn cookie unless it's empty; we don't
want people posting it in public with debugging output */
Nov 11, 2020
Nov 11, 2020
323
if (vpninfo->proto->secure_cookie && !strcmp(colon, vpninfo->proto->secure_cookie) && *equals)
Sep 22, 2011
Sep 22, 2011
324
print_equals = _("<elided>");
Jun 13, 2014
Jun 13, 2014
325
vpn_progress(vpninfo, PRG_DEBUG, "%s: %s=%s%s%s\n",
Sep 13, 2019
Sep 13, 2019
326
hdrline, colon, print_equals, semicolon ? ";" : "",
Mar 10, 2013
Mar 10, 2013
327
semicolon ? (semicolon+1) : "");
Aug 7, 2010
Aug 7, 2010
328
Sep 25, 2011
Sep 25, 2011
329
330
331
332
333
334
335
/* The server tends to ask for the username and password as
usual, even if we've already failed because it didn't like
our cert. Thankfully it does give us this hint... */
if (!strcmp(colon, "ClientCertAuthFailed"))
vpn_progress(vpninfo, PRG_ERR,
_("SSL certificate authentication failed\n"));
Jan 26, 2015
Jan 26, 2015
336
ret = http_add_cookie(vpninfo, colon, equals, 1);
Sep 13, 2019
Sep 13, 2019
337
338
if (ret)
goto err;
Aug 7, 2010
Aug 7, 2010
339
} else {
Sep 13, 2019
Sep 13, 2019
340
vpn_progress(vpninfo, PRG_DEBUG, "%s: %s\n", hdrline, colon);
Aug 7, 2010
Aug 7, 2010
341
342
}
Sep 13, 2019
Sep 13, 2019
343
if (!strcasecmp(hdrline, "Connection")) {
Jan 9, 2010
Jan 9, 2010
344
345
if (!strcasecmp(colon, "Close"))
closeconn = 1;
Feb 28, 2010
Feb 28, 2010
346
347
348
349
350
351
#if 0
/* This might seem reasonable, but in fact it breaks
certificate authentication with some servers. If
they give an HTTP/1.0 response, even if they
explicitly give a Connection: Keep-Alive header,
just close the connection. */
Jan 9, 2010
Jan 9, 2010
352
353
else if (!strcasecmp(colon, "Keep-Alive"))
closeconn = 0;
Feb 28, 2010
Feb 28, 2010
354
#endif
Jan 9, 2010
Jan 9, 2010
355
}
Sep 13, 2019
Sep 13, 2019
356
if (!strcasecmp(hdrline, "Location")) {
Oct 1, 2008
Oct 1, 2008
357
vpninfo->redirect_url = strdup(colon);
Sep 10, 2019
Sep 10, 2019
358
if (!vpninfo->redirect_url) {
Sep 13, 2019
Sep 13, 2019
359
360
ret = -ENOMEM;
goto err;
Sep 10, 2019
Sep 10, 2019
361
}
Oct 1, 2008
Oct 1, 2008
362
}
Sep 13, 2019
Sep 13, 2019
363
if (!strcasecmp(hdrline, "Content-Length")) {
Oct 1, 2008
Oct 1, 2008
364
bodylen = atoi(colon);
Feb 22, 2010
Feb 22, 2010
365
if (bodylen < 0) {
Sep 22, 2011
Sep 22, 2011
366
367
368
vpn_progress(vpninfo, PRG_ERR,
_("Response body has negative size (%d)\n"),
bodylen);
Sep 13, 2019
Sep 13, 2019
369
370
ret = -EINVAL;
goto err;
Oct 1, 2008
Oct 1, 2008
371
372
}
}
Sep 13, 2019
Sep 13, 2019
373
if (!strcasecmp(hdrline, "Transfer-Encoding")) {
Jan 9, 2010
Jan 9, 2010
374
if (!strcasecmp(colon, "chunked"))
Jan 9, 2010
Jan 9, 2010
375
bodylen = BODY_CHUNKED;
Oct 1, 2008
Oct 1, 2008
376
else {
Sep 22, 2011
Sep 22, 2011
377
378
379
vpn_progress(vpninfo, PRG_ERR,
_("Unknown Transfer-Encoding: %s\n"),
colon);
Sep 13, 2019
Sep 13, 2019
380
381
ret = -EINVAL;
goto err;
Oct 1, 2008
Oct 1, 2008
382
383
}
}
Jun 18, 2014
Jun 18, 2014
384
if (header_cb)
Sep 13, 2019
Sep 13, 2019
385
header_cb(vpninfo, hdrline, colon);
Oct 1, 2008
Oct 1, 2008
386
387
388
}
/* Handle 'HTTP/1.1 100 Continue'. Not that we should ever see it */
Jul 24, 2014
Jul 24, 2014
389
if (result == 100)
Oct 1, 2008
Oct 1, 2008
390
391
goto cont;
Jun 7, 2019
Jun 7, 2019
392
/* On successful CONNECT or upgrade, there is no body. Return success */
Sep 13, 2019
Sep 13, 2019
393
394
if (connect && (result == 200 || result == 101)) {
buf_free(hdrbuf);
Jul 24, 2014
Jul 24, 2014
395
return result;
Sep 13, 2019
Sep 13, 2019
396
}
Jun 18, 2014
Jun 18, 2014
397
Jan 3, 2010
Jan 3, 2010
398
/* Now the body, if there is one */
Jun 13, 2014
Jun 13, 2014
399
vpn_progress(vpninfo, PRG_DEBUG, _("HTTP body %s (%d)\n"),
Mar 10, 2013
Mar 10, 2013
400
401
bodylen == BODY_HTTP10 ? "http 1.0" :
bodylen == BODY_CHUNKED ? "chunked" : "length: ",
Sep 22, 2011
Sep 22, 2011
402
bodylen);
Jan 3, 2010
Jan 3, 2010
403
Oct 1, 2008
Oct 1, 2008
404
405
/* If we were given Content-Length, it's nice and easy... */
if (bodylen > 0) {
Sep 10, 2019
Sep 10, 2019
406
if (buf_ensure_space(body, bodylen + 1)) {
Sep 13, 2019
Sep 13, 2019
407
408
ret = buf_error(body);
goto err;
Sep 10, 2019
Sep 10, 2019
409
}
Jul 24, 2014
Jul 24, 2014
410
411
412
while (body->pos < bodylen) {
i = vpninfo->ssl_read(vpninfo, body->data + body->pos, bodylen - body->pos);
Oct 1, 2008
Oct 1, 2008
413
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
414
415
vpn_progress(vpninfo, PRG_ERR,
_("Error reading HTTP response body\n"));
Sep 13, 2019
Sep 13, 2019
416
417
ret = i;
goto err;
Oct 1, 2008
Oct 1, 2008
418
}
Jul 24, 2014
Jul 24, 2014
419
body->pos += i;
Oct 1, 2008
Oct 1, 2008
420
}
Jan 9, 2010
Jan 9, 2010
421
} else if (bodylen == BODY_CHUNKED) {
Sep 13, 2019
Sep 13, 2019
422
char clen_buf[16];
Jan 9, 2010
Jan 9, 2010
423
/* ... else, chunked */
Sep 13, 2019
Sep 13, 2019
424
while ((i = vpninfo->ssl_gets(vpninfo, clen_buf, sizeof(clen_buf)))) {
Jan 13, 2024
Jan 13, 2024
425
char *endp;
Sep 11, 2019
Sep 11, 2019
426
427
int lastchunk = 0;
long chunklen;
Oct 1, 2008
Oct 1, 2008
428
429
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
430
431
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching chunk header\n"));
Sep 13, 2019
Sep 13, 2019
432
433
ret = i;
goto err;
Jan 9, 2010
Jan 9, 2010
434
}
Jun 17, 2023
Jun 17, 2023
435
chunklen = strtol(clen_buf, &endp, 16);
Jan 13, 2024
Jan 13, 2024
436
437
438
439
if (endp != clen_buf)
/* Be lenient with extraneous trailing spaces in chunk-size */
while (*endp && isspace(*endp))
++endp;
Jun 17, 2023
Jun 17, 2023
440
441
442
443
444
445
446
if (endp == clen_buf || (*endp && *endp != ';')) {
/* XX: Anything other than a non-negative hex integer followed by EOL or ';' is an error. */
vpn_progress(vpninfo, PRG_ERR,
_("Error in chunked decoding. Expected hexadecimal chunk length, got: '%s'\n"),
clen_buf);
goto err;
}
Jan 9, 2010
Jan 9, 2010
447
if (!chunklen) {
Jun 17, 2023
Jun 17, 2023
448
/* Zero indicates the last chunk */
Jan 9, 2010
Jan 9, 2010
449
450
451
lastchunk = 1;
goto skip;
}
Sep 11, 2019
Sep 11, 2019
452
453
454
if (chunklen < 0) {
vpn_progress(vpninfo, PRG_ERR,
_("HTTP chunk length is negative (%ld)\n"), chunklen);
Sep 13, 2019
Sep 13, 2019
455
456
ret = -EINVAL;
goto err;
Sep 11, 2019
Sep 11, 2019
457
458
459
460
}
if (chunklen >= INT_MAX) {
vpn_progress(vpninfo, PRG_ERR,
_("HTTP chunk length is too large (%ld)\n"), chunklen);
Sep 13, 2019
Sep 13, 2019
461
462
ret = -EINVAL;
goto err;
Sep 11, 2019
Sep 11, 2019
463
}
Sep 10, 2019
Sep 10, 2019
464
if (buf_ensure_space(body, chunklen + 1)) {
Sep 13, 2019
Sep 13, 2019
465
466
ret = buf_error(body);
goto err;
Sep 10, 2019
Sep 10, 2019
467
}
Jan 9, 2010
Jan 9, 2010
468
while (chunklen) {
Jul 24, 2014
Jul 24, 2014
469
i = vpninfo->ssl_read(vpninfo, body->data + body->pos, chunklen);
Jan 9, 2010
Jan 9, 2010
470
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
471
472
vpn_progress(vpninfo, PRG_ERR,
_("Error reading HTTP response body\n"));
Sep 13, 2019
Sep 13, 2019
473
474
ret = i;
goto err;
Jan 9, 2010
Jan 9, 2010
475
476
}
chunklen -= i;
Jul 24, 2014
Jul 24, 2014
477
body->pos += i;
Jan 9, 2010
Jan 9, 2010
478
479
}
skip:
Sep 13, 2019
Sep 13, 2019
480
if ((i = vpninfo->ssl_gets(vpninfo, clen_buf, sizeof(clen_buf)))) {
Jan 9, 2010
Jan 9, 2010
481
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
482
483
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching HTTP response body\n"));
Sep 13, 2019
Sep 13, 2019
484
ret = i;
Jan 9, 2010
Jan 9, 2010
485
} else {
Sep 22, 2011
Sep 22, 2011
486
vpn_progress(vpninfo, PRG_ERR,
Mar 29, 2021
Mar 29, 2021
487
_("Error in chunked decoding. Expected '', got: '%s'\n"),
Sep 13, 2019
Sep 13, 2019
488
489
clen_buf);
ret = -EINVAL;
Jan 9, 2010
Jan 9, 2010
490
}
Sep 13, 2019
Sep 13, 2019
491
goto err;
Oct 1, 2008
Oct 1, 2008
492
}
Feb 22, 2010
Feb 22, 2010
493
Jan 9, 2010
Jan 9, 2010
494
495
496
497
498
if (lastchunk)
break;
}
} else if (bodylen == BODY_HTTP10) {
if (!closeconn) {
Sep 22, 2011
Sep 22, 2011
499
500
vpn_progress(vpninfo, PRG_ERR,
_("Cannot receive HTTP 1.0 body without closing connection\n"));
Feb 4, 2013
Feb 4, 2013
501
openconnect_close_https(vpninfo, 0);
Nov 17, 2020
Nov 17, 2020
502
buf_free(hdrbuf);
Oct 1, 2008
Oct 1, 2008
503
504
505
return -EINVAL;
}
Jul 24, 2014
Jul 24, 2014
506
/* HTTP 1.0 response. Just eat all we can in 4KiB chunks */
Jan 9, 2010
Jan 9, 2010
507
while (1) {
Sep 10, 2019
Sep 10, 2019
508
if (buf_ensure_space(body, 4096 + 1)) {
Sep 13, 2019
Sep 13, 2019
509
510
ret = buf_error(body);
goto err;
Sep 10, 2019
Sep 10, 2019
511
}
Jul 24, 2014
Jul 24, 2014
512
513
i = vpninfo->ssl_read(vpninfo, body->data + body->pos, 4096);
if (i < 0) {
May 12, 2012
May 12, 2012
514
/* Error */
Sep 13, 2019
Sep 13, 2019
515
516
ret = i;
goto err;
Jul 24, 2014
Jul 24, 2014
517
} else if (!i)
Jan 9, 2010
Jan 9, 2010
518
break;
Jul 24, 2014
Jul 24, 2014
519
520
521
/* Got more data */
body->pos += i;
Jan 9, 2010
Jan 9, 2010
522
}
Oct 1, 2008
Oct 1, 2008
523
}
Jan 9, 2010
Jan 9, 2010
524
Apr 13, 2021
Apr 13, 2021
525
526
if (body && body->data)
body->data[body->pos] = 0;
Sep 13, 2019
Sep 13, 2019
527
528
529
530
531
532
533
ret = result;
if (closeconn || vpninfo->no_http_keepalive) {
err:
openconnect_close_https(vpninfo, 0);
}
buf_free(hdrbuf);
Oct 8, 2019
Oct 8, 2019
534
return ret;
Oct 1, 2008
Oct 1, 2008
535
536
}
Sep 29, 2014
Sep 29, 2014
537
int internal_parse_url(const char *url, char **res_proto, char **res_host,
Mar 9, 2011
Mar 9, 2011
538
int *res_port, char **res_path, int default_port)
Dec 25, 2009
Dec 25, 2009
539
{
Sep 29, 2014
Sep 29, 2014
540
541
542
const char *orig_host, *orig_path;
char *host, *port_str;
int port, proto_len = 0;
Dec 25, 2009
Dec 25, 2009
543
Sep 29, 2014
Sep 29, 2014
544
545
546
547
orig_host = strstr(url, "://");
if (orig_host) {
proto_len = orig_host - url;
orig_host += 3;
Jan 1, 2010
Jan 1, 2010
548
Sep 29, 2014
Sep 29, 2014
549
if (strprefix_match(url, proto_len, "https"))
Jan 1, 2010
Jan 1, 2010
550
port = 443;
Sep 29, 2014
Sep 29, 2014
551
else if (strprefix_match(url, proto_len, "http"))
Jan 1, 2010
Jan 1, 2010
552
port = 80;
Sep 29, 2014
Sep 29, 2014
553
554
555
else if (strprefix_match(url, proto_len, "socks") ||
strprefix_match(url, proto_len, "socks4") ||
strprefix_match(url, proto_len, "socks5"))
Jan 1, 2010
Jan 1, 2010
556
557
558
559
560
561
port = 1080;
else
return -EPROTONOSUPPORT;
} else {
if (default_port) {
port = default_port;
Sep 29, 2014
Sep 29, 2014
562
orig_host = url;
Jan 1, 2010
Jan 1, 2010
563
564
565
} else
return -EINVAL;
}
Dec 25, 2009
Dec 25, 2009
566
Sep 29, 2014
Sep 29, 2014
567
568
569
570
571
572
573
574
orig_path = strchr(orig_host, '/');
if (orig_path) {
host = strndup(orig_host, orig_path - orig_host);
orig_path++;
} else
host = strdup(orig_host);
if (!host)
return -ENOMEM;
Dec 25, 2009
Dec 25, 2009
575
576
577
578
579
580
581
582
583
port_str = strrchr(host, ':');
if (port_str) {
char *end;
int new_port = strtol(port_str + 1, &end, 10);
if (!*end) {
*port_str = 0;
port = new_port;
Nov 17, 2020
Nov 17, 2020
584
585
if (port <= 0 || port > 0xffff) {
free(host);
Nov 14, 2020
Nov 14, 2020
586
return -EINVAL;
Nov 17, 2020
Nov 17, 2020
587
}
Dec 25, 2009
Dec 25, 2009
588
589
590
591
}
}
if (res_proto)
Sep 29, 2014
Sep 29, 2014
592
*res_proto = proto_len ? strndup(url, proto_len) : NULL;
Dec 25, 2009
Dec 25, 2009
593
if (res_host)
Sep 29, 2014
Sep 29, 2014
594
595
596
*res_host = host;
else
free(host);
Dec 25, 2009
Dec 25, 2009
597
598
599
if (res_port)
*res_port = port;
if (res_path)
Sep 29, 2014
Sep 29, 2014
600
601
*res_path = (orig_path && *orig_path) ? strdup(orig_path) : NULL;
Dec 25, 2009
Dec 25, 2009
602
603
604
return 0;
}
Mar 29, 2021
Mar 29, 2021
605
606
char *internal_get_url(struct openconnect_info *vpninfo)
{
Apr 6, 2021
Apr 6, 2021
607
struct oc_text_buf *buf = buf_alloc();
Mar 29, 2021
Mar 29, 2021
608
char *url;
Apr 6, 2021
Apr 6, 2021
609
610
611
612
613
614
615
616
617
618
buf_append(buf, "https://%s", vpninfo->hostname);
if (vpninfo->port != 443)
buf_append(buf, ":%d", vpninfo->port);
buf_append(buf, "/");
if (vpninfo->urlpath)
buf_append(buf, "%s", vpninfo->urlpath);
if (buf_error(buf)) {
buf_free(buf);
Mar 29, 2021
Mar 29, 2021
619
return NULL;
Apr 6, 2021
Apr 6, 2021
620
621
622
623
} else {
url = buf->data;
buf->data = NULL;
buf_free(buf);
Mar 29, 2021
Mar 29, 2021
624
return url;
Apr 6, 2021
Apr 6, 2021
625
}
Mar 29, 2021
Mar 29, 2021
626
627
}
Oct 10, 2014
Oct 10, 2014
628
void openconnect_clear_cookies(struct openconnect_info *vpninfo)
Oct 27, 2012
Oct 27, 2012
629
{
Jan 15, 2014
Jan 15, 2014
630
struct oc_vpn_option *opt, *next;
Oct 27, 2012
Oct 27, 2012
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
for (opt = vpninfo->cookies; opt; opt = next) {
next = opt->next;
free(opt->option);
free(opt->value);
free(opt);
}
vpninfo->cookies = NULL;
}
/* Return value:
* < 0, on error
* = 0, on success (go ahead and retry with the latest vpninfo->{hostname,urlpath,port,...})
*/
Jan 26, 2015
Jan 26, 2015
646
int handle_redirect(struct openconnect_info *vpninfo)
Oct 27, 2012
Oct 27, 2012
647
{
Oct 28, 2012
Oct 28, 2012
648
649
vpninfo->redirect_type = REDIR_TYPE_LOCAL;
Oct 27, 2012
Oct 27, 2012
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
/* New host. Tear down the existing connection and make a new one */
char *host;
int port;
int ret;
free(vpninfo->urlpath);
vpninfo->urlpath = NULL;
ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
if (ret) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to parse redirected URL '%s': %s\n"),
vpninfo->redirect_url, strerror(-ret));
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
return ret;
}
if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
Dec 31, 2013
Dec 31, 2013
670
openconnect_set_hostname(vpninfo, host);
Oct 27, 2012
Oct 27, 2012
671
672
673
674
vpninfo->port = port;
/* Kill the existing connection, and a new one will happen */
openconnect_close_https(vpninfo, 0);
Oct 10, 2014
Oct 10, 2014
675
openconnect_clear_cookies(vpninfo);
Oct 28, 2012
Oct 28, 2012
676
vpninfo->redirect_type = REDIR_TYPE_NEWHOST;
Nov 4, 2014
Nov 4, 2014
677
678
}
free(host);
Oct 27, 2012
Oct 27, 2012
679
680
681
682
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
Jul 30, 2022
Jul 30, 2022
683
684
685
686
687
return 0;
} else if (vpninfo->redirect_url[0] == '\0' || vpninfo->redirect_url[0] == '#') {
/* Empty redirect, no op */
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
Oct 27, 2012
Oct 27, 2012
688
return 0;
Jan 27, 2022
Jan 27, 2022
689
690
691
692
693
694
695
} else if (vpninfo->redirect_url[0] == '/') {
/* Absolute redirect within same host */
free(vpninfo->urlpath);
vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
return 0;
Oct 27, 2012
Oct 27, 2012
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
} else if (strstr(vpninfo->redirect_url, "://")) {
vpn_progress(vpninfo, PRG_ERR,
_("Cannot follow redirection to non-https URL '%s'\n"),
vpninfo->redirect_url);
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
return -EINVAL;
} else {
char *lastslash = NULL;
if (vpninfo->urlpath)
lastslash = strrchr(vpninfo->urlpath, '/');
if (!lastslash) {
free(vpninfo->urlpath);
vpninfo->urlpath = vpninfo->redirect_url;
vpninfo->redirect_url = NULL;
} else {
char *oldurl = vpninfo->urlpath;
*lastslash = 0;
vpninfo->urlpath = NULL;
if (asprintf(&vpninfo->urlpath, "%s/%s",
oldurl, vpninfo->redirect_url) == -1) {
int err = -errno;
vpn_progress(vpninfo, PRG_ERR,
_("Allocating new path for relative redirect failed: %s\n"),
strerror(-err));
return err;
}
free(oldurl);
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
}
return 0;
}
}
Apr 9, 2022
Apr 9, 2022
731
void do_dump_buf(struct openconnect_info *vpninfo, char prefix, char *buf)
May 30, 2013
May 30, 2013
732
733
734
735
736
737
738
739
740
741
742
743
744
745
{
while (*buf) {
char *eol = buf;
char eol_char = 0;
while (*eol) {
if (*eol == '\r' || *eol == '\n') {
eol_char = *eol;
*eol = 0;
break;
}
eol++;
}
Jun 13, 2014
Jun 13, 2014
746
vpn_progress(vpninfo, PRG_DEBUG, "%c %s\n", prefix, buf);
May 30, 2013
May 30, 2013
747
748
749
750
751
752
753
754
755
756
if (!eol_char)
break;
*eol = eol_char;
buf = eol + 1;
if (eol_char == '\r' && *buf == '\n')
buf++;
}
}
Apr 9, 2022
Apr 9, 2022
757
void do_dump_buf_hex(struct openconnect_info *vpninfo, int loglevel, char prefix, unsigned char *buf, int len)
Aug 14, 2017
Aug 14, 2017
758
{
Jun 7, 2019
Jun 7, 2019
759
struct oc_text_buf *line = buf_alloc();
Apr 9, 2022
Apr 9, 2022
760
int i;
Aug 14, 2017
Aug 14, 2017
761
Jun 7, 2019
Jun 7, 2019
762
for (i = 0; i < len; i+=16) {
Apr 9, 2022
Apr 9, 2022
763
764
int j;
Jun 7, 2019
Jun 7, 2019
765
766
buf_truncate(line);
buf_append(line, "%04x:", i);
Jun 7, 2019
Jun 7, 2019
767
for (j = i; j < i+16; j++) {
Jun 7, 2019
Jun 7, 2019
768
769
770
if (!(j & 7))
buf_append(line, " ");
Jun 7, 2019
Jun 7, 2019
771
if (j < len)
Jun 7, 2019
Jun 7, 2019
772
buf_append(line, " %02x", buf[j]);
Jun 7, 2019
Jun 7, 2019
773
else
Jun 7, 2019
Jun 7, 2019
774
buf_append(line, " ");
Aug 14, 2017
Aug 14, 2017
775
}
Jun 7, 2019
Jun 7, 2019
776
buf_append(line, " |");
Jun 7, 2019
Jun 7, 2019
777
for (j = i; j < i+16 && j < len; j++)
Jun 7, 2019
Jun 7, 2019
778
779
780
781
782
buf_append(line, "%c", isprint(buf[j])? buf[j] : '.');
buf_append(line, "|");
if (buf_error(line))
break;
vpn_progress(vpninfo, loglevel, "%c %s\n", prefix, line->data);
Aug 14, 2017
Aug 14, 2017
783
}
Jun 7, 2019
Jun 7, 2019
784
buf_free(line);
Aug 14, 2017
Aug 14, 2017
785
786
}
Dec 29, 2019
Dec 29, 2019
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
static int https_socket_closed(struct openconnect_info *vpninfo)
{
char c;
if (!openconnect_https_connected(vpninfo))
return 1;
if (recv(vpninfo->ssl_fd, &c, 1, MSG_PEEK) == 0) {
vpn_progress(vpninfo, PRG_DEBUG,
_("HTTPS socket closed by peer; reopening\n"));
openconnect_close_https(vpninfo, 0);
return 1;
}
return 0;
}
Oct 28, 2012
Oct 28, 2012
805
806
807
808
809
810
811
812
/* Inputs:
* method: GET or POST
* vpninfo->hostname: Host DNS name
* vpninfo->port: TCP port, typically 443
* vpninfo->urlpath: Relative path, e.g. /+webvpn+/foo.html
* request_body_type: Content type for a POST (e.g. text/html). Can be NULL.
* request_body: POST content
* form_buf: Callee-allocated buffer for server content
Jun 15, 2021
Jun 15, 2021
813
814
* header_cb: Callback executed on every header line
* If HTTP authentication is needed, the callback specified needs to call http_auth_hdrs.
Oct 21, 2021
Oct 21, 2021
815
816
817
* flags (bitfield): HTTP_REDIRECT: follow redirects;
* HTTP_REDIRECT_TO_GET: follow redirects, but change POST to GET;
* HTTP_BODY_ON_ERR: return server content in form_buf even on error
Oct 28, 2012
Oct 28, 2012
818
819
*
* Return value:
Jan 24, 2009
Jan 24, 2009
820
* < 0, on error
Oct 28, 2012
Oct 28, 2012
821
* >=0, on success, indicating the length of the data in *form_buf
Jan 24, 2009
Jan 24, 2009
822
*/
Jun 15, 2021
Jun 15, 2021
823
824
int do_https_request(struct openconnect_info *vpninfo, const char *method, const char *request_body_type,
struct oc_text_buf *request_body, char **form_buf,
Oct 21, 2021
Oct 21, 2021
825
int (*header_cb)(struct openconnect_info *, char *, char *), int flags)
Oct 1, 2008
Oct 1, 2008
826
{
Oct 9, 2019
Oct 9, 2019
827
struct oc_text_buf *buf;
Jul 24, 2014
Jul 24, 2014
828
int result;
May 22, 2013
May 22, 2013
829
int rq_retry;
Feb 3, 2014
Feb 3, 2014
830
int rlen, pad;
Nov 29, 2017
Nov 29, 2017
831
int i, auth = 0;
Feb 24, 2015
Feb 24, 2015
832
int max_redirects = 10;
Oct 15, 2012
Oct 15, 2012
833
Jun 15, 2021
Jun 15, 2021
834
835
836
if (!header_cb)
header_cb = http_auth_hdrs;
Jul 27, 2014
Jul 27, 2014
837
if (request_body_type && buf_error(request_body))
Jul 24, 2014
Jul 24, 2014
838
839
return buf_error(request_body);
Oct 9, 2019
Oct 9, 2019
840
841
buf = buf_alloc();
May 22, 2013
May 22, 2013
842
redirected:
Feb 24, 2015
Feb 24, 2015
843
844
845
846
847
if (max_redirects-- <= 0) {
result = -EIO;
goto out;
}
Oct 28, 2012
Oct 28, 2012
848
849
vpninfo->redirect_type = REDIR_TYPE_NONE;
Oct 28, 2012
Oct 28, 2012
850
851
852
if (*form_buf) {
free(*form_buf);
*form_buf = NULL;
Nov 24, 2010
Nov 24, 2010
853
}
Oct 1, 2008
Oct 1, 2008
854
855
/*
Jan 14, 2016
Jan 14, 2016
856
857
858
* A long time ago, I *wanted* to use an HTTP client library like cURL
* for this. But we need a *lot* of control over the underlying SSL
* transport, and we also have to do horrid tricks like the Juniper NC
Aug 7, 2021
Aug 7, 2021
859
* 'GET' request that actually behaves like a 'CONNECT'.
Jan 14, 2016
Jan 14, 2016
860
861
*
* So the world gained Yet Another HTTP Implementation. Sorry.
Oct 1, 2008
Oct 1, 2008
862
863
*
*/
Mar 14, 2015
Mar 14, 2015
864
buf_truncate(buf);
Oct 28, 2012
Oct 28, 2012
865
buf_append(buf, "%s /%s HTTP/1.1\r\n", method, vpninfo->urlpath ?: "");
Feb 24, 2015
Feb 24, 2015
866
867
868
869
870
871
872
873
if (auth) {
result = gen_authorization_hdr(vpninfo, 0, buf);
if (result)
goto out;
/* Forget existing challenges */
clear_auth_states(vpninfo, vpninfo->http_auth, 0);
}
May 16, 2016
May 16, 2016
874
875
if (vpninfo->proto->add_http_headers)
vpninfo->proto->add_http_headers(vpninfo, buf);
Oct 1, 2008
Oct 1, 2008
876
Oct 1, 2008
Oct 1, 2008
877
if (request_body_type) {
Jul 24, 2014
Jul 24, 2014
878
rlen = request_body->pos;
Feb 3, 2014
Feb 3, 2014
879
880
881
882
883
884
/* force body length to be a multiple of 64, to avoid leaking
* password length. */
pad = 64*(1+rlen/64) - rlen;
buf_append(buf, "X-Pad: %0*d\r\n", pad, 0);
Oct 28, 2012
Oct 28, 2012
885
buf_append(buf, "Content-Type: %s\r\n", request_body_type);
Feb 3, 2014
Feb 3, 2014
886
buf_append(buf, "Content-Length: %d\r\n", (int)rlen);
Oct 1, 2008
Oct 1, 2008
887
}
Oct 28, 2012
Oct 28, 2012
888
889
buf_append(buf, "\r\n");
Oct 1, 2008
Oct 1, 2008
890
if (request_body_type)
Jul 24, 2014
Jul 24, 2014
891
buf_append_bytes(buf, request_body->data, request_body->pos);
Oct 1, 2008
Oct 1, 2008
892
Dec 23, 2009
Dec 23, 2009
893
if (vpninfo->port == 443)
Jun 27, 2011
Jun 27, 2011
894
vpn_progress(vpninfo, PRG_INFO, "%s https://%s/%s\n",
Sep 22, 2011
Sep 22, 2011
895
896
method, vpninfo->hostname,
vpninfo->urlpath ?: "");
Dec 23, 2009
Dec 23, 2009
897
else
Jun 27, 2011
Jun 27, 2011
898
vpn_progress(vpninfo, PRG_INFO, "%s https://%s:%d/%s\n",
Sep 22, 2011
Sep 22, 2011
899
900
method, vpninfo->hostname, vpninfo->port,
vpninfo->urlpath ?: "");
Apr 1, 2009
Apr 1, 2009
901
Oct 28, 2012
Oct 28, 2012
902
903
904
if (buf_error(buf))
return buf_free(buf);
Feb 24, 2015
Feb 24, 2015
905
906
vpninfo->retry_on_auth_fail = 0;
May 22, 2013
May 22, 2013
907
retry:
Dec 29, 2019
Dec 29, 2019
908
if (!https_socket_closed(vpninfo)) {
May 22, 2013
May 22, 2013
909
910
911
912
913
914
/* The session is already connected. If we get a failure on
* *sending* the request, try it again immediately with a new
* connection. */
rq_retry = 1;
} else {
rq_retry = 0;
Nov 17, 2020
Nov 17, 2020
915
if ((openconnect_open_https(vpninfo))) {
May 22, 2013
May 22, 2013
916
917
918
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open HTTPS connection to %s\n"),
vpninfo->hostname);
Jul 18, 2014
Jul 18, 2014
919
920
921
922
/* We really don't want to return -EINVAL if we have
failed to even connect to the server, because if
we do that openconnect_obtain_cookie() might try
again without XMLPOST... with the same result. */
Feb 24, 2015
Feb 24, 2015
923
924
result = -EIO;
goto out;
May 22, 2013
May 22, 2013
925
926
927
}
}
May 30, 2013
May 30, 2013
928
929
930
if (vpninfo->dump_http_traffic)
dump_buf(vpninfo, '>', buf->data);
Nov 29, 2017
Nov 29, 2017
931
932
933
934
935
936
937
938
939
940
941
942
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;
}
May 22, 2013
May 22, 2013
943
}
Oct 1, 2008
Oct 1, 2008
944
Jun 15, 2021
Jun 15, 2021
945
result = process_http_response(vpninfo, 0, header_cb, buf);
Jul 24, 2014
Jul 24, 2014
946
if (result < 0) {
Jan 15, 2020
Jan 15, 2020
947
948
949
950
951
952
953
954
955
if (rq_retry) {
openconnect_close_https(vpninfo, 0);
vpn_progress(vpninfo, PRG_INFO,
_("Retrying failed %s request on new connection\n"),
method);
/* All the way back to 'redirected' since we need to rebuild
* the request in 'buf' from scratch. */
goto redirected;
}
Jul 24, 2014
Jul 24, 2014
956
goto out;
Oct 1, 2008
Oct 1, 2008
957
}
Jul 24, 2014
Jul 24, 2014
958
959
if (vpninfo->dump_http_traffic && buf->pos)
dump_buf(vpninfo, '<', buf->data);
Oct 1, 2008
Oct 1, 2008
960
Feb 24, 2015
Feb 24, 2015
961
if (result == 401 && vpninfo->try_http_auth) {
Feb 24, 2015
Feb 24, 2015
962
963
964
auth = 1;
goto redirected;
}
Oct 1, 2008
Oct 1, 2008
965
if (result != 200 && vpninfo->redirect_url) {
Oct 27, 2012
Oct 27, 2012
966
result = handle_redirect(vpninfo);
Oct 28, 2012
Oct 28, 2012
967
if (result == 0) {
Oct 21, 2021
Oct 21, 2021
968
if (!(flags & (HTTP_REDIRECT | HTTP_REDIRECT_TO_GET)))
Jul 27, 2014
Jul 27, 2014
969
goto out;
Oct 21, 2021
Oct 21, 2021
970
971
if (flags & HTTP_REDIRECT_TO_GET) {
/* Some protocols require a GET after a redirected POST */
Jan 26, 2015
Jan 26, 2015
972
973
974
method = "GET";
request_body_type = NULL;
}
Feb 24, 2015
Feb 24, 2015
975
976
if (vpninfo->redirect_type == REDIR_TYPE_NEWHOST)
clear_auth_states(vpninfo, vpninfo->http_auth, 1);
May 22, 2013
May 22, 2013
977
goto redirected;
Oct 28, 2012
Oct 28, 2012
978
}
Oct 28, 2012
Oct 28, 2012
979
goto out;
Oct 1, 2008
Oct 1, 2008
980
}
Jul 24, 2014
Jul 24, 2014
981
if (!buf->pos || result != 200) {
Jun 27, 2011
Jun 27, 2011
982
vpn_progress(vpninfo, PRG_ERR,
Sep 22, 2011
Sep 22, 2011
983
984
_("Unexpected %d result from server\n"),
result);
May 31, 2018
May 31, 2018
985
986
987
988
if (result == 401 || result == 403)
result = -EPERM;
else if (result == 512) /* GlobalProtect invalid username/password */
result = -EACCES;
Sep 1, 2022
Sep 1, 2022
989
990
else if (result == 405) /* Method not supported */
result = -EOPNOTSUPP;
May 31, 2018
May 31, 2018
991
992
else
result = -EINVAL;
Oct 21, 2021
Oct 21, 2021
993
994
995
996
997
if (!buf->pos || !(flags & HTTP_BODY_ON_ERROR))
goto out;
} else
result = buf->pos;
Oct 28, 2012
Oct 28, 2012
998
Jul 24, 2014
Jul 24, 2014
999
1000
*form_buf = buf->data;
buf->data = NULL;