Skip to content

Latest commit

 

History

History
1464 lines (1275 loc) · 36.1 KB

http.c

File metadata and controls

1464 lines (1275 loc) · 36.1 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
*
May 13, 2012
May 13, 2012
4
* Copyright © 2008-2012 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
17
18
19
20
21
22
23
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to:
*
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
Oct 1, 2008
Oct 1, 2008
24
25
26
27
28
29
*/
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
Jun 1, 2009
Jun 1, 2009
30
#include <string.h>
Oct 1, 2008
Oct 1, 2008
31
#include <ctype.h>
Aug 7, 2009
Aug 7, 2009
32
#include <pwd.h>
Jul 20, 2009
Jul 20, 2009
33
#include <sys/stat.h>
Aug 7, 2009
Aug 7, 2009
34
#include <sys/types.h>
May 29, 2012
May 29, 2012
35
36
37
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
Oct 28, 2012
Oct 28, 2012
38
#include <stdarg.h>
Oct 1, 2008
Oct 1, 2008
39
Mar 9, 2011
Mar 9, 2011
40
#include "openconnect-internal.h"
Oct 1, 2008
Oct 1, 2008
41
May 12, 2012
May 12, 2012
42
43
44
45
static int proxy_write(struct openconnect_info *vpninfo, int fd,
unsigned char *buf, size_t len);
static int proxy_read(struct openconnect_info *vpninfo, int fd,
unsigned char *buf, size_t len);
Feb 22, 2010
Feb 22, 2010
46
Aug 4, 2009
Aug 4, 2009
47
#define MAX_BUF_LEN 131072
Oct 28, 2012
Oct 28, 2012
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define BUF_CHUNK_SIZE 4096
struct oc_text_buf {
char *data;
int pos;
int buf_len;
int error;
};
static struct oc_text_buf *buf_alloc(void)
{
return calloc(1, sizeof(struct oc_text_buf));
}
static void buf_append(struct oc_text_buf *buf, const char *fmt, ...)
{
va_list ap;
if (!buf || buf->error)
return;
if (!buf->data) {
buf->data = malloc(BUF_CHUNK_SIZE);
if (!buf->data) {
buf->error = -ENOMEM;
return;
}
buf->buf_len = BUF_CHUNK_SIZE;
}
while (1) {
int max_len = buf->buf_len - buf->pos, ret;
va_start(ap, fmt);
ret = vsnprintf(buf->data + buf->pos, max_len, fmt, ap);
va_end(ap);
if (ret < 0) {
buf->error = -EIO;
break;
} else if (ret < max_len) {
buf->pos += ret;
break;
} else {
int new_buf_len = buf->buf_len + BUF_CHUNK_SIZE;
if (new_buf_len > MAX_BUF_LEN) {
/* probably means somebody is messing with us */
buf->error = -E2BIG;
break;
}
buf->data = realloc(buf->data, new_buf_len);
if (!buf->data) {
buf->error = -ENOMEM;
break;
}
buf->buf_len = new_buf_len;
}
}
}
static int buf_error(struct oc_text_buf *buf)
{
return buf ? buf->error : -ENOMEM;
}
static int buf_free(struct oc_text_buf *buf)
{
int error = buf_error(buf);
if (buf) {
if (buf->data)
free(buf->data);
free(buf);
}
return error;
}
Oct 1, 2008
Oct 1, 2008
127
/*
Apr 9, 2009
Apr 9, 2009
128
* We didn't really want to have to do this for ourselves -- one might have
Oct 1, 2008
Oct 1, 2008
129
130
131
132
133
134
* 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.
*/
Apr 16, 2010
Apr 16, 2010
135
136
static int http_add_cookie(struct openconnect_info *vpninfo,
const char *option, const char *value)
Nov 6, 2009
Nov 6, 2009
137
138
139
140
141
142
{
struct vpn_option *new, **this;
if (*value) {
new = malloc(sizeof(*new));
if (!new) {
Sep 22, 2011
Sep 22, 2011
143
144
vpn_progress(vpninfo, PRG_ERR,
_("No memory for allocating cookies\n"));
Nov 6, 2009
Nov 6, 2009
145
146
147
148
149
return -ENOMEM;
}
new->next = NULL;
new->option = strdup(option);
new->value = strdup(value);
Nov 6, 2009
Nov 6, 2009
150
151
152
153
154
155
if (!new->option || !new->value) {
free(new->option);
free(new->value);
free(new);
return -ENOMEM;
}
Nov 6, 2009
Nov 6, 2009
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
} else {
/* Kill cookie; don't replace it */
new = NULL;
}
for (this = &vpninfo->cookies; *this; this = &(*this)->next) {
if (!strcmp(option, (*this)->option)) {
/* Replace existing cookie */
if (new)
new->next = (*this)->next;
else
new = (*this)->next;
free((*this)->option);
free((*this)->value);
free(*this);
*this = new;
break;
}
}
if (new && !*this) {
*this = new;
new->next = NULL;
}
return 0;
}
Jan 9, 2010
Jan 9, 2010
182
183
184
#define BODY_HTTP10 -1
#define BODY_CHUNKED -2
Oct 5, 2008
Oct 5, 2008
185
186
static int process_http_response(struct openconnect_info *vpninfo, int *result,
int (*header_cb)(struct openconnect_info *, char *, char *),
Feb 22, 2010
Feb 22, 2010
187
char **body_ret)
Oct 1, 2008
Oct 1, 2008
188
{
Aug 4, 2009
Aug 4, 2009
189
char buf[MAX_BUF_LEN];
Feb 22, 2010
Feb 22, 2010
190
char *body = NULL;
Jan 9, 2010
Jan 9, 2010
191
int bodylen = BODY_HTTP10;
Oct 1, 2008
Oct 1, 2008
192
int done = 0;
Jan 9, 2010
Jan 9, 2010
193
int closeconn = 0;
Oct 1, 2008
Oct 1, 2008
194
195
int i;
Jan 3, 2010
Jan 3, 2010
196
cont:
May 12, 2012
May 12, 2012
197
if (openconnect_SSL_gets(vpninfo, buf, sizeof(buf)) < 0) {
Sep 22, 2011
Sep 22, 2011
198
199
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching HTTPS response\n"));
Oct 5, 2008
Oct 5, 2008
200
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
201
202
}
Jan 9, 2010
Jan 9, 2010
203
if (!strncmp(buf, "HTTP/1.0 ", 9))
Oct 1, 2008
Oct 1, 2008
204
closeconn = 1;
Jan 9, 2010
Jan 9, 2010
205
206
if ((!closeconn && strncmp(buf, "HTTP/1.1 ", 9)) || !(*result = atoi(buf+9))) {
Sep 22, 2011
Sep 22, 2011
207
208
vpn_progress(vpninfo, PRG_ERR,
_("Failed to parse HTTP response '%s'\n"), buf);
Oct 1, 2008
Oct 1, 2008
209
210
211
return -EINVAL;
}
Jun 27, 2011
Jun 27, 2011
212
vpn_progress(vpninfo, (*result==200)?PRG_TRACE:PRG_INFO,
Sep 22, 2011
Sep 22, 2011
213
_("Got HTTP response: %s\n"), buf);
Oct 1, 2008
Oct 1, 2008
214
215
/* Eat headers... */
May 12, 2012
May 12, 2012
216
while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
Oct 1, 2008
Oct 1, 2008
217
218
219
char *colon;
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
220
221
vpn_progress(vpninfo, PRG_ERR,
_("Error processing HTTP response\n"));
Oct 1, 2008
Oct 1, 2008
222
223
224
225
return -EINVAL;
}
colon = strchr(buf, ':');
if (!colon) {
Sep 22, 2011
Sep 22, 2011
226
227
vpn_progress(vpninfo, PRG_ERR,
_("Ignoring unknown HTTP response line '%s'\n"), buf);
Oct 1, 2008
Oct 1, 2008
228
229
230
231
232
233
continue;
}
*(colon++) = 0;
if (*colon == ' ')
colon++;
Aug 7, 2010
Aug 7, 2010
234
235
236
237
/* Handle Set-Cookie first so that we can avoid printing the
webvpn cookie in the verbose debug output */
if (!strcasecmp(buf, "Set-Cookie")) {
char *semicolon = strchr(colon, ';');
Sep 15, 2011
Sep 15, 2011
238
239
const char *print_equals;
char *equals = strchr(colon, '=');
Aug 7, 2010
Aug 7, 2010
240
241
242
243
244
245
int ret;
if (semicolon)
*semicolon = 0;
if (!equals) {
Sep 22, 2011
Sep 22, 2011
246
247
vpn_progress(vpninfo, PRG_ERR,
_("Invalid cookie offered: %s\n"), buf);
Aug 7, 2010
Aug 7, 2010
248
249
250
251
252
return -EINVAL;
}
*(equals++) = 0;
print_equals = equals;
Nov 30, 2010
Nov 30, 2010
253
254
255
/* Don't print the webvpn cookie unless it's empty; we don't
want people posting it in public with debugging output */
if (!strcmp(colon, "webvpn") && *equals)
Sep 22, 2011
Sep 22, 2011
256
print_equals = _("<elided>");
Jun 27, 2011
Jun 27, 2011
257
vpn_progress(vpninfo, PRG_TRACE, "%s: %s=%s%s%s\n",
Sep 22, 2011
Sep 22, 2011
258
259
buf, colon, print_equals, semicolon?";":"",
semicolon?(semicolon+1):"");
Aug 7, 2010
Aug 7, 2010
260
Sep 25, 2011
Sep 25, 2011
261
262
263
264
265
266
267
/* 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"));
Aug 7, 2010
Aug 7, 2010
268
269
270
271
ret = http_add_cookie(vpninfo, colon, equals);
if (ret)
return ret;
} else {
Jun 27, 2011
Jun 27, 2011
272
vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
Aug 7, 2010
Aug 7, 2010
273
274
}
Jan 9, 2010
Jan 9, 2010
275
276
277
if (!strcasecmp(buf, "Connection")) {
if (!strcasecmp(colon, "Close"))
closeconn = 1;
Feb 28, 2010
Feb 28, 2010
278
279
280
281
282
283
#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
284
285
else if (!strcasecmp(colon, "Keep-Alive"))
closeconn = 0;
Feb 28, 2010
Feb 28, 2010
286
#endif
Jan 9, 2010
Jan 9, 2010
287
}
Jan 9, 2010
Jan 9, 2010
288
if (!strcasecmp(buf, "Location")) {
Oct 1, 2008
Oct 1, 2008
289
290
291
292
vpninfo->redirect_url = strdup(colon);
if (!vpninfo->redirect_url)
return -ENOMEM;
}
Jan 9, 2010
Jan 9, 2010
293
if (!strcasecmp(buf, "Content-Length")) {
Oct 1, 2008
Oct 1, 2008
294
bodylen = atoi(colon);
Feb 22, 2010
Feb 22, 2010
295
if (bodylen < 0) {
Sep 22, 2011
Sep 22, 2011
296
297
298
vpn_progress(vpninfo, PRG_ERR,
_("Response body has negative size (%d)\n"),
bodylen);
Oct 1, 2008
Oct 1, 2008
299
300
301
return -EINVAL;
}
}
Jan 9, 2010
Jan 9, 2010
302
303
if (!strcasecmp(buf, "Transfer-Encoding")) {
if (!strcasecmp(colon, "chunked"))
Jan 9, 2010
Jan 9, 2010
304
bodylen = BODY_CHUNKED;
Oct 1, 2008
Oct 1, 2008
305
else {
Sep 22, 2011
Sep 22, 2011
306
307
308
vpn_progress(vpninfo, PRG_ERR,
_("Unknown Transfer-Encoding: %s\n"),
colon);
Oct 1, 2008
Oct 1, 2008
309
310
311
312
313
314
315
316
317
318
319
return -EINVAL;
}
}
if (header_cb && !strncmp(buf, "X-", 2))
header_cb(vpninfo, buf, colon);
}
/* Handle 'HTTP/1.1 100 Continue'. Not that we should ever see it */
if (*result == 100)
goto cont;
Jan 3, 2010
Jan 3, 2010
320
/* Now the body, if there is one */
Sep 22, 2011
Sep 22, 2011
321
322
323
324
vpn_progress(vpninfo, PRG_TRACE, _("HTTP body %s (%d)\n"),
bodylen==BODY_HTTP10?"http 1.0" :
bodylen==BODY_CHUNKED?"chunked" : "length: ",
bodylen);
Jan 3, 2010
Jan 3, 2010
325
Oct 1, 2008
Oct 1, 2008
326
327
/* If we were given Content-Length, it's nice and easy... */
if (bodylen > 0) {
Feb 22, 2010
Feb 22, 2010
328
329
330
body = malloc(bodylen + 1);
if (!body)
return -ENOMEM;
Oct 1, 2008
Oct 1, 2008
331
while (done < bodylen) {
May 12, 2012
May 12, 2012
332
i = openconnect_SSL_read(vpninfo, body + done, bodylen - done);
Oct 1, 2008
Oct 1, 2008
333
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
334
335
vpn_progress(vpninfo, PRG_ERR,
_("Error reading HTTP response body\n"));
Feb 22, 2010
Feb 22, 2010
336
free(body);
Oct 1, 2008
Oct 1, 2008
337
338
339
340
return -EINVAL;
}
done += i;
}
Jan 9, 2010
Jan 9, 2010
341
342
} else if (bodylen == BODY_CHUNKED) {
/* ... else, chunked */
May 12, 2012
May 12, 2012
343
while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
Jan 9, 2010
Jan 9, 2010
344
int chunklen, lastchunk = 0;
Oct 1, 2008
Oct 1, 2008
345
346
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
347
348
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching chunk header\n"));
May 13, 2012
May 13, 2012
349
return i;
Jan 9, 2010
Jan 9, 2010
350
351
352
353
354
355
}
chunklen = strtol(buf, NULL, 16);
if (!chunklen) {
lastchunk = 1;
goto skip;
}
Feb 22, 2010
Feb 22, 2010
356
357
358
body = realloc(body, done + chunklen + 1);
if (!body)
return -ENOMEM;
Jan 9, 2010
Jan 9, 2010
359
while (chunklen) {
May 12, 2012
May 12, 2012
360
i = openconnect_SSL_read(vpninfo, body + done, chunklen);
Jan 9, 2010
Jan 9, 2010
361
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
362
363
vpn_progress(vpninfo, PRG_ERR,
_("Error reading HTTP response body\n"));
Feb 22, 2010
Feb 22, 2010
364
free(body);
Jan 9, 2010
Jan 9, 2010
365
366
367
368
369
370
return -EINVAL;
}
chunklen -= i;
done += i;
}
skip:
May 12, 2012
May 12, 2012
371
if ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
Jan 9, 2010
Jan 9, 2010
372
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
373
374
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching HTTP response body\n"));
Jan 9, 2010
Jan 9, 2010
375
} else {
Sep 22, 2011
Sep 22, 2011
376
377
378
vpn_progress(vpninfo, PRG_ERR,
_("Error in chunked decoding. Expected '', got: '%s'"),
buf);
Jan 9, 2010
Jan 9, 2010
379
}
Feb 22, 2010
Feb 22, 2010
380
free(body);
Jan 9, 2010
Jan 9, 2010
381
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
382
}
Feb 22, 2010
Feb 22, 2010
383
Jan 9, 2010
Jan 9, 2010
384
385
386
387
388
if (lastchunk)
break;
}
} else if (bodylen == BODY_HTTP10) {
if (!closeconn) {
Sep 22, 2011
Sep 22, 2011
389
390
vpn_progress(vpninfo, PRG_ERR,
_("Cannot receive HTTP 1.0 body without closing connection\n"));
Feb 4, 2013
Feb 4, 2013
391
openconnect_close_https(vpninfo, 0);
Oct 1, 2008
Oct 1, 2008
392
393
394
return -EINVAL;
}
Feb 22, 2010
Feb 22, 2010
395
/* HTTP 1.0 response. Just eat all we can in 16KiB chunks */
Jan 9, 2010
Jan 9, 2010
396
while (1) {
Feb 22, 2010
Feb 22, 2010
397
body = realloc(body, done + 16384);
Feb 22, 2010
Feb 22, 2010
398
399
if (!body)
return -ENOMEM;
May 12, 2012
May 12, 2012
400
401
402
403
404
405
406
407
408
409
i = openconnect_SSL_read(vpninfo, body + done, 16384);
if (i > 0) {
/* Got more data */
done += i;
} else if (i < 0) {
/* Error */
free(body);
return i;
} else {
/* Connection closed. Reduce allocation to just what we need */
Feb 22, 2010
Feb 22, 2010
410
body = realloc(body, done + 1);
Feb 22, 2010
Feb 22, 2010
411
412
if (!body)
return -ENOMEM;
Jan 9, 2010
Jan 9, 2010
413
break;
Feb 22, 2010
Feb 22, 2010
414
}
Jan 9, 2010
Jan 9, 2010
415
}
Oct 1, 2008
Oct 1, 2008
416
}
Jan 9, 2010
Jan 9, 2010
417
May 28, 2012
May 28, 2012
418
if (closeconn || vpninfo->no_http_keepalive)
Jun 9, 2012
Jun 9, 2012
419
openconnect_close_https(vpninfo, 0);
Feb 22, 2010
Feb 22, 2010
420
421
422
423
if (body)
body[done] = 0;
*body_ret = body;
Oct 1, 2008
Oct 1, 2008
424
425
426
return done;
}
Oct 28, 2012
Oct 28, 2012
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
static void add_common_headers(struct openconnect_info *vpninfo, struct oc_text_buf *buf)
{
struct vpn_option *opt;
buf_append(buf, "Host: %s\r\n", vpninfo->hostname);
buf_append(buf, "User-Agent: %s\r\n", vpninfo->useragent);
buf_append(buf, "Accept: */*\r\n");
buf_append(buf, "Accept-Encoding: identity\r\n");
if (vpninfo->cookies) {
buf_append(buf, "Cookie: ");
for (opt = vpninfo->cookies; opt; opt = opt->next)
buf_append(buf, "%s=%s%s", opt->option,
opt->value, opt->next ? "; " : "\r\n");
}
buf_append(buf, "X-Transcend-Version: 1\r\n");
Oct 28, 2012
Oct 28, 2012
443
444
buf_append(buf, "X-Aggregate-Auth: 1\r\n");
buf_append(buf, "X-AnyConnect-Platform: %s\r\n", vpninfo->platname);
Oct 28, 2012
Oct 28, 2012
445
446
}
Oct 5, 2008
Oct 5, 2008
447
static int fetch_config(struct openconnect_info *vpninfo, char *fu, char *bu,
Oct 4, 2008
Oct 4, 2008
448
char *server_sha1)
Oct 2, 2008
Oct 2, 2008
449
{
Oct 28, 2012
Oct 28, 2012
450
struct oc_text_buf *buf;
Feb 22, 2010
Feb 22, 2010
451
char *config_buf = NULL;
Oct 2, 2008
Oct 2, 2008
452
int result, buflen;
May 29, 2012
May 29, 2012
453
454
unsigned char local_sha1_bin[SHA1_SIZE];
char local_sha1_ascii[(SHA1_SIZE * 2)+1];
Oct 2, 2008
Oct 2, 2008
455
456
int i;
Jun 5, 2012
Jun 5, 2012
457
458
459
460
461
462
463
if (openconnect_open_https(vpninfo)) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open HTTPS connection to %s\n"),
vpninfo->hostname);
return -EINVAL;
}
Oct 28, 2012
Oct 28, 2012
464
465
buf = buf_alloc();
buf_append(buf, "GET %s%s HTTP/1.1\r\n", fu, bu);
Oct 28, 2012
Oct 28, 2012
466
467
add_common_headers(vpninfo, buf);
buf_append(buf, "\r\n");
Oct 28, 2012
Oct 28, 2012
468
469
470
if (buf_error(buf))
return buf_free(buf);
Oct 2, 2008
Oct 2, 2008
471
Oct 28, 2012
Oct 28, 2012
472
if (openconnect_SSL_write(vpninfo, buf->data, buf->pos) != buf->pos) {
May 28, 2012
May 28, 2012
473
474
vpn_progress(vpninfo, PRG_ERR,
_("Failed to send GET request for new config\n"));
Oct 28, 2012
Oct 28, 2012
475
buf_free(buf);
May 28, 2012
May 28, 2012
476
477
return -EIO;
}
Oct 28, 2012
Oct 28, 2012
478
buf_free(buf);
Oct 2, 2008
Oct 2, 2008
479
Feb 22, 2010
Feb 22, 2010
480
buflen = process_http_response(vpninfo, &result, NULL, &config_buf);
Oct 2, 2008
Oct 2, 2008
481
482
483
484
485
if (buflen < 0) {
/* We'll already have complained about whatever offended us */
return -EINVAL;
}
Feb 22, 2010
Feb 22, 2010
486
487
if (result != 200) {
free(config_buf);
Oct 2, 2008
Oct 2, 2008
488
return -EINVAL;
Feb 22, 2010
Feb 22, 2010
489
}
Apr 9, 2009
Apr 9, 2009
490
May 29, 2012
May 29, 2012
491
openconnect_sha1(local_sha1_bin, config_buf, buflen);
Oct 2, 2008
Oct 2, 2008
492
May 29, 2012
May 29, 2012
493
for (i = 0; i < SHA1_SIZE; i++)
Oct 2, 2008
Oct 2, 2008
494
495
496
sprintf(&local_sha1_ascii[i*2], "%02x", local_sha1_bin[i]);
if (strcasecmp(server_sha1, local_sha1_ascii)) {
Sep 22, 2011
Sep 22, 2011
497
498
vpn_progress(vpninfo, PRG_ERR,
_("Downloaded config file did not match intended SHA1\n"));
Feb 22, 2010
Feb 22, 2010
499
free(config_buf);
Oct 2, 2008
Oct 2, 2008
500
501
502
return -EINVAL;
}
Jun 27, 2011
Jun 27, 2011
503
result = vpninfo->write_new_config(vpninfo->cbdata, config_buf, buflen);
Feb 22, 2010
Feb 22, 2010
504
505
free(config_buf);
return result;
Oct 2, 2008
Oct 2, 2008
506
}
Oct 4, 2008
Oct 4, 2008
507
Aug 4, 2009
Aug 4, 2009
508
static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int buflen)
Jul 20, 2009
Jul 20, 2009
509
510
{
char fname[16];
Feb 22, 2010
Feb 22, 2010
511
int fd, ret;
Jul 20, 2009
Jul 20, 2009
512
Nov 21, 2010
Nov 21, 2010
513
if (!vpninfo->uid_csd_given && !vpninfo->csd_wrapper) {
Jun 27, 2011
Jun 27, 2011
514
vpn_progress(vpninfo, PRG_ERR,
Sep 22, 2011
Sep 22, 2011
515
516
_("Error: Server asked us to download and run a 'Cisco Secure Desktop' trojan.\n"
"This facility is disabled by default for security reasons, so you may wish to enable it."));
Mar 11, 2010
Mar 11, 2010
517
return -EPERM;
Sep 21, 2009
Sep 21, 2009
518
519
}
Nov 5, 2009
Nov 5, 2009
520
#ifndef __linux__
Jun 27, 2011
Jun 27, 2011
521
vpn_progress(vpninfo, PRG_INFO,
Sep 22, 2011
Sep 22, 2011
522
_("Trying to run Linux CSD trojan script."));
Nov 5, 2009
Nov 5, 2009
523
524
#endif
Jul 20, 2009
Jul 20, 2009
525
526
527
528
sprintf(fname, "/tmp/csdXXXXXX");
fd = mkstemp(fname);
if (fd < 0) {
int err = -errno;
Sep 22, 2011
Sep 22, 2011
529
530
531
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open temporary CSD script file: %s\n"),
strerror(errno));
Jul 20, 2009
Jul 20, 2009
532
533
return err;
}
Feb 22, 2010
Feb 22, 2010
534
May 12, 2012
May 12, 2012
535
ret = proxy_write(vpninfo, fd, (void *)buf, buflen);
Feb 22, 2010
Feb 22, 2010
536
if (ret) {
Sep 22, 2011
Sep 22, 2011
537
538
vpn_progress(vpninfo, PRG_ERR,
_("Failed to write temporary CSD script file: %s\n"),
Sep 26, 2012
Sep 26, 2012
539
strerror(-ret));
Feb 22, 2010
Feb 22, 2010
540
541
return ret;
}
Aug 7, 2009
Aug 7, 2009
542
fchmod(fd, 0755);
Aug 4, 2009
Aug 4, 2009
543
close(fd);
Aug 4, 2009
Aug 4, 2009
544
Jul 20, 2009
Jul 20, 2009
545
if (!fork()) {
May 29, 2012
May 29, 2012
546
547
char scertbuf[MD5_SIZE * 2 + 1];
char ccertbuf[MD5_SIZE * 2 + 1];
Aug 4, 2009
Aug 4, 2009
548
549
550
char *csd_argv[32];
int i = 0;
Jul 12, 2012
Jul 12, 2012
551
if (vpninfo->uid_csd_given && vpninfo->uid_csd != getuid()) {
Aug 7, 2009
Aug 7, 2009
552
553
struct passwd *pw;
Aug 21, 2009
Aug 21, 2009
554
if (setuid(vpninfo->uid_csd)) {
Apr 19, 2012
Apr 19, 2012
555
556
fprintf(stderr, _("Failed to set uid %ld\n"),
(long)vpninfo->uid_csd);
Aug 7, 2009
Aug 7, 2009
557
558
exit(1);
}
Aug 21, 2009
Aug 21, 2009
559
if (!(pw = getpwuid(vpninfo->uid_csd))) {
Apr 19, 2012
Apr 19, 2012
560
561
fprintf(stderr, _("Invalid user uid=%ld\n"),
(long)vpninfo->uid_csd);
Aug 7, 2009
Aug 7, 2009
562
563
564
exit(1);
}
setenv("HOME", pw->pw_dir, 1);
Jan 5, 2010
Jan 5, 2010
565
if (chdir(pw->pw_dir)) {
Sep 22, 2011
Sep 22, 2011
566
fprintf(stderr, _("Failed to change to CSD home directory '%s': %s\n"),
Jan 5, 2010
Jan 5, 2010
567
568
569
pw->pw_dir, strerror(errno));
exit(1);
}
Aug 7, 2009
Aug 7, 2009
570
}
Jul 12, 2012
Jul 12, 2012
571
if (getuid() == 0 && !vpninfo->csd_wrapper) {
Sep 22, 2011
Sep 22, 2011
572
573
574
fprintf(stderr, _("Warning: you are running insecure "
"CSD code with root privileges\n"
"\t Use command line option \"--csd-user\"\n"));
Aug 7, 2009
Aug 7, 2009
575
}
Jul 12, 2012
Jul 12, 2012
576
if (vpninfo->uid_csd_given == 2) {
Mar 11, 2010
Mar 11, 2010
577
578
579
580
/* The NM tool really needs not to get spurious output
on stdout, which the CSD trojan spews. */
dup2(2, 1);
}
Nov 21, 2010
Nov 21, 2010
581
582
if (vpninfo->csd_wrapper)
csd_argv[i++] = vpninfo->csd_wrapper;
Aug 4, 2009
Aug 4, 2009
583
csd_argv[i++] = fname;
Sep 15, 2011
Sep 15, 2011
584
csd_argv[i++]= (char *)"-ticket";
Jan 5, 2010
Jan 5, 2010
585
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->csd_ticket) == -1)
Oct 28, 2012
Oct 28, 2012
586
goto out;
Sep 15, 2011
Sep 15, 2011
587
588
589
csd_argv[i++]= (char *)"-stub";
csd_argv[i++]= (char *)"\"0\"";
csd_argv[i++]= (char *)"-group";
Jan 5, 2010
Jan 5, 2010
590
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->authgroup?:"") == -1)
Oct 28, 2012
Oct 28, 2012
591
goto out;
Jan 5, 2010
Jan 5, 2010
592
May 29, 2012
May 29, 2012
593
594
595
openconnect_local_cert_md5(vpninfo, ccertbuf);
scertbuf[0] = 0;
get_cert_md5_fingerprint(vpninfo, vpninfo->peer_cert, scertbuf);
Sep 15, 2011
Sep 15, 2011
596
csd_argv[i++]= (char *)"-certhash";
Jan 5, 2010
Jan 5, 2010
597
if (asprintf(&csd_argv[i++], "\"%s:%s\"", scertbuf, ccertbuf) == -1)
Oct 28, 2012
Oct 28, 2012
598
goto out;
May 29, 2012
May 29, 2012
599
Sep 15, 2011
Sep 15, 2011
600
csd_argv[i++]= (char *)"-url";
Jan 5, 2010
Jan 5, 2010
601
if (asprintf(&csd_argv[i++], "\"https://%s%s\"", vpninfo->hostname, vpninfo->csd_starturl) == -1)
Oct 28, 2012
Oct 28, 2012
602
goto out;
Jul 12, 2012
Jul 12, 2012
603
Sep 15, 2011
Sep 15, 2011
604
csd_argv[i++]= (char *)"-langselen";
Aug 4, 2009
Aug 4, 2009
605
606
csd_argv[i++] = NULL;
Oct 28, 2012
Oct 28, 2012
607
608
609
610
611
if (setenv("CSD_TOKEN", vpninfo->csd_token, 1))
goto out;
if (setenv("CSD_HOSTNAME", vpninfo->hostname, 1))
goto out;
Nov 21, 2010
Nov 21, 2010
612
execv(csd_argv[0], csd_argv);
Oct 28, 2012
Oct 28, 2012
613
614
out:
Sep 22, 2011
Sep 22, 2011
615
616
vpn_progress(vpninfo, PRG_ERR,
_("Failed to exec CSD script %s\n"), csd_argv[0]);
Aug 4, 2009
Aug 4, 2009
617
exit(1);
Jul 20, 2009
Jul 20, 2009
618
619
620
621
}
free(vpninfo->csd_stuburl);
vpninfo->csd_stuburl = NULL;
Oct 28, 2012
Oct 28, 2012
622
free(vpninfo->urlpath);
Aug 4, 2009
Aug 4, 2009
623
624
vpninfo->urlpath = strdup(vpninfo->csd_waiturl +
(vpninfo->csd_waiturl[0] == '/' ? 1 : 0));
Oct 28, 2012
Oct 28, 2012
625
free(vpninfo->csd_waiturl);
Jul 20, 2009
Jul 20, 2009
626
vpninfo->csd_waiturl = NULL;
Aug 4, 2009
Aug 4, 2009
627
vpninfo->csd_scriptname = strdup(fname);
Aug 4, 2009
Aug 4, 2009
628
Nov 6, 2009
Nov 6, 2009
629
630
http_add_cookie(vpninfo, "sdesktop", vpninfo->csd_token);
Jul 20, 2009
Jul 20, 2009
631
632
633
return 0;
}
Mar 9, 2011
Mar 9, 2011
634
635
int internal_parse_url(char *url, char **res_proto, char **res_host,
int *res_port, char **res_path, int default_port)
Dec 25, 2009
Dec 25, 2009
636
637
638
639
640
641
{
char *proto = url;
char *host, *path, *port_str;
int port;
host = strstr(url, "://");
Jan 1, 2010
Jan 1, 2010
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
if (host) {
*host = 0;
host += 3;
if (!strcasecmp(proto, "https"))
port = 443;
else if (!strcasecmp(proto, "http"))
port = 80;
else if (!strcasecmp(proto, "socks") ||
!strcasecmp(proto, "socks4") ||
!strcasecmp(proto, "socks5"))
port = 1080;
else
return -EPROTONOSUPPORT;
} else {
if (default_port) {
proto = NULL;
port = default_port;
host = url;
} else
return -EINVAL;
}
Dec 25, 2009
Dec 25, 2009
664
665
path = strchr(host, '/');
May 12, 2010
May 12, 2010
666
if (path)
Dec 25, 2009
Dec 25, 2009
667
668
669
670
671
672
673
674
675
676
677
678
679
680
*(path++) = 0;
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;
}
}
if (res_proto)
Jan 1, 2010
Jan 1, 2010
681
*res_proto = proto ? strdup(proto) : NULL;
Dec 25, 2009
Dec 25, 2009
682
683
684
685
686
if (res_host)
*res_host = strdup(host);
if (res_port)
*res_port = port;
if (res_path)
May 12, 2010
May 12, 2010
687
688
689
*res_path = (path && *path) ? strdup(path) : NULL;
/* Undo the damage we did to the original string */
May 13, 2012
May 13, 2012
690
691
if (port_str)
*(port_str) = ':';
May 12, 2010
May 12, 2010
692
693
694
695
if (path)
*(path - 1) = '/';
if (proto)
*(host - 3) = ':';
Dec 25, 2009
Dec 25, 2009
696
697
698
return 0;
}
Oct 27, 2012
Oct 27, 2012
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
static void clear_cookies(struct openconnect_info *vpninfo)
{
struct vpn_option *opt, *next;
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,...})
*/
static int handle_redirect(struct openconnect_info *vpninfo)
{
Oct 28, 2012
Oct 28, 2012
719
720
vpninfo->redirect_type = REDIR_TYPE_LOCAL;
Oct 27, 2012
Oct 27, 2012
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
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) {
free(vpninfo->hostname);
vpninfo->hostname = host;
vpninfo->port = port;
/* Kill the existing connection, and a new one will happen */
free(vpninfo->peer_addr);
vpninfo->peer_addr = NULL;
openconnect_close_https(vpninfo, 0);
clear_cookies(vpninfo);
Oct 28, 2012
Oct 28, 2012
750
vpninfo->redirect_type = REDIR_TYPE_NEWHOST;
Oct 27, 2012
Oct 27, 2012
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
} else
free(host);
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
return 0;
} 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 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;
} 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;
}
}
Oct 28, 2012
Oct 28, 2012
800
801
802
803
804
805
806
807
808
809
/* 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
*
* Return value:
Jan 24, 2009
Jan 24, 2009
810
* < 0, on error
Oct 28, 2012
Oct 28, 2012
811
* >=0, on success, indicating the length of the data in *form_buf
Jan 24, 2009
Jan 24, 2009
812
*/
Oct 28, 2012
Oct 28, 2012
813
814
static int do_https_request(struct openconnect_info *vpninfo, const char *method,
const char *request_body_type, const char *request_body,
Oct 28, 2012
Oct 28, 2012
815
char **form_buf, int fetch_redirect)
Oct 1, 2008
Oct 1, 2008
816
{
Oct 28, 2012
Oct 28, 2012
817
struct oc_text_buf *buf;
Oct 1, 2008
Oct 1, 2008
818
int result, buflen;
Oct 15, 2012
Oct 15, 2012
819
Oct 1, 2008
Oct 1, 2008
820
retry:
Oct 28, 2012
Oct 28, 2012
821
822
vpninfo->redirect_type = REDIR_TYPE_NONE;
Oct 28, 2012
Oct 28, 2012
823
824
825
if (*form_buf) {
free(*form_buf);
*form_buf = NULL;
Nov 24, 2010
Nov 24, 2010
826
}
May 28, 2012
May 28, 2012
827
if (openconnect_open_https(vpninfo)) {
Sep 22, 2011
Sep 22, 2011
828
829
830
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open HTTPS connection to %s\n"),
vpninfo->hostname);
Oct 5, 2008
Oct 5, 2008
831
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
832
833
834
}
/*
Apr 9, 2009
Apr 9, 2009
835
836
* It would be nice to use cURL for this, but we really need to guarantee
* that we'll be using OpenSSL (for the TPM stuff), and it doesn't seem
Oct 1, 2008
Oct 1, 2008
837
838
* to have any way to let us provide our own socket read/write functions.
* We can only provide a socket _open_ function. Which would require having
Apr 9, 2009
Apr 9, 2009
839
* a socketpair() and servicing the "other" end of it.
Oct 1, 2008
Oct 1, 2008
840
841
842
*
* So we process the HTTP for ourselves...
*/
Oct 28, 2012
Oct 28, 2012
843
844
buf = buf_alloc();
buf_append(buf, "%s /%s HTTP/1.1\r\n", method, vpninfo->urlpath ?: "");
Oct 28, 2012
Oct 28, 2012
845
add_common_headers(vpninfo, buf);
Oct 1, 2008
Oct 1, 2008
846
Oct 1, 2008
Oct 1, 2008
847
if (request_body_type) {
Oct 28, 2012
Oct 28, 2012
848
849
buf_append(buf, "Content-Type: %s\r\n", request_body_type);
buf_append(buf, "Content-Length: %zd\r\n", strlen(request_body));
Oct 1, 2008
Oct 1, 2008
850
}
Oct 28, 2012
Oct 28, 2012
851
852
buf_append(buf, "\r\n");
Oct 1, 2008
Oct 1, 2008
853
if (request_body_type)
Oct 28, 2012
Oct 28, 2012
854
buf_append(buf, "%s", request_body);
Oct 1, 2008
Oct 1, 2008
855
Dec 23, 2009
Dec 23, 2009
856
if (vpninfo->port == 443)
Jun 27, 2011
Jun 27, 2011
857
vpn_progress(vpninfo, PRG_INFO, "%s https://%s/%s\n",
Sep 22, 2011
Sep 22, 2011
858
859
method, vpninfo->hostname,
vpninfo->urlpath ?: "");
Dec 23, 2009
Dec 23, 2009
860
else
Jun 27, 2011
Jun 27, 2011
861
vpn_progress(vpninfo, PRG_INFO, "%s https://%s:%d/%s\n",
Sep 22, 2011
Sep 22, 2011
862
863
method, vpninfo->hostname, vpninfo->port,
vpninfo->urlpath ?: "");
Apr 1, 2009
Apr 1, 2009
864
Oct 28, 2012
Oct 28, 2012
865
866
867
868
869
if (buf_error(buf))
return buf_free(buf);
result = openconnect_SSL_write(vpninfo, buf->data, buf->pos);
buf_free(buf);
May 12, 2012
May 12, 2012
870
871
if (result < 0)
return result;
Oct 1, 2008
Oct 1, 2008
872
Oct 28, 2012
Oct 28, 2012
873
buflen = process_http_response(vpninfo, &result, NULL, form_buf);
Oct 1, 2008
Oct 1, 2008
874
875
if (buflen < 0) {
/* We'll already have complained about whatever offended us */
May 13, 2012
May 13, 2012
876
return buflen;
Oct 1, 2008
Oct 1, 2008
877
878
879
}
if (result != 200 && vpninfo->redirect_url) {
Oct 27, 2012
Oct 27, 2012
880
result = handle_redirect(vpninfo);
Oct 28, 2012
Oct 28, 2012
881
882
883
if (result == 0) {
if (!fetch_redirect)
return 0;
Oct 1, 2008
Oct 1, 2008
884
goto retry;
Oct 28, 2012
Oct 28, 2012
885
}
Oct 28, 2012
Oct 28, 2012
886
goto out;
Oct 1, 2008
Oct 1, 2008
887
}
Oct 28, 2012
Oct 28, 2012
888
if (!*form_buf || result != 200) {
Jun 27, 2011
Jun 27, 2011
889
vpn_progress(vpninfo, PRG_ERR,
Sep 22, 2011
Sep 22, 2011
890
891
_("Unexpected %d result from server\n"),
result);
Oct 28, 2012
Oct 28, 2012
892
893
894
895
896
897
898
899
900
901
902
903
result = -EINVAL;
goto out;
}
return buflen;
out:
free(*form_buf);
*form_buf = NULL;
return result;
}
Oct 28, 2012
Oct 28, 2012
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
/* Return value:
* < 0, if the data is unrecognized
* = 0, if the page contains an XML document
* = 1, if the page is a wait/refresh HTML page
*/
static int check_response_type(struct openconnect_info *vpninfo, char *form_buf)
{
if (strncmp(form_buf, "<?xml", 5)) {
/* Not XML? Perhaps it's HTML with a refresh... */
if (strcasestr(form_buf, "http-equiv=\"refresh\""))
return 1;
vpn_progress(vpninfo, PRG_ERR,
_("Unknown response from server\n"));
return -EINVAL;
}
return 0;
}
Oct 28, 2012
Oct 28, 2012
922
923
924
925
926
927
928
929
930
/* Return value:
* < 0, on error
* > 0, no cookie (user cancel)
* = 0, obtained cookie
*/
int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
{
struct vpn_option *opt;
char *form_buf = NULL;
Oct 28, 2012
Oct 28, 2012
931
932
struct oc_auth_form *form = NULL;
int result, buflen, tries;
Oct 28, 2012
Oct 28, 2012
933
char request_body[2048];
Oct 28, 2012
Oct 28, 2012
934
935
936
const char *request_body_type = "application/x-www-form-urlencoded";
const char *method = "POST";
int xmlpost = 0;
Oct 28, 2012
Oct 28, 2012
937
Oct 28, 2012
Oct 28, 2012
938
/* Step 1: Unlock software token (if applicable) */
Oct 28, 2012
Oct 28, 2012
939
940
941
942
if (vpninfo->use_stoken) {
result = prepare_stoken(vpninfo);
if (result)
return result;
Apr 4, 2010
Apr 4, 2010
943
}
Oct 28, 2012
Oct 28, 2012
944
Oct 28, 2012
Oct 28, 2012
945
946
947
948
949
950
951
952
953
954
955
956
/*
* Step 2: Probe for XML POST compatibility
*
* This can get stuck in a redirect loop, so give up after any of:
*
* a) HTTP error (e.g. 400 Bad Request)
* b) Same-host redirect (e.g. Location: /foo/bar)
* c) Three redirects without seeing a plausible login form
*/
result = xmlpost_initial_req(vpninfo, request_body, sizeof(request_body));
if (result < 0)
return result;
Oct 28, 2012
Oct 28, 2012
957
Oct 28, 2012
Oct 28, 2012
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
for (tries = 0; ; tries++) {
if (tries == 3)
break;
buflen = do_https_request(vpninfo, method, request_body_type, request_body,
&form_buf, 0);
if (buflen == -EINVAL)
break;
if (buflen < 0)
return buflen;
if (vpninfo->redirect_type == REDIR_TYPE_LOCAL)
break;
else if (vpninfo->redirect_type != REDIR_TYPE_NONE)
continue;
result = parse_xml_response(vpninfo, form_buf, &form);
if (result < 0)
break;
xmlpost = 1;
vpn_progress(vpninfo, PRG_INFO, _("XML POST enabled\n"));
break;
}
/* Step 3: Fetch and parse the login form, if not using XML POST */
if (!xmlpost) {
buflen = do_https_request(vpninfo, "GET", NULL, NULL, &form_buf, 0);
if (buflen < 0)
return buflen;
result = parse_xml_response(vpninfo, form_buf, &form);
if (result < 0) {
Feb 22, 2010
Feb 22, 2010
990
free(form_buf);
Jul 20, 2009
Jul 20, 2009
991
return result;
Feb 22, 2010
Feb 22, 2010
992
}
Feb 4, 2013
Feb 4, 2013
993
994
995
996
if (form->action) {
vpninfo->redirect_url = strdup(form->action);
handle_redirect(vpninfo);
}
Jul 20, 2009
Jul 20, 2009
997
}
Oct 28, 2012
Oct 28, 2012
998
999
1000
/* Step 4: Run the CSD trojan, if applicable */
if (vpninfo->csd_starturl) {