Skip to content

Latest commit

 

History

History
1207 lines (1067 loc) · 31.2 KB

http.c

File metadata and controls

1207 lines (1067 loc) · 31.2 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 1, 2008
Oct 1, 2008
38
Mar 9, 2011
Mar 9, 2011
39
#include "openconnect-internal.h"
Oct 1, 2008
Oct 1, 2008
40
May 12, 2012
May 12, 2012
41
42
43
44
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
45
Aug 4, 2009
Aug 4, 2009
46
#define MAX_BUF_LEN 131072
Oct 1, 2008
Oct 1, 2008
47
/*
Apr 9, 2009
Apr 9, 2009
48
* We didn't really want to have to do this for ourselves -- one might have
Oct 1, 2008
Oct 1, 2008
49
50
51
52
53
54
* 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
55
56
static int http_add_cookie(struct openconnect_info *vpninfo,
const char *option, const char *value)
Nov 6, 2009
Nov 6, 2009
57
58
59
60
61
62
{
struct vpn_option *new, **this;
if (*value) {
new = malloc(sizeof(*new));
if (!new) {
Sep 22, 2011
Sep 22, 2011
63
64
vpn_progress(vpninfo, PRG_ERR,
_("No memory for allocating cookies\n"));
Nov 6, 2009
Nov 6, 2009
65
66
67
68
69
return -ENOMEM;
}
new->next = NULL;
new->option = strdup(option);
new->value = strdup(value);
Nov 6, 2009
Nov 6, 2009
70
71
72
73
74
75
if (!new->option || !new->value) {
free(new->option);
free(new->value);
free(new);
return -ENOMEM;
}
Nov 6, 2009
Nov 6, 2009
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
} 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
102
103
104
#define BODY_HTTP10 -1
#define BODY_CHUNKED -2
Oct 5, 2008
Oct 5, 2008
105
106
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
107
char **body_ret)
Oct 1, 2008
Oct 1, 2008
108
{
Aug 4, 2009
Aug 4, 2009
109
char buf[MAX_BUF_LEN];
Feb 22, 2010
Feb 22, 2010
110
char *body = NULL;
Jan 9, 2010
Jan 9, 2010
111
int bodylen = BODY_HTTP10;
Oct 1, 2008
Oct 1, 2008
112
int done = 0;
Jan 9, 2010
Jan 9, 2010
113
int closeconn = 0;
Oct 1, 2008
Oct 1, 2008
114
115
int i;
Jan 3, 2010
Jan 3, 2010
116
cont:
May 12, 2012
May 12, 2012
117
if (openconnect_SSL_gets(vpninfo, buf, sizeof(buf)) < 0) {
Sep 22, 2011
Sep 22, 2011
118
119
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching HTTPS response\n"));
Oct 5, 2008
Oct 5, 2008
120
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
121
122
}
Jan 9, 2010
Jan 9, 2010
123
if (!strncmp(buf, "HTTP/1.0 ", 9))
Oct 1, 2008
Oct 1, 2008
124
closeconn = 1;
Jan 9, 2010
Jan 9, 2010
125
126
if ((!closeconn && strncmp(buf, "HTTP/1.1 ", 9)) || !(*result = atoi(buf+9))) {
Sep 22, 2011
Sep 22, 2011
127
128
vpn_progress(vpninfo, PRG_ERR,
_("Failed to parse HTTP response '%s'\n"), buf);
Oct 1, 2008
Oct 1, 2008
129
130
131
return -EINVAL;
}
Jun 27, 2011
Jun 27, 2011
132
vpn_progress(vpninfo, (*result==200)?PRG_TRACE:PRG_INFO,
Sep 22, 2011
Sep 22, 2011
133
_("Got HTTP response: %s\n"), buf);
Oct 1, 2008
Oct 1, 2008
134
135
/* Eat headers... */
May 12, 2012
May 12, 2012
136
while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
Oct 1, 2008
Oct 1, 2008
137
138
139
char *colon;
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
140
141
vpn_progress(vpninfo, PRG_ERR,
_("Error processing HTTP response\n"));
Oct 1, 2008
Oct 1, 2008
142
143
144
145
return -EINVAL;
}
colon = strchr(buf, ':');
if (!colon) {
Sep 22, 2011
Sep 22, 2011
146
147
vpn_progress(vpninfo, PRG_ERR,
_("Ignoring unknown HTTP response line '%s'\n"), buf);
Oct 1, 2008
Oct 1, 2008
148
149
150
151
152
153
continue;
}
*(colon++) = 0;
if (*colon == ' ')
colon++;
Aug 7, 2010
Aug 7, 2010
154
155
156
157
/* 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
158
159
const char *print_equals;
char *equals = strchr(colon, '=');
Aug 7, 2010
Aug 7, 2010
160
161
162
163
164
165
int ret;
if (semicolon)
*semicolon = 0;
if (!equals) {
Sep 22, 2011
Sep 22, 2011
166
167
vpn_progress(vpninfo, PRG_ERR,
_("Invalid cookie offered: %s\n"), buf);
Aug 7, 2010
Aug 7, 2010
168
169
170
171
172
return -EINVAL;
}
*(equals++) = 0;
print_equals = equals;
Nov 30, 2010
Nov 30, 2010
173
174
175
/* 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
176
print_equals = _("<elided>");
Jun 27, 2011
Jun 27, 2011
177
vpn_progress(vpninfo, PRG_TRACE, "%s: %s=%s%s%s\n",
Sep 22, 2011
Sep 22, 2011
178
179
buf, colon, print_equals, semicolon?";":"",
semicolon?(semicolon+1):"");
Aug 7, 2010
Aug 7, 2010
180
Sep 25, 2011
Sep 25, 2011
181
182
183
184
185
186
187
/* 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
188
189
190
191
ret = http_add_cookie(vpninfo, colon, equals);
if (ret)
return ret;
} else {
Jun 27, 2011
Jun 27, 2011
192
vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
Aug 7, 2010
Aug 7, 2010
193
194
}
Jan 9, 2010
Jan 9, 2010
195
196
197
if (!strcasecmp(buf, "Connection")) {
if (!strcasecmp(colon, "Close"))
closeconn = 1;
Feb 28, 2010
Feb 28, 2010
198
199
200
201
202
203
#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
204
205
else if (!strcasecmp(colon, "Keep-Alive"))
closeconn = 0;
Feb 28, 2010
Feb 28, 2010
206
#endif
Jan 9, 2010
Jan 9, 2010
207
}
Jan 9, 2010
Jan 9, 2010
208
if (!strcasecmp(buf, "Location")) {
Oct 1, 2008
Oct 1, 2008
209
210
211
212
vpninfo->redirect_url = strdup(colon);
if (!vpninfo->redirect_url)
return -ENOMEM;
}
Jan 9, 2010
Jan 9, 2010
213
if (!strcasecmp(buf, "Content-Length")) {
Oct 1, 2008
Oct 1, 2008
214
bodylen = atoi(colon);
Feb 22, 2010
Feb 22, 2010
215
if (bodylen < 0) {
Sep 22, 2011
Sep 22, 2011
216
217
218
vpn_progress(vpninfo, PRG_ERR,
_("Response body has negative size (%d)\n"),
bodylen);
Oct 1, 2008
Oct 1, 2008
219
220
221
return -EINVAL;
}
}
Jan 9, 2010
Jan 9, 2010
222
223
if (!strcasecmp(buf, "Transfer-Encoding")) {
if (!strcasecmp(colon, "chunked"))
Jan 9, 2010
Jan 9, 2010
224
bodylen = BODY_CHUNKED;
Oct 1, 2008
Oct 1, 2008
225
else {
Sep 22, 2011
Sep 22, 2011
226
227
228
vpn_progress(vpninfo, PRG_ERR,
_("Unknown Transfer-Encoding: %s\n"),
colon);
Oct 1, 2008
Oct 1, 2008
229
230
231
232
233
234
235
236
237
238
239
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
240
/* Now the body, if there is one */
Sep 22, 2011
Sep 22, 2011
241
242
243
244
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
245
Oct 1, 2008
Oct 1, 2008
246
247
/* If we were given Content-Length, it's nice and easy... */
if (bodylen > 0) {
Feb 22, 2010
Feb 22, 2010
248
249
250
body = malloc(bodylen + 1);
if (!body)
return -ENOMEM;
Oct 1, 2008
Oct 1, 2008
251
while (done < bodylen) {
May 12, 2012
May 12, 2012
252
i = openconnect_SSL_read(vpninfo, body + done, bodylen - done);
Oct 1, 2008
Oct 1, 2008
253
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
254
255
vpn_progress(vpninfo, PRG_ERR,
_("Error reading HTTP response body\n"));
Feb 22, 2010
Feb 22, 2010
256
free(body);
Oct 1, 2008
Oct 1, 2008
257
258
259
260
return -EINVAL;
}
done += i;
}
Jan 9, 2010
Jan 9, 2010
261
262
} else if (bodylen == BODY_CHUNKED) {
/* ... else, chunked */
May 12, 2012
May 12, 2012
263
while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
Jan 9, 2010
Jan 9, 2010
264
int chunklen, lastchunk = 0;
Oct 1, 2008
Oct 1, 2008
265
266
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
267
268
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching chunk header\n"));
May 13, 2012
May 13, 2012
269
return i;
Jan 9, 2010
Jan 9, 2010
270
271
272
273
274
275
}
chunklen = strtol(buf, NULL, 16);
if (!chunklen) {
lastchunk = 1;
goto skip;
}
Feb 22, 2010
Feb 22, 2010
276
277
278
body = realloc(body, done + chunklen + 1);
if (!body)
return -ENOMEM;
Jan 9, 2010
Jan 9, 2010
279
while (chunklen) {
May 12, 2012
May 12, 2012
280
i = openconnect_SSL_read(vpninfo, body + done, chunklen);
Jan 9, 2010
Jan 9, 2010
281
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
282
283
vpn_progress(vpninfo, PRG_ERR,
_("Error reading HTTP response body\n"));
Feb 22, 2010
Feb 22, 2010
284
free(body);
Jan 9, 2010
Jan 9, 2010
285
286
287
288
289
290
return -EINVAL;
}
chunklen -= i;
done += i;
}
skip:
May 12, 2012
May 12, 2012
291
if ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
Jan 9, 2010
Jan 9, 2010
292
if (i < 0) {
Sep 22, 2011
Sep 22, 2011
293
294
vpn_progress(vpninfo, PRG_ERR,
_("Error fetching HTTP response body\n"));
Jan 9, 2010
Jan 9, 2010
295
} else {
Sep 22, 2011
Sep 22, 2011
296
297
298
vpn_progress(vpninfo, PRG_ERR,
_("Error in chunked decoding. Expected '', got: '%s'"),
buf);
Jan 9, 2010
Jan 9, 2010
299
}
Feb 22, 2010
Feb 22, 2010
300
free(body);
Jan 9, 2010
Jan 9, 2010
301
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
302
}
Feb 22, 2010
Feb 22, 2010
303
Jan 9, 2010
Jan 9, 2010
304
305
306
307
308
if (lastchunk)
break;
}
} else if (bodylen == BODY_HTTP10) {
if (!closeconn) {
Sep 22, 2011
Sep 22, 2011
309
310
vpn_progress(vpninfo, PRG_ERR,
_("Cannot receive HTTP 1.0 body without closing connection\n"));
Oct 1, 2008
Oct 1, 2008
311
312
313
return -EINVAL;
}
Feb 22, 2010
Feb 22, 2010
314
/* HTTP 1.0 response. Just eat all we can in 16KiB chunks */
Jan 9, 2010
Jan 9, 2010
315
while (1) {
Feb 22, 2010
Feb 22, 2010
316
body = realloc(body, done + 16384);
Feb 22, 2010
Feb 22, 2010
317
318
if (!body)
return -ENOMEM;
May 12, 2012
May 12, 2012
319
320
321
322
323
324
325
326
327
328
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
329
body = realloc(body, done + 1);
Feb 22, 2010
Feb 22, 2010
330
331
if (!body)
return -ENOMEM;
Jan 9, 2010
Jan 9, 2010
332
break;
Feb 22, 2010
Feb 22, 2010
333
}
Jan 9, 2010
Jan 9, 2010
334
}
Oct 1, 2008
Oct 1, 2008
335
}
Jan 9, 2010
Jan 9, 2010
336
May 28, 2012
May 28, 2012
337
if (closeconn || vpninfo->no_http_keepalive)
Jun 9, 2012
Jun 9, 2012
338
openconnect_close_https(vpninfo, 0);
Feb 22, 2010
Feb 22, 2010
339
340
341
342
if (body)
body[done] = 0;
*body_ret = body;
Oct 1, 2008
Oct 1, 2008
343
344
345
return done;
}
Oct 5, 2008
Oct 5, 2008
346
static int fetch_config(struct openconnect_info *vpninfo, char *fu, char *bu,
Oct 4, 2008
Oct 4, 2008
347
char *server_sha1)
Oct 2, 2008
Oct 2, 2008
348
349
{
struct vpn_option *opt;
Aug 4, 2009
Aug 4, 2009
350
char buf[MAX_BUF_LEN];
Feb 22, 2010
Feb 22, 2010
351
char *config_buf = NULL;
Oct 2, 2008
Oct 2, 2008
352
int result, buflen;
May 29, 2012
May 29, 2012
353
354
unsigned char local_sha1_bin[SHA1_SIZE];
char local_sha1_ascii[(SHA1_SIZE * 2)+1];
Oct 2, 2008
Oct 2, 2008
355
356
int i;
Jun 5, 2012
Jun 5, 2012
357
358
359
360
361
362
363
if (openconnect_open_https(vpninfo)) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open HTTPS connection to %s\n"),
vpninfo->hostname);
return -EINVAL;
}
Oct 2, 2008
Oct 2, 2008
364
365
366
367
368
369
370
371
372
373
sprintf(buf, "GET %s%s HTTP/1.1\r\n", fu, bu);
sprintf(buf + strlen(buf), "Host: %s\r\n", vpninfo->hostname);
sprintf(buf + strlen(buf), "User-Agent: %s\r\n", vpninfo->useragent);
sprintf(buf + strlen(buf), "Accept: */*\r\n");
sprintf(buf + strlen(buf), "Accept-Encoding: identity\r\n");
if (vpninfo->cookies) {
sprintf(buf + strlen(buf), "Cookie: ");
for (opt = vpninfo->cookies; opt; opt = opt->next)
sprintf(buf + strlen(buf), "%s=%s%s", opt->option,
Apr 9, 2009
Apr 9, 2009
374
opt->value, opt->next ? "; " : "\r\n");
Oct 2, 2008
Oct 2, 2008
375
376
377
}
sprintf(buf + strlen(buf), "X-Transcend-Version: 1\r\n\r\n");
Jun 5, 2012
Jun 5, 2012
378
if (openconnect_SSL_write(vpninfo, buf, strlen(buf)) != strlen(buf)) {
May 28, 2012
May 28, 2012
379
380
381
382
vpn_progress(vpninfo, PRG_ERR,
_("Failed to send GET request for new config\n"));
return -EIO;
}
Oct 2, 2008
Oct 2, 2008
383
Feb 22, 2010
Feb 22, 2010
384
buflen = process_http_response(vpninfo, &result, NULL, &config_buf);
Oct 2, 2008
Oct 2, 2008
385
386
387
388
389
if (buflen < 0) {
/* We'll already have complained about whatever offended us */
return -EINVAL;
}
Feb 22, 2010
Feb 22, 2010
390
391
if (result != 200) {
free(config_buf);
Oct 2, 2008
Oct 2, 2008
392
return -EINVAL;
Feb 22, 2010
Feb 22, 2010
393
}
Apr 9, 2009
Apr 9, 2009
394
May 29, 2012
May 29, 2012
395
openconnect_sha1(local_sha1_bin, config_buf, buflen);
Oct 2, 2008
Oct 2, 2008
396
May 29, 2012
May 29, 2012
397
for (i = 0; i < SHA1_SIZE; i++)
Oct 2, 2008
Oct 2, 2008
398
399
400
sprintf(&local_sha1_ascii[i*2], "%02x", local_sha1_bin[i]);
if (strcasecmp(server_sha1, local_sha1_ascii)) {
Sep 22, 2011
Sep 22, 2011
401
402
vpn_progress(vpninfo, PRG_ERR,
_("Downloaded config file did not match intended SHA1\n"));
Feb 22, 2010
Feb 22, 2010
403
free(config_buf);
Oct 2, 2008
Oct 2, 2008
404
405
406
return -EINVAL;
}
Jun 27, 2011
Jun 27, 2011
407
result = vpninfo->write_new_config(vpninfo->cbdata, config_buf, buflen);
Feb 22, 2010
Feb 22, 2010
408
409
free(config_buf);
return result;
Oct 2, 2008
Oct 2, 2008
410
}
Oct 4, 2008
Oct 4, 2008
411
Aug 4, 2009
Aug 4, 2009
412
static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int buflen)
Jul 20, 2009
Jul 20, 2009
413
414
{
char fname[16];
Feb 22, 2010
Feb 22, 2010
415
int fd, ret;
Jul 20, 2009
Jul 20, 2009
416
Nov 21, 2010
Nov 21, 2010
417
if (!vpninfo->uid_csd_given && !vpninfo->csd_wrapper) {
Jun 27, 2011
Jun 27, 2011
418
vpn_progress(vpninfo, PRG_ERR,
Sep 22, 2011
Sep 22, 2011
419
420
_("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
421
return -EPERM;
Sep 21, 2009
Sep 21, 2009
422
423
}
Nov 5, 2009
Nov 5, 2009
424
#ifndef __linux__
Jun 27, 2011
Jun 27, 2011
425
vpn_progress(vpninfo, PRG_INFO,
Sep 22, 2011
Sep 22, 2011
426
_("Trying to run Linux CSD trojan script."));
Nov 5, 2009
Nov 5, 2009
427
428
#endif
Jul 20, 2009
Jul 20, 2009
429
430
431
432
sprintf(fname, "/tmp/csdXXXXXX");
fd = mkstemp(fname);
if (fd < 0) {
int err = -errno;
Sep 22, 2011
Sep 22, 2011
433
434
435
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open temporary CSD script file: %s\n"),
strerror(errno));
Jul 20, 2009
Jul 20, 2009
436
437
return err;
}
Feb 22, 2010
Feb 22, 2010
438
May 12, 2012
May 12, 2012
439
ret = proxy_write(vpninfo, fd, (void *)buf, buflen);
Feb 22, 2010
Feb 22, 2010
440
if (ret) {
Sep 22, 2011
Sep 22, 2011
441
442
443
vpn_progress(vpninfo, PRG_ERR,
_("Failed to write temporary CSD script file: %s\n"),
strerror(ret));
Feb 22, 2010
Feb 22, 2010
444
445
return ret;
}
Aug 7, 2009
Aug 7, 2009
446
fchmod(fd, 0755);
Aug 4, 2009
Aug 4, 2009
447
close(fd);
Aug 4, 2009
Aug 4, 2009
448
Jul 20, 2009
Jul 20, 2009
449
if (!fork()) {
May 29, 2012
May 29, 2012
450
451
char scertbuf[MD5_SIZE * 2 + 1];
char ccertbuf[MD5_SIZE * 2 + 1];
Aug 4, 2009
Aug 4, 2009
452
453
454
char *csd_argv[32];
int i = 0;
Aug 21, 2009
Aug 21, 2009
455
if (vpninfo->uid_csd != getuid()) {
Aug 7, 2009
Aug 7, 2009
456
457
struct passwd *pw;
Aug 21, 2009
Aug 21, 2009
458
if (setuid(vpninfo->uid_csd)) {
Apr 19, 2012
Apr 19, 2012
459
460
fprintf(stderr, _("Failed to set uid %ld\n"),
(long)vpninfo->uid_csd);
Aug 7, 2009
Aug 7, 2009
461
462
exit(1);
}
Aug 21, 2009
Aug 21, 2009
463
if (!(pw = getpwuid(vpninfo->uid_csd))) {
Apr 19, 2012
Apr 19, 2012
464
465
fprintf(stderr, _("Invalid user uid=%ld\n"),
(long)vpninfo->uid_csd);
Aug 7, 2009
Aug 7, 2009
466
467
468
exit(1);
}
setenv("HOME", pw->pw_dir, 1);
Jan 5, 2010
Jan 5, 2010
469
if (chdir(pw->pw_dir)) {
Sep 22, 2011
Sep 22, 2011
470
fprintf(stderr, _("Failed to change to CSD home directory '%s': %s\n"),
Jan 5, 2010
Jan 5, 2010
471
472
473
pw->pw_dir, strerror(errno));
exit(1);
}
Aug 7, 2009
Aug 7, 2009
474
}
Nov 21, 2010
Nov 21, 2010
475
if (vpninfo->uid_csd == 0 && !vpninfo->csd_wrapper) {
Sep 22, 2011
Sep 22, 2011
476
477
478
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
479
}
Mar 11, 2010
Mar 11, 2010
480
481
482
483
484
if (vpninfo->uid_csd_given == 2) {
/* 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
485
486
if (vpninfo->csd_wrapper)
csd_argv[i++] = vpninfo->csd_wrapper;
Aug 4, 2009
Aug 4, 2009
487
csd_argv[i++] = fname;
Sep 15, 2011
Sep 15, 2011
488
csd_argv[i++]= (char *)"-ticket";
Jan 5, 2010
Jan 5, 2010
489
490
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->csd_ticket) == -1)
return -ENOMEM;
Sep 15, 2011
Sep 15, 2011
491
492
493
csd_argv[i++]= (char *)"-stub";
csd_argv[i++]= (char *)"\"0\"";
csd_argv[i++]= (char *)"-group";
Jan 5, 2010
Jan 5, 2010
494
495
496
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->authgroup?:"") == -1)
return -ENOMEM;
May 29, 2012
May 29, 2012
497
498
499
openconnect_local_cert_md5(vpninfo, ccertbuf);
scertbuf[0] = 0;
get_cert_md5_fingerprint(vpninfo, vpninfo->peer_cert, scertbuf);
Sep 15, 2011
Sep 15, 2011
500
csd_argv[i++]= (char *)"-certhash";
Jan 5, 2010
Jan 5, 2010
501
502
if (asprintf(&csd_argv[i++], "\"%s:%s\"", scertbuf, ccertbuf) == -1)
return -ENOMEM;
May 29, 2012
May 29, 2012
503
Sep 15, 2011
Sep 15, 2011
504
csd_argv[i++]= (char *)"-url";
Jan 5, 2010
Jan 5, 2010
505
506
if (asprintf(&csd_argv[i++], "\"https://%s%s\"", vpninfo->hostname, vpninfo->csd_starturl) == -1)
return -ENOMEM;
Aug 4, 2009
Aug 4, 2009
507
/* WTF would it want to know this for? */
Sep 15, 2011
Sep 15, 2011
508
509
510
csd_argv[i++]= (char *)"-vpnclient";
csd_argv[i++]= (char *)"\"/opt/cisco/vpn/bin/vpnui";
csd_argv[i++]= (char *)"-connect";
Jan 5, 2010
Jan 5, 2010
511
512
if (asprintf(&csd_argv[i++], "https://%s/%s", vpninfo->hostname, vpninfo->csd_preurl) == -1)
return -ENOMEM;
Sep 15, 2011
Sep 15, 2011
513
csd_argv[i++]= (char *)"-connectparam";
Jan 5, 2010
Jan 5, 2010
514
515
if (asprintf(&csd_argv[i++], "#csdtoken=%s\"", vpninfo->csd_token) == -1)
return -ENOMEM;
Sep 15, 2011
Sep 15, 2011
516
csd_argv[i++]= (char *)"-langselen";
Aug 4, 2009
Aug 4, 2009
517
518
csd_argv[i++] = NULL;
Nov 21, 2010
Nov 21, 2010
519
execv(csd_argv[0], csd_argv);
Sep 22, 2011
Sep 22, 2011
520
521
vpn_progress(vpninfo, PRG_ERR,
_("Failed to exec CSD script %s\n"), csd_argv[0]);
Aug 4, 2009
Aug 4, 2009
522
exit(1);
Jul 20, 2009
Jul 20, 2009
523
524
525
526
}
free(vpninfo->csd_stuburl);
vpninfo->csd_stuburl = NULL;
Aug 4, 2009
Aug 4, 2009
527
528
vpninfo->urlpath = strdup(vpninfo->csd_waiturl +
(vpninfo->csd_waiturl[0] == '/' ? 1 : 0));
Jul 20, 2009
Jul 20, 2009
529
vpninfo->csd_waiturl = NULL;
Aug 4, 2009
Aug 4, 2009
530
vpninfo->csd_scriptname = strdup(fname);
Aug 4, 2009
Aug 4, 2009
531
Nov 6, 2009
Nov 6, 2009
532
533
http_add_cookie(vpninfo, "sdesktop", vpninfo->csd_token);
Jul 20, 2009
Jul 20, 2009
534
535
536
return 0;
}
Apr 18, 2012
Apr 18, 2012
537
538
#ifndef HAVE_STRCASESTR
static char *openconnect__strcasestr(const char *haystack, const char *needle)
Nov 3, 2009
Nov 3, 2009
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
{
int hlen = strlen(haystack);
int nlen = strlen(needle);
int i, j;
for (i = 0; i < hlen - nlen + 1; i++) {
for (j = 0; j < nlen; j++) {
if (tolower(haystack[i + j]) !=
tolower(needle[j]))
break;
}
if (j == nlen)
return (char *)haystack + i;
}
return NULL;
}
Apr 18, 2012
Apr 18, 2012
555
556
557
#define strcasestr openconnect__strcasestr
#endif
Nov 3, 2009
Nov 3, 2009
558
Mar 9, 2011
Mar 9, 2011
559
560
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
561
562
563
564
565
566
{
char *proto = url;
char *host, *path, *port_str;
int port;
host = strstr(url, "://");
Jan 1, 2010
Jan 1, 2010
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
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
589
590
path = strchr(host, '/');
May 12, 2010
May 12, 2010
591
if (path)
Dec 25, 2009
Dec 25, 2009
592
593
594
595
596
597
598
599
600
601
602
603
604
605
*(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
606
*res_proto = proto ? strdup(proto) : NULL;
Dec 25, 2009
Dec 25, 2009
607
608
609
610
611
if (res_host)
*res_host = strdup(host);
if (res_port)
*res_port = port;
if (res_path)
May 12, 2010
May 12, 2010
612
613
614
*res_path = (path && *path) ? strdup(path) : NULL;
/* Undo the damage we did to the original string */
May 13, 2012
May 13, 2012
615
616
if (port_str)
*(port_str) = ':';
May 12, 2010
May 12, 2010
617
618
619
620
if (path)
*(path - 1) = '/';
if (proto)
*(host - 3) = ':';
Dec 25, 2009
Dec 25, 2009
621
622
623
return 0;
}
Jan 24, 2009
Jan 24, 2009
624
625
626
627
628
/* Return value:
* < 0, on error
* = 0, no cookie (user cancel)
* = 1, obtained cookie
*/
Oct 5, 2008
Oct 5, 2008
629
int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
Oct 1, 2008
Oct 1, 2008
630
631
{
struct vpn_option *opt, *next;
Aug 4, 2009
Aug 4, 2009
632
char buf[MAX_BUF_LEN];
Feb 22, 2010
Feb 22, 2010
633
char *form_buf = NULL;
Oct 1, 2008
Oct 1, 2008
634
int result, buflen;
Oct 1, 2008
Oct 1, 2008
635
char request_body[2048];
Sep 15, 2011
Sep 15, 2011
636
637
const char *request_body_type = NULL;
const char *method = "GET";
Oct 1, 2008
Oct 1, 2008
638
639
retry:
Nov 24, 2010
Nov 24, 2010
640
641
642
643
if (form_buf) {
free(form_buf);
form_buf = NULL;
}
May 28, 2012
May 28, 2012
644
if (openconnect_open_https(vpninfo)) {
Sep 22, 2011
Sep 22, 2011
645
646
647
vpn_progress(vpninfo, PRG_ERR,
_("Failed to open HTTPS connection to %s\n"),
vpninfo->hostname);
Oct 5, 2008
Oct 5, 2008
648
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
649
650
651
}
/*
Apr 9, 2009
Apr 9, 2009
652
653
* 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
654
655
* 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
656
* a socketpair() and servicing the "other" end of it.
Oct 1, 2008
Oct 1, 2008
657
658
659
*
* So we process the HTTP for ourselves...
*/
Apr 9, 2009
Apr 9, 2009
660
sprintf(buf, "%s /%s HTTP/1.1\r\n", method, vpninfo->urlpath ?: "");
Oct 1, 2008
Oct 1, 2008
661
662
663
664
665
sprintf(buf + strlen(buf), "Host: %s\r\n", vpninfo->hostname);
sprintf(buf + strlen(buf), "User-Agent: %s\r\n", vpninfo->useragent);
sprintf(buf + strlen(buf), "Accept: */*\r\n");
sprintf(buf + strlen(buf), "Accept-Encoding: identity\r\n");
Oct 1, 2008
Oct 1, 2008
666
if (vpninfo->cookies) {
Oct 1, 2008
Oct 1, 2008
667
sprintf(buf + strlen(buf), "Cookie: ");
Oct 1, 2008
Oct 1, 2008
668
for (opt = vpninfo->cookies; opt; opt = opt->next)
Oct 1, 2008
Oct 1, 2008
669
sprintf(buf + strlen(buf), "%s=%s%s", opt->option,
Apr 9, 2009
Apr 9, 2009
670
opt->value, opt->next ? "; " : "\r\n");
Oct 1, 2008
Oct 1, 2008
671
}
Oct 1, 2008
Oct 1, 2008
672
if (request_body_type) {
Oct 1, 2008
Oct 1, 2008
673
sprintf(buf + strlen(buf), "Content-Type: %s\r\n",
Oct 1, 2008
Oct 1, 2008
674
request_body_type);
Oct 1, 2008
Oct 1, 2008
675
sprintf(buf + strlen(buf), "Content-Length: %zd\r\n",
Oct 1, 2008
Oct 1, 2008
676
677
strlen(request_body));
}
Oct 1, 2008
Oct 1, 2008
678
679
680
681
sprintf(buf + strlen(buf), "X-Transcend-Version: 1\r\n\r\n");
if (request_body_type)
sprintf(buf + strlen(buf), "%s", request_body);
Dec 23, 2009
Dec 23, 2009
682
if (vpninfo->port == 443)
Jun 27, 2011
Jun 27, 2011
683
vpn_progress(vpninfo, PRG_INFO, "%s https://%s/%s\n",
Sep 22, 2011
Sep 22, 2011
684
685
method, vpninfo->hostname,
vpninfo->urlpath ?: "");
Dec 23, 2009
Dec 23, 2009
686
else
Jun 27, 2011
Jun 27, 2011
687
vpn_progress(vpninfo, PRG_INFO, "%s https://%s:%d/%s\n",
Sep 22, 2011
Sep 22, 2011
688
689
method, vpninfo->hostname, vpninfo->port,
vpninfo->urlpath ?: "");
Apr 1, 2009
Apr 1, 2009
690
May 12, 2012
May 12, 2012
691
692
693
result = openconnect_SSL_write(vpninfo, buf, strlen(buf));
if (result < 0)
return result;
Oct 1, 2008
Oct 1, 2008
694
Feb 22, 2010
Feb 22, 2010
695
buflen = process_http_response(vpninfo, &result, NULL, &form_buf);
Oct 1, 2008
Oct 1, 2008
696
697
if (buflen < 0) {
/* We'll already have complained about whatever offended us */
May 13, 2012
May 13, 2012
698
return buflen;
Oct 1, 2008
Oct 1, 2008
699
700
701
}
if (result != 200 && vpninfo->redirect_url) {
Aug 4, 2009
Aug 4, 2009
702
redirect:
Oct 1, 2008
Oct 1, 2008
703
704
if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
/* New host. Tear down the existing connection and make a new one */
Dec 25, 2009
Dec 25, 2009
705
706
707
char *host;
int port;
int ret;
Mar 31, 2009
Mar 31, 2009
708
Oct 1, 2008
Oct 1, 2008
709
free(vpninfo->urlpath);
Dec 25, 2009
Dec 25, 2009
710
vpninfo->urlpath = NULL;
Dec 23, 2009
Dec 23, 2009
711
Mar 9, 2011
Mar 9, 2011
712
ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
Dec 25, 2009
Dec 25, 2009
713
if (ret) {
Sep 22, 2011
Sep 22, 2011
714
715
716
vpn_progress(vpninfo, PRG_ERR,
_("Failed to parse redirected URL '%s': %s\n"),
vpninfo->redirect_url, strerror(-ret));
Dec 25, 2009
Dec 25, 2009
717
free(vpninfo->redirect_url);
May 13, 2012
May 13, 2012
718
vpninfo->redirect_url = NULL;
Feb 22, 2010
Feb 22, 2010
719
free(form_buf);
Dec 25, 2009
Dec 25, 2009
720
return ret;
Dec 23, 2009
Dec 23, 2009
721
}
Dec 25, 2009
Dec 25, 2009
722
Jan 9, 2010
Jan 9, 2010
723
if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
Mar 31, 2009
Mar 31, 2009
724
free(vpninfo->hostname);
Dec 25, 2009
Dec 25, 2009
725
vpninfo->hostname = host;
Dec 23, 2009
Dec 23, 2009
726
vpninfo->port = port;
Oct 1, 2008
Oct 1, 2008
727
Mar 31, 2009
Mar 31, 2009
728
/* Kill the existing connection, and a new one will happen */
Dec 7, 2009
Dec 7, 2009
729
730
free(vpninfo->peer_addr);
vpninfo->peer_addr = NULL;
Jun 9, 2012
Jun 9, 2012
731
openconnect_close_https(vpninfo, 0);
Oct 1, 2008
Oct 1, 2008
732
Mar 31, 2009
Mar 31, 2009
733
734
735
736
737
738
739
740
for (opt = vpninfo->cookies; opt; opt = next) {
next = opt->next;
free(opt->option);
free(opt->value);
free(opt);
}
vpninfo->cookies = NULL;
Dec 25, 2009
Dec 25, 2009
741
742
743
} else
free(host);
Mar 31, 2009
Mar 31, 2009
744
745
746
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
Oct 1, 2008
Oct 1, 2008
747
goto retry;
May 13, 2012
May 13, 2012
748
749
750
751
752
753
754
755
} 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;
free(form_buf);
return -EINVAL;
Oct 1, 2008
Oct 1, 2008
756
757
758
} else if (vpninfo->redirect_url[0] == '/') {
/* Absolute redirect within same host */
free(vpninfo->urlpath);
Apr 1, 2009
Apr 1, 2009
759
760
vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
free(vpninfo->redirect_url);
Oct 1, 2008
Oct 1, 2008
761
762
763
vpninfo->redirect_url = NULL;
goto retry;
} else {
Sep 3, 2010
Sep 3, 2010
764
765
766
char *lastslash = NULL;
if (vpninfo->urlpath)
lastslash = strrchr(vpninfo->urlpath, '/');
Feb 22, 2010
Feb 22, 2010
767
768
769
770
771
772
773
774
775
776
777
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;
Jun 27, 2011
Jun 27, 2011
778
vpn_progress(vpninfo, PRG_ERR,
Sep 22, 2011
Sep 22, 2011
779
780
_("Allocating new path for relative redirect failed: %s\n"),
strerror(-err));
Feb 22, 2010
Feb 22, 2010
781
782
783
784
785
786
787
return err;
}
free(oldurl);
free(vpninfo->redirect_url);
vpninfo->redirect_url = NULL;
}
goto retry;
Oct 1, 2008
Oct 1, 2008
788
789
}
}
Apr 4, 2010
Apr 4, 2010
790
if (!form_buf || result != 200) {
Jun 27, 2011
Jun 27, 2011
791
vpn_progress(vpninfo, PRG_ERR,
Sep 22, 2011
Sep 22, 2011
792
793
_("Unexpected %d result from server\n"),
result);
May 12, 2010
May 12, 2010
794
free(form_buf);
Apr 4, 2010
Apr 4, 2010
795
796
return -EINVAL;
}
Jul 20, 2009
Jul 20, 2009
797
798
if (vpninfo->csd_stuburl) {
/* This is the CSD stub script, which we now need to run */
Feb 22, 2010
Feb 22, 2010
799
800
801
result = run_csd_script(vpninfo, form_buf, buflen);
if (result) {
free(form_buf);
Jul 20, 2009
Jul 20, 2009
802
return result;
Feb 22, 2010
Feb 22, 2010
803
}
Jul 20, 2009
Jul 20, 2009
804
805
806
807
/* Now we'll be redirected to the waiturl */
goto retry;
}
Feb 22, 2010
Feb 22, 2010
808
if (strncmp(form_buf, "<?xml", 5)) {
Aug 4, 2009
Aug 4, 2009
809
/* Not XML? Perhaps it's HTML with a refresh... */
Feb 22, 2010
Feb 22, 2010
810
if (strcasestr(form_buf, "http-equiv=\"refresh\"")) {
Sep 22, 2011
Sep 22, 2011
811
812
813
vpn_progress(vpninfo, PRG_INFO,
_("Refreshing %s after 1 second...\n"),
vpninfo->urlpath);
Aug 4, 2009
Aug 4, 2009
814
815
816
sleep(1);
goto retry;
}
Sep 22, 2011
Sep 22, 2011
817
818
vpn_progress(vpninfo, PRG_ERR,
_("Unknown response from server\n"));
Feb 22, 2010
Feb 22, 2010
819
free(form_buf);
Aug 4, 2009
Aug 4, 2009
820
821
return -EINVAL;
}
Oct 1, 2008
Oct 1, 2008
822
request_body[0] = 0;
Feb 22, 2010
Feb 22, 2010
823
result = parse_xml_response(vpninfo, form_buf, request_body, sizeof(request_body),
Jul 20, 2009
Jul 20, 2009
824
&method, &request_body_type);
Feb 22, 2010
Feb 22, 2010
825
Jul 20, 2009
Jul 20, 2009
826
if (!result)
Aug 4, 2009
Aug 4, 2009
827
goto redirect;
Jul 20, 2009
Jul 20, 2009
828
Feb 22, 2010
Feb 22, 2010
829
830
free(form_buf);
Apr 22, 2009
Apr 22, 2009
831
if (result != 2)
Apr 22, 2009
Apr 22, 2009
832
return result;
Feb 22, 2010
Feb 22, 2010
833
Apr 22, 2009
Apr 22, 2009
834
835
/* A return value of 2 means the XML form indicated
success. We _should_ have a cookie... */
Oct 1, 2008
Oct 1, 2008
836
Oct 1, 2008
Oct 1, 2008
837
838
839
840
for (opt = vpninfo->cookies; opt; opt = opt->next) {
if (!strcmp(opt->option, "webvpn"))
vpninfo->cookie = opt->value;
Oct 5, 2008
Oct 5, 2008
841
else if (vpninfo->write_new_config && !strcmp(opt->option, "webvpnc")) {
Oct 2, 2008
Oct 2, 2008
842
843
844
845
846
847
848
849
850
851
852
853
char *tok = opt->value;
char *bu = NULL, *fu = NULL, *sha = NULL;
do {
if (tok != opt->value)
*(tok++) = 0;
if (!strncmp(tok, "bu:", 3))
bu = tok + 3;
else if (!strncmp(tok, "fu:", 3))
fu = tok + 3;
else if (!strncmp(tok, "fh:", 3)) {
Oct 5, 2008
Oct 5, 2008
854
if (!strncasecmp(tok+3, vpninfo->xmlsha1,
May 29, 2012
May 29, 2012
855
SHA1_SIZE * 2))
Oct 2, 2008
Oct 2, 2008
856
857
break;
sha = tok + 3;
Oct 1, 2008
Oct 1, 2008
858
}
Oct 2, 2008
Oct 2, 2008
859
860
861
862
} while ((tok = strchr(tok, '&')));
if (bu && fu && sha)
fetch_config(vpninfo, bu, fu, sha);
Oct 1, 2008
Oct 1, 2008
863
864
}
}
Aug 4, 2009
Aug 4, 2009
865
866
867
868
869
if (vpninfo->csd_scriptname) {
unlink(vpninfo->csd_scriptname);
free(vpninfo->csd_scriptname);
vpninfo->csd_scriptname = NULL;
}
Apr 22, 2009
Apr 22, 2009
870
return 0;
Oct 1, 2008
Oct 1, 2008
871
}
Oct 5, 2008
Oct 5, 2008
872
Sep 15, 2011
Sep 15, 2011
873
char *openconnect_create_useragent(const char *base)
Oct 5, 2008
Oct 5, 2008
874
{
Dec 7, 2009
Dec 7, 2009
875
876
char *uagent;
May 12, 2012
May 12, 2012
877
if (asprintf(&uagent, "%s %s", base, openconnect_version_str) < 0)
Dec 7, 2009
Dec 7, 2009
878
879
return NULL;
Oct 5, 2008
Oct 5, 2008
880
881
return uagent;
}
Jan 1, 2010
Jan 1, 2010
882
May 12, 2012
May 12, 2012
883
884
static int proxy_gets(struct openconnect_info *vpninfo, int fd,
char *buf, size_t len)
Jan 1, 2010
Jan 1, 2010
885
886
887
888
889
890
891
{
int i = 0;
int ret;
if (len < 2)
return -EINVAL;
May 12, 2012
May 12, 2012
892
while ( (ret = proxy_read(vpninfo, fd, (void *)(buf + i), 1)) == 0) {
Jan 1, 2010
Jan 1, 2010
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
if (buf[i] == '\n') {
buf[i] = 0;
if (i && buf[i-1] == '\r') {
buf[i-1] = 0;
i--;
}
return i;
}
i++;
if (i >= len - 1) {
buf[i] = 0;
return i;
}
}
buf[i] = 0;
return i ?: ret;
}
May 12, 2012
May 12, 2012
912
913
static int proxy_write(struct openconnect_info *vpninfo, int fd,
unsigned char *buf, size_t len)
Jan 2, 2010
Jan 2, 2010
914
915
{
size_t count;
May 12, 2012
May 12, 2012
916
Jan 2, 2010
Jan 2, 2010
917
for (count = 0; count < len; ) {
May 12, 2012
May 12, 2012
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
fd_set rd_set, wr_set;
int maxfd = fd;
int i;
FD_ZERO(&wr_set);
FD_ZERO(&rd_set);
FD_SET(fd, &wr_set);
if (vpninfo->cancel_fd != -1) {
FD_SET(vpninfo->cancel_fd, &rd_set);
if (vpninfo->cancel_fd > fd)
maxfd = vpninfo->cancel_fd;
}
select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
if (vpninfo->cancel_fd != -1 &&
FD_ISSET(vpninfo->cancel_fd, &rd_set))
return -EINTR;
/* Not that this should ever be able to happen... */
if (!FD_ISSET(fd, &wr_set))
continue;
i = write(fd, buf + count, len - count);
Jan 2, 2010
Jan 2, 2010
941
942
943
944
945
946
947
if (i < 0)
return -errno;
count += i;
}
return 0;
}
Jan 1, 2010
Jan 1, 2010
948
May 12, 2012
May 12, 2012
949
950
static int proxy_read(struct openconnect_info *vpninfo, int fd,
unsigned char *buf, size_t len)
Jan 2, 2010
Jan 2, 2010
951
952
953
954
{
size_t count;
for (count = 0; count < len; ) {
May 12, 2012
May 12, 2012
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
fd_set rd_set;
int maxfd = fd;
int i;
FD_ZERO(&rd_set);
FD_SET(fd, &rd_set);
if (vpninfo->cancel_fd != -1) {
FD_SET(vpninfo->cancel_fd, &rd_set);
if (vpninfo->cancel_fd > fd)
maxfd = vpninfo->cancel_fd;
}
select(maxfd + 1, &rd_set, NULL, NULL, NULL);
if (vpninfo->cancel_fd != -1 &&
FD_ISSET(vpninfo->cancel_fd, &rd_set))
return -EINTR;
/* Not that this should ever be able to happen... */
if (!FD_ISSET(fd, &rd_set))
continue;
i = read(fd, buf + count, len - count);
Jan 2, 2010
Jan 2, 2010
977
978
979
980
981
982
983
984
985
if (i < 0)
return -errno;
count += i;
}
return 0;
}
static const char *socks_errors[] = {
Sep 22, 2011
Sep 22, 2011
986
987
988
989
990
991
992
993
994
N_("request granted"),
N_("general failure"),
N_("connection not allowed by ruleset"),
N_("network unreachable"),
N_("host unreachable"),
N_("connection refused by destination host"),
N_("TTL expired"),
N_("command not supported / protocol error"),
N_("address type not supported")
Jan 2, 2010
Jan 2, 2010
995
996
997
998
999
1000
};
static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock)
{
unsigned char buf[1024];
int i;