Skip to content

Latest commit

 

History

History
2950 lines (2611 loc) · 82.3 KB

gnutls.c

File metadata and controls

2950 lines (2611 loc) · 82.3 KB
 
May 29, 2012
May 29, 2012
1
2
3
/*
* OpenConnect (SSL + DTLS) VPN client
*
Jan 26, 2015
Jan 26, 2015
4
* Copyright © 2008-2015 Intel Corporation.
May 29, 2012
May 29, 2012
5
6
7
8
9
10
11
12
13
14
15
16
17
*
* Author: David Woodhouse <dwmw2@infradead.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* 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.
*/
Jul 1, 2014
Jul 1, 2014
18
19
#include <config.h>
May 29, 2012
May 29, 2012
20
#include <sys/types.h>
May 31, 2012
May 31, 2012
21
#include <sys/stat.h>
May 29, 2012
May 29, 2012
22
23
24
25
26
27
28
29
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
Jun 14, 2012
Jun 14, 2012
30
31
32
33
34
35
#ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
/* Shut up about gnutls_sign_callback_set() being deprecated. We only use it
in the GnuTLS 2.12 case, and there just isn't another way of doing it. */
#define GNUTLS_INTERNAL_BUILD 1
#endif
May 29, 2012
May 29, 2012
36
37
38
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/crypto.h>
May 31, 2012
May 31, 2012
39
#include <gnutls/pkcs12.h>
Jun 10, 2012
Jun 10, 2012
40
#include <gnutls/abstract.h>
May 29, 2012
May 29, 2012
41
Jun 13, 2012
Jun 13, 2012
42
43
44
45
#ifdef HAVE_TROUSERS
#include <trousers/tss.h>
#include <trousers/trousers.h>
#endif
Nov 27, 2014
Nov 27, 2014
46
Jun 8, 2012
Jun 8, 2012
47
48
#ifdef HAVE_P11KIT
#include <p11-kit/p11-kit.h>
Jun 10, 2012
Jun 10, 2012
49
#include <p11-kit/pkcs11.h>
Jun 8, 2012
Jun 8, 2012
50
#include <p11-kit/pin.h>
Nov 27, 2014
Nov 27, 2014
51
#endif
Jun 8, 2012
Jun 8, 2012
52
Nov 27, 2014
Nov 27, 2014
53
#if defined(HAVE_P11KIT) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
Nov 18, 2014
Nov 18, 2014
54
55
56
57
58
59
60
61
static int gnutls_pin_callback(void *priv, int attempt, const char *uri,
const char *token_label, unsigned int flags,
char *pin, size_t pin_max);
#ifndef HAVE_GNUTLS_X509_CRT_SET_PIN_FUNCTION
/* If we don't have this (3.1.0+) then we'll use p11-kit callbacks instead
* because the old GnuTLS callback was global rather than context-specific,
* which makes it basically unusable from libopenconnect. The p11-kit
Nov 27, 2014
Nov 27, 2014
62
* callback function is a simple wrapper around the GnuTLS native version. */
Nov 18, 2014
Nov 18, 2014
63
64
65
66
67
68
69
70
71
72
73
74
75
76
typedef enum {
GNUTLS_PIN_USER = (1 << 0),
GNUTLS_PIN_SO = (1 << 1),
GNUTLS_PIN_FINAL_TRY = (1 << 2),
GNUTLS_PIN_COUNT_LOW = (1 << 3),
GNUTLS_PIN_CONTEXT_SPECIFIC = (1 << 4),
GNUTLS_PIN_WRONG = (1 << 5)
} gnutls_pin_flag_t;
static P11KitPin *p11kit_pin_callback(const char *pin_source, P11KitUri *pin_uri,
const char *pin_description,
P11KitPinFlags flags,
void *_vpninfo);
#endif /* !HAVE_GNUTLS_X509_CRT_SET_PIN_FUNCTION */
Nov 27, 2014
Nov 27, 2014
77
#endif /* HAVE_P11KIT || HAVE_GNUTLS_SYSTEM_KEYS */
Jun 8, 2012
Jun 8, 2012
78
Jun 14, 2012
Jun 14, 2012
79
#include "gnutls.h"
May 29, 2012
May 29, 2012
80
81
#include "openconnect-internal.h"
Aug 6, 2015
Aug 6, 2015
82
83
84
85
86
87
88
89
/* GnuTLS 2.x lacked this. But GNUTLS_E_UNEXPECTED_PACKET_LENGTH basically
* does the same thing.
* http://lists.infradead.org/pipermail/openconnect-devel/2014-March/001726.html
*/
#ifndef GNUTLS_E_PREMATURE_TERMINATION
#define GNUTLS_E_PREMATURE_TERMINATION GNUTLS_E_UNEXPECTED_PACKET_LENGTH
#endif
Aug 7, 2015
Aug 7, 2015
90
91
92
93
94
95
96
97
98
99
100
/* Compile-time optimisable GnuTLS version check. We should never be
* run against a version of GnuTLS which is *older* than the one we
* were built again, but we might be run against a version which is
* newer. So some ancient compatibility code *can* be dropped at
* compile time. Likewise, if building against GnuTLS 2.x then we
* can never be running agsinst a 3.x library — the soname changed. */
#define gtls_ver(a,b,c) ( GNUTLS_VERSION_MAJOR >= (a) && \
(GNUTLS_VERSION_NUMBER >= ( ((a) << 16) + ((b) << 8) + (c) ) || \
gnutls_check_version(#a "." #b "." #c)))
Feb 14, 2014
Feb 14, 2014
101
/* Helper functions for reading/writing lines over SSL. */
Sep 10, 2016
Sep 10, 2016
102
static int _openconnect_gnutls_write(gnutls_session_t ses, int fd, struct openconnect_info *vpninfo, char *buf, size_t len)
May 29, 2012
May 29, 2012
103
104
105
106
{
size_t orig_len = len;
while (len) {
Sep 10, 2016
Sep 10, 2016
107
int done = gnutls_record_send(ses, buf, len);
May 29, 2012
May 29, 2012
108
109
if (done > 0)
len -= done;
Aug 30, 2016
Aug 30, 2016
110
else if (done == GNUTLS_E_AGAIN || done == GNUTLS_E_INTERRUPTED) {
Feb 14, 2014
Feb 14, 2014
111
/* Wait for something to happen on the socket, or on cmd_fd */
May 29, 2012
May 29, 2012
112
fd_set wr_set, rd_set;
Sep 10, 2016
Sep 10, 2016
113
int maxfd = fd;
May 29, 2012
May 29, 2012
114
115
116
FD_ZERO(&wr_set);
FD_ZERO(&rd_set);
Mar 10, 2013
Mar 10, 2013
117
Sep 10, 2016
Sep 10, 2016
118
119
if (gnutls_record_get_direction(ses))
FD_SET(fd, &wr_set);
May 29, 2012
May 29, 2012
120
else
Sep 10, 2016
Sep 10, 2016
121
FD_SET(fd, &rd_set);
May 29, 2012
May 29, 2012
122
Jan 15, 2014
Jan 15, 2014
123
cmd_fd_set(vpninfo, &rd_set, &maxfd);
May 29, 2012
May 29, 2012
124
select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
Jan 15, 2014
Jan 15, 2014
125
if (is_cancel_pending(vpninfo, &rd_set)) {
May 29, 2012
May 29, 2012
126
127
128
vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
return -EINTR;
}
Feb 14, 2014
Feb 14, 2014
129
130
131
132
} else {
vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket: %s\n"),
gnutls_strerror(done));
return -EIO;
May 29, 2012
May 29, 2012
133
134
135
136
137
}
}
return orig_len;
}
Sep 10, 2016
Sep 10, 2016
138
139
140
141
142
143
144
145
146
147
148
static int openconnect_gnutls_write(struct openconnect_info *vpninfo, char *buf, size_t len)
{
return _openconnect_gnutls_write(vpninfo->https_sess, vpninfo->ssl_fd, vpninfo, buf, len);
}
int openconnect_dtls_write(struct openconnect_info *vpninfo, void *buf, size_t len)
{
return _openconnect_gnutls_write(vpninfo->dtls_ssl, vpninfo->dtls_fd, vpninfo, buf, len);
}
static int _openconnect_gnutls_read(gnutls_session_t ses, int fd, struct openconnect_info *vpninfo, char *buf, size_t len, unsigned ms)
May 29, 2012
May 29, 2012
149
{
Sep 10, 2016
Sep 10, 2016
150
151
152
153
154
155
156
157
int done, ret;
struct timeval timeout, *tv = NULL;
if (ms) {
timeout.tv_sec = ms/1000;
timeout.tv_usec = (ms%1000)*1000;
tv = &timeout;
}
May 29, 2012
May 29, 2012
158
Sep 10, 2016
Sep 10, 2016
159
while ((done = gnutls_record_recv(ses, buf, len)) < 0) {
Aug 30, 2016
Aug 30, 2016
160
if (done == GNUTLS_E_AGAIN || done == GNUTLS_E_INTERRUPTED) {
Feb 14, 2014
Feb 14, 2014
161
162
/* Wait for something to happen on the socket, or on cmd_fd */
fd_set wr_set, rd_set;
Sep 10, 2016
Sep 10, 2016
163
int maxfd = fd;
May 29, 2012
May 29, 2012
164
165
166
FD_ZERO(&wr_set);
FD_ZERO(&rd_set);
Mar 10, 2013
Mar 10, 2013
167
Sep 10, 2016
Sep 10, 2016
168
169
if (gnutls_record_get_direction(ses))
FD_SET(fd, &wr_set);
May 29, 2012
May 29, 2012
170
else
Sep 10, 2016
Sep 10, 2016
171
FD_SET(fd, &rd_set);
May 29, 2012
May 29, 2012
172
Jan 15, 2014
Jan 15, 2014
173
cmd_fd_set(vpninfo, &rd_set, &maxfd);
Sep 10, 2016
Sep 10, 2016
174
ret = select(maxfd + 1, &rd_set, &wr_set, NULL, tv);
Jan 15, 2014
Jan 15, 2014
175
if (is_cancel_pending(vpninfo, &rd_set)) {
May 29, 2012
May 29, 2012
176
vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
Sep 10, 2016
Sep 10, 2016
177
178
179
180
181
182
183
done = -EINTR;
goto cleanup;
}
if (ret == 0) {
done = -ETIMEDOUT;
goto cleanup;
May 29, 2012
May 29, 2012
184
}
Feb 14, 2014
Feb 14, 2014
185
186
187
188
} else if (done == GNUTLS_E_PREMATURE_TERMINATION) {
/* We've seen this with HTTP 1.0 responses followed by abrupt
socket closure and no clean SSL shutdown.
https://bugs.launchpad.net/bugs/1225276 */
Jun 13, 2014
Jun 13, 2014
189
vpn_progress(vpninfo, PRG_DEBUG, _("SSL socket closed uncleanly\n"));
Sep 10, 2016
Sep 10, 2016
190
191
done = 0;
goto cleanup;
Dec 2, 2015
Dec 2, 2015
192
193
} else if (done == GNUTLS_E_REHANDSHAKE) {
int ret = cstp_handshake(vpninfo, 0);
Sep 10, 2016
Sep 10, 2016
194
195
196
197
if (ret) {
done = ret;
goto cleanup;
}
Feb 14, 2014
Feb 14, 2014
198
199
200
} else {
vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s\n"),
gnutls_strerror(done));
Sep 10, 2016
Sep 10, 2016
201
202
203
204
205
206
207
if (done == GNUTLS_E_TIMEDOUT) {
done = -ETIMEDOUT;
goto cleanup;
} else {
done = -EIO;
goto cleanup;
}
May 29, 2012
May 29, 2012
208
}
Feb 14, 2014
Feb 14, 2014
209
May 29, 2012
May 29, 2012
210
}
Sep 10, 2016
Sep 10, 2016
211
212
cleanup:
May 29, 2012
May 29, 2012
213
return done;
Sep 10, 2016
Sep 10, 2016
214
215
216
217
218
219
220
221
222
223
224
}
static int openconnect_gnutls_read(struct openconnect_info *vpninfo, char *buf, size_t len)
{
return _openconnect_gnutls_read(vpninfo->https_sess, vpninfo->ssl_fd, vpninfo, buf, len, 0);
}
int openconnect_dtls_read(struct openconnect_info *vpninfo, void *buf, size_t len, unsigned ms)
{
return _openconnect_gnutls_read(vpninfo->dtls_ssl, vpninfo->dtls_fd, vpninfo, buf, len, ms);
May 29, 2012
May 29, 2012
225
226
}
Jun 18, 2014
Jun 18, 2014
227
static int openconnect_gnutls_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
May 29, 2012
May 29, 2012
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
{
int i = 0;
int ret;
if (len < 2)
return -EINVAL;
while (1) {
ret = gnutls_record_recv(vpninfo->https_sess, buf + i, 1);
if (ret == 1) {
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;
}
Aug 30, 2016
Aug 30, 2016
252
} else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
Feb 14, 2014
Feb 14, 2014
253
/* Wait for something to happen on the socket, or on cmd_fd */
May 29, 2012
May 29, 2012
254
255
fd_set rd_set, wr_set;
int maxfd = vpninfo->ssl_fd;
Mar 10, 2013
Mar 10, 2013
256
May 29, 2012
May 29, 2012
257
258
FD_ZERO(&rd_set);
FD_ZERO(&wr_set);
Mar 10, 2013
Mar 10, 2013
259
May 29, 2012
May 29, 2012
260
261
262
263
264
if (gnutls_record_get_direction(vpninfo->https_sess))
FD_SET(vpninfo->ssl_fd, &wr_set);
else
FD_SET(vpninfo->ssl_fd, &rd_set);
Jan 15, 2014
Jan 15, 2014
265
cmd_fd_set(vpninfo, &rd_set, &maxfd);
May 29, 2012
May 29, 2012
266
select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
Jan 15, 2014
Jan 15, 2014
267
if (is_cancel_pending(vpninfo, &rd_set)) {
May 29, 2012
May 29, 2012
268
269
270
271
vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
ret = -EINTR;
break;
}
Dec 2, 2015
Dec 2, 2015
272
273
274
275
} else if (ret == GNUTLS_E_REHANDSHAKE) {
ret = cstp_handshake(vpninfo, 0);
if (ret)
return ret;
Feb 14, 2014
Feb 14, 2014
276
277
278
279
280
} else {
vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s\n"),
gnutls_strerror(ret));
ret = -EIO;
break;
May 29, 2012
May 29, 2012
281
282
283
284
285
286
}
}
buf[i] = 0;
return i ?: ret;
}
Jan 26, 2015
Jan 26, 2015
287
288
289
290
291
292
293
294
int ssl_nonblock_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
{
int ret;
ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
if (ret > 0)
return ret;
Aug 30, 2016
Aug 30, 2016
295
if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) {
Jan 26, 2015
Jan 26, 2015
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
vpn_progress(vpninfo, PRG_ERR,
_("SSL read error: %s; reconnecting.\n"),
gnutls_strerror(ret));
return -EIO;
}
return 0;
}
int ssl_nonblock_write(struct openconnect_info *vpninfo, void *buf, int buflen)
{
int ret;
ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
if (ret > 0)
return ret;
Aug 30, 2016
Aug 30, 2016
312
if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
Jan 29, 2015
Jan 29, 2015
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/*
* Before 3.3.13, GnuTLS could return zero instead of one,
* indicating that it was waiting for a read when in fact
* it was waiting for a write. That caused us to block for
* ever, waiting for the read that it said it wanted.
*
* So instead, just *assume* it actually wants a write.
* Which is true most of the time, and on the rare occasion
* that it *isn't* true, the failure mode will just be that
* we keep waking up and calling GnuTLS again until the read
* that it's waiting for does arrive.
*/
if (GNUTLS_VERSION_NUMBER < 0x03030d ||
gnutls_record_get_direction(vpninfo->https_sess)) {
/* Waiting for the socket to become writable — it's
Jan 26, 2015
Jan 26, 2015
328
329
330
331
332
333
334
335
336
337
probably stalled, and/or the buffers are full */
monitor_write_fd(vpninfo, ssl);
}
return 0;
}
vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
gnutls_strerror(ret));
return -1;
}
May 31, 2012
May 31, 2012
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x509_crt_t cert)
{
const char *reason = NULL;
time_t expires = gnutls_x509_crt_get_expiration_time(cert);
time_t now = time(NULL);
if (expires == -1) {
vpn_progress(vpninfo, PRG_ERR,
_("Could not extract expiration time of certificate\n"));
return -EINVAL;
}
if (expires < now)
reason = _("Client certificate has expired at");
else if (expires < now + vpninfo->cert_expire_warning)
reason = _("Client certificate expires soon at");
if (reason) {
char buf[80];
Feb 5, 2014
Feb 5, 2014
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#ifdef _WIN32
/*
* Windows doesn't have gmtime_r but apparently its gmtime()
* *is* thread-safe because it uses a per-thread static buffer.
* cf. http://sourceforge.net/p/mingw/bugs/1625/
*
* We also explicitly say 'GMT' because %Z would give us the
* Microsoft stupidity "GMT Standard Time". Which is not only
* silly, but also ambiguous because Windows actually says that
* even when it means British Summer Time (GMT+1). And having
* used gmtime() we really *are* giving the time in GMT.
*/
struct tm *tm = gmtime(&expires);
strftime(buf, 80, "%a, %d %b %Y %H:%M:%S GMT", tm);
#else
struct tm tm;
May 31, 2012
May 31, 2012
373
374
375
gmtime_r(&expires, &tm);
strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
Feb 5, 2014
Feb 5, 2014
376
#endif
May 31, 2012
May 31, 2012
377
378
379
380
381
vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
}
return 0;
}
May 31, 2012
May 31, 2012
382
383
384
385
386
static int load_datum(struct openconnect_info *vpninfo,
gnutls_datum_t *datum, const char *fname)
{
struct stat st;
int fd, err;
Jul 31, 2014
Jul 31, 2014
387
Jun 15, 2012
Jun 15, 2012
388
389
390
391
392
393
394
395
396
397
398
#ifdef ANDROID_KEYSTORE
if (!strncmp(fname, "keystore:", 9)) {
int len;
const char *p = fname + 9;
/* Skip first two slashes if the user has given it as
keystore://foo ... */
if (*p == '/')
p++;
if (*p == '/')
p++;
Jun 17, 2012
Jun 17, 2012
399
400
len = keystore_fetch(p, &datum->data);
if (len <= 0) {
Jun 15, 2012
Jun 15, 2012
401
vpn_progress(vpninfo, PRG_ERR,
Jun 17, 2012
Jun 17, 2012
402
403
_("Failed to load item '%s' from keystore: %s\n"),
p, keystore_strerror(len));
Jun 15, 2012
Jun 15, 2012
404
405
406
407
408
return -EINVAL;
}
datum->size = len;
return 0;
}
Jul 31, 2014
Jul 31, 2014
409
#endif /* ANDROID_KEYSTORE */
May 31, 2012
May 31, 2012
410
Aug 3, 2014
Aug 3, 2014
411
fd = openconnect_open_utf8(vpninfo, fname, O_RDONLY|O_CLOEXEC|O_BINARY);
May 31, 2012
May 31, 2012
412
413
414
if (fd == -1) {
err = errno;
vpn_progress(vpninfo, PRG_ERR,
Jun 9, 2012
Jun 9, 2012
415
416
_("Failed to open key/certificate file %s: %s\n"),
fname, strerror(err));
May 31, 2012
May 31, 2012
417
418
419
420
421
return -ENOENT;
}
if (fstat(fd, &st)) {
err = errno;
vpn_progress(vpninfo, PRG_ERR,
Jun 9, 2012
Jun 9, 2012
422
423
_("Failed to stat key/certificate file %s: %s\n"),
fname, strerror(err));
May 31, 2012
May 31, 2012
424
425
close(fd);
return -EIO;
May 31, 2012
May 31, 2012
426
}
May 31, 2012
May 31, 2012
427
datum->size = st.st_size;
May 31, 2012
May 31, 2012
428
datum->data = gnutls_malloc(st.st_size + 1);
May 31, 2012
May 31, 2012
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
if (!datum->data) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to allocate certificate buffer\n"));
close(fd);
return -ENOMEM;
}
errno = EAGAIN;
if (read(fd, datum->data, datum->size) != datum->size) {
err = errno;
vpn_progress(vpninfo, PRG_ERR,
_("Failed to read certificate into memory: %s\n"),
strerror(err));
close(fd);
gnutls_free(datum->data);
return -EIO;
}
May 31, 2012
May 31, 2012
445
datum->data[st.st_size] = 0;
May 31, 2012
May 31, 2012
446
447
448
449
close(fd);
return 0;
}
May 31, 2012
May 31, 2012
450
451
452
453
/* A non-zero, non-error return to make load_certificate() continue and
interpreting the file as other types */
#define NOT_PKCS12 1
May 31, 2012
May 31, 2012
454
static int load_pkcs12_certificate(struct openconnect_info *vpninfo,
May 31, 2012
May 31, 2012
455
456
gnutls_datum_t *datum,
gnutls_x509_privkey_t *key,
Jun 9, 2012
Jun 9, 2012
457
458
gnutls_x509_crt_t **chain,
unsigned int *chain_len,
May 31, 2012
May 31, 2012
459
gnutls_x509_crt_t **extra_certs,
Jun 9, 2012
Jun 9, 2012
460
unsigned int *extra_certs_len,
May 31, 2012
May 31, 2012
461
gnutls_x509_crl_t *crl)
May 31, 2012
May 31, 2012
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
{
gnutls_pkcs12_t p12;
char *pass;
int err;
err = gnutls_pkcs12_init(&p12);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to setup PKCS#12 data structure: %s\n"),
gnutls_strerror(err));
return -EIO;
}
err = gnutls_pkcs12_import(p12, datum, GNUTLS_X509_FMT_DER, 0);
if (err) {
gnutls_pkcs12_deinit(p12);
Aug 17, 2014
Aug 17, 2014
478
return NOT_PKCS12;
May 31, 2012
May 31, 2012
479
480
481
}
pass = vpninfo->cert_password;
May 31, 2012
May 31, 2012
482
while ((err = gnutls_pkcs12_verify_mac(p12, pass)) == GNUTLS_E_MAC_VERIFY_FAILED) {
Mar 31, 2014
Mar 31, 2014
483
484
485
486
if (!pass) {
/* OpenSSL's PKCS12_parse() code will try both NULL and "" automatically,
* but GnuTLS requires two separate attempts. */
err = gnutls_pkcs12_verify_mac(p12, "");
Apr 26, 2014
Apr 26, 2014
487
if (!err) {
Mar 31, 2014
Mar 31, 2014
488
489
490
491
pass = strdup("");
break;
}
} else
May 31, 2012
May 31, 2012
492
493
494
vpn_progress(vpninfo, PRG_ERR,
_("Failed to decrypt PKCS#12 certificate file\n"));
free(pass);
May 31, 2012
May 31, 2012
495
vpninfo->cert_password = NULL;
Jun 13, 2012
Jun 13, 2012
496
err = request_passphrase(vpninfo, "openconnect_pkcs12", &pass,
May 31, 2012
May 31, 2012
497
498
499
500
501
502
_("Enter PKCS#12 pass phrase:"));
if (err) {
gnutls_pkcs12_deinit(p12);
return -EINVAL;
}
}
May 31, 2012
May 31, 2012
503
504
505
506
507
508
509
510
511
512
/* If it wasn't GNUTLS_E_MAC_VERIFY_FAILED, then the problem wasn't just a
bad password. Give up. */
if (err) {
int level = PRG_ERR;
int ret = -EINVAL;
gnutls_pkcs12_deinit(p12);
/* If the first attempt, and we didn't know for sure it was PKCS#12
anyway, bail out and try loading it as something different. */
Aug 17, 2014
Aug 17, 2014
513
if (pass == vpninfo->cert_password) {
May 31, 2012
May 31, 2012
514
/* Make it non-fatal... */
Jun 13, 2014
Jun 13, 2014
515
level = PRG_DEBUG;
May 31, 2012
May 31, 2012
516
517
518
519
520
521
522
523
ret = NOT_PKCS12;
}
vpn_progress(vpninfo, level,
_("Failed to process PKCS#12 file: %s\n"),
gnutls_strerror(err));
return ret;
}
Jun 9, 2012
Jun 9, 2012
524
525
err = gnutls_pkcs12_simple_parse(p12, pass, key, chain, chain_len,
extra_certs, extra_certs_len, crl, 0);
Jun 12, 2012
Jun 12, 2012
526
527
528
free(pass);
vpninfo->cert_password = NULL;
May 31, 2012
May 31, 2012
529
530
531
532
533
534
535
536
537
538
gnutls_pkcs12_deinit(p12);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to load PKCS#12 certificate: %s\n"),
gnutls_strerror(err));
return -EINVAL;
}
return 0;
}
May 31, 2012
May 31, 2012
539
/* Older versions of GnuTLS didn't actually bother to check this, so we'll
Nov 15, 2013
Nov 15, 2013
540
541
do it for them. Is there a bug reference for this? Or just the git commit
reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
May 31, 2012
May 31, 2012
542
543
static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
{
Oct 27, 2014
Oct 27, 2014
544
#if GNUTLS_VERSION_NUMBER > 0x030014
May 31, 2012
May 31, 2012
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
return 0;
#else
unsigned char id1[512], id2[512];
size_t id1_size = 512, id2_size = 512;
int err;
err = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
if (err)
return 0;
err = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
if (err)
return 0;
if (id1_size == id2_size && !memcmp(id1, id2, id1_size))
return 0;
/* EEP! */
return -EIO;
#endif
}
May 31, 2012
May 31, 2012
566
567
568
569
570
571
572
573
574
575
576
577
static int count_x509_certificates(gnutls_datum_t *datum)
{
int count = 0;
char *p = (char *)datum->data;
while (p) {
p = strstr(p, "-----BEGIN ");
if (!p)
break;
p += 11;
if (!strncmp(p, "CERTIFICATE", 11) ||
!strncmp(p, "X509 CERTIFICATE", 16))
Mar 10, 2013
Mar 10, 2013
578
count++;
May 31, 2012
May 31, 2012
579
580
581
582
}
return count;
}
Jun 11, 2012
Jun 11, 2012
583
584
585
586
587
588
589
590
591
592
593
594
static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
{
if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
0, 0, name, &namelen) &&
gnutls_x509_crt_get_dn(cert, name, &namelen)) {
name[namelen-1] = 0;
snprintf(name, namelen-1, "<unknown>");
return -EINVAL;
}
return 0;
}
Nov 27, 2014
Nov 27, 2014
595
#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined (HAVE_GNUTLS_SYSTEM_KEYS)
Jun 14, 2012
Jun 14, 2012
596
#ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
Jun 14, 2012
Jun 14, 2012
597
598
599
600
601
602
603
604
/* For GnuTLS 2.12 even if we *have* a privkey (as we do for PKCS#11), we
can't register it. So we have to use the cert_callback function. This
just hands out the certificate chain we prepared in load_certificate().
If we have a pkey then return that too; otherwise leave the key NULL —
we'll also have registered a sign_callback for the session, which will
handle that. */
static int gtls_cert_cb(gnutls_session_t sess, const gnutls_datum_t *req_ca_dn,
int nreqs, const gnutls_pk_algorithm_t *pk_algos,
Jun 14, 2012
Jun 14, 2012
605
int pk_algos_length, gnutls_retr2_st *st) {
Jun 14, 2012
Jun 14, 2012
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
struct openconnect_info *vpninfo = gnutls_session_get_ptr(sess);
int algo = GNUTLS_PK_RSA; /* TPM */
int i;
#ifdef HAVE_P11KIT
if (vpninfo->my_p11key) {
st->key_type = GNUTLS_PRIVKEY_PKCS11;
st->key.pkcs11 = vpninfo->my_p11key;
algo = gnutls_pkcs11_privkey_get_pk_algorithm(vpninfo->my_p11key, NULL);
};
#endif
for (i = 0; i < pk_algos_length; i++) {
if (algo == pk_algos[i])
break;
}
if (i == pk_algos_length)
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
st->cert_type = GNUTLS_CRT_X509;
st->cert.x509 = vpninfo->my_certs;
st->ncerts = vpninfo->nr_my_certs;
st->deinit_all = 0;
return 0;
}
Jun 14, 2012
Jun 14, 2012
632
Jun 14, 2012
Jun 14, 2012
633
634
635
636
637
638
639
640
641
/* For GnuTLS 2.12, this has to set the cert_callback to the function
above, which will return the pkey and certs on demand. Or in the
case of TPM we can't make a suitable pkey, so we have to set a
sign_callback too (which is done in openconnect_open_https() since
it has to be done on the *session*). */
static int assign_privkey(struct openconnect_info *vpninfo,
gnutls_privkey_t pkey,
gnutls_x509_crt_t *certs,
unsigned int nr_certs,
Nov 15, 2013
Nov 15, 2013
642
uint8_t *free_certs)
Jun 14, 2012
Jun 14, 2012
643
644
645
646
647
{
vpninfo->my_certs = gnutls_calloc(nr_certs, sizeof(*certs));
if (!vpninfo->my_certs)
return GNUTLS_E_MEMORY_ERROR;
Nov 15, 2013
Nov 15, 2013
648
vpninfo->free_my_certs = gnutls_malloc(nr_certs);
Mar 19, 2014
Mar 19, 2014
649
if (!vpninfo->free_my_certs) {
Nov 15, 2013
Nov 15, 2013
650
651
652
653
654
655
gnutls_free(vpninfo->my_certs);
vpninfo->my_certs = NULL;
return GNUTLS_E_MEMORY_ERROR;
}
memcpy(vpninfo->free_my_certs, free_certs, nr_certs);
Jun 14, 2012
Jun 14, 2012
656
657
658
memcpy(vpninfo->my_certs, certs, nr_certs * sizeof(*certs));
vpninfo->nr_my_certs = nr_certs;
Jun 14, 2012
Jun 14, 2012
659
660
/* We are *keeping* the certs, unlike in GnuTLS 3 where our caller
can free them after gnutls_certificate_set_key() has been called.
Nov 15, 2013
Nov 15, 2013
661
662
So wipe the 'free_certs' array. */
memset(free_certs, 0, nr_certs);
Jun 14, 2012
Jun 14, 2012
663
664
665
666
667
668
669
gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
gtls_cert_cb);
vpninfo->my_pkey = pkey;
return 0;
}
Jun 14, 2012
Jun 14, 2012
670
#else /* !SET_KEY */
Jun 14, 2012
Jun 14, 2012
671
672
673
674
675
676
677
678
679
/* For GnuTLS 3+ this is saner than the GnuTLS 2.12 version. But still we
have to convert the array of X509 certificates to gnutls_pcert_st for
ourselves. There's no function that takes a gnutls_privkey_t as the key
and gnutls_x509_crt_t certificates. */
static int assign_privkey(struct openconnect_info *vpninfo,
gnutls_privkey_t pkey,
gnutls_x509_crt_t *certs,
unsigned int nr_certs,
Nov 15, 2013
Nov 15, 2013
680
uint8_t *free_certs)
Jun 14, 2012
Jun 14, 2012
681
682
683
684
685
686
687
{
gnutls_pcert_st *pcerts = calloc(nr_certs, sizeof(*pcerts));
int i, err;
if (!pcerts)
return GNUTLS_E_MEMORY_ERROR;
Mar 10, 2013
Mar 10, 2013
688
for (i = 0 ; i < nr_certs; i++) {
Jun 14, 2012
Jun 14, 2012
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
err = gnutls_pcert_import_x509(pcerts + i, certs[i], 0);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Importing X509 certificate failed: %s\n"),
gnutls_strerror(err));
goto free_pcerts;
}
}
err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0,
pcerts, nr_certs, pkey);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Setting PKCS#11 certificate failed: %s\n"),
gnutls_strerror(err));
free_pcerts:
Mar 10, 2013
Mar 10, 2013
705
for (i = 0 ; i < nr_certs; i++)
Jun 14, 2012
Jun 14, 2012
706
gnutls_pcert_deinit(pcerts + i);
Mar 10, 2013
Mar 10, 2013
707
free(pcerts);
Jun 14, 2012
Jun 14, 2012
708
709
710
711
}
return err;
}
#endif /* !SET_KEY */
Mar 6, 2013
Mar 6, 2013
712
713
714
715
static int verify_signed_data(gnutls_pubkey_t pubkey, gnutls_privkey_t privkey,
const gnutls_datum_t *data, const gnutls_datum_t *sig)
{
May 31, 2013
May 31, 2013
716
#ifdef HAVE_GNUTLS_PK_TO_SIGN
Mar 6, 2013
Mar 6, 2013
717
718
719
720
721
722
723
724
725
726
727
gnutls_sign_algorithm_t algo = GNUTLS_SIGN_RSA_SHA1; /* TPM keys */
if (privkey != OPENCONNECT_TPM_PKEY)
algo = gnutls_pk_to_sign(gnutls_privkey_get_pk_algorithm(privkey, NULL),
GNUTLS_DIG_SHA1);
return gnutls_pubkey_verify_data2(pubkey, algo, 0, data, sig);
#else
return gnutls_pubkey_verify_data(pubkey, 0, data, sig);
#endif
}
Nov 27, 2014
Nov 27, 2014
728
#endif /* (P11KIT || TROUSERS || SYSTEM_KEYS) */
Jun 14, 2012
Jun 14, 2012
729
Jun 19, 2012
Jun 19, 2012
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
static int openssl_hash_password(struct openconnect_info *vpninfo, char *pass,
gnutls_datum_t *key, gnutls_datum_t *salt)
{
unsigned char md5[16];
gnutls_hash_hd_t hash;
int count = 0;
int err;
while (count < key->size) {
err = gnutls_hash_init(&hash, GNUTLS_DIG_MD5);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Could not initialise MD5 hash: %s\n"),
gnutls_strerror(err));
return -EIO;
}
if (count) {
err = gnutls_hash(hash, md5, sizeof(md5));
if (err) {
hash_err:
gnutls_hash_deinit(hash, NULL);
vpn_progress(vpninfo, PRG_ERR,
_("MD5 hash error: %s\n"),
gnutls_strerror(err));
return -EIO;
}
}
if (pass) {
err = gnutls_hash(hash, pass, strlen(pass));
if (err)
goto hash_err;
}
Jun 29, 2012
Jun 29, 2012
762
763
/* We only use the first 8 bytes of the salt for this */
err = gnutls_hash(hash, salt->data, 8);
Jun 19, 2012
Jun 19, 2012
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
if (err)
goto hash_err;
gnutls_hash_deinit(hash, md5);
if (key->size - count <= sizeof(md5)) {
memcpy(&key->data[count], md5, key->size - count);
break;
}
memcpy(&key->data[count], md5, sizeof(md5));
count += sizeof(md5);
}
return 0;
}
static int import_openssl_pem(struct openconnect_info *vpninfo,
gnutls_x509_privkey_t key,
char type, char *pem_header, size_t pem_size)
{
gnutls_cipher_hd_t handle;
gnutls_cipher_algorithm_t cipher;
gnutls_datum_t constructed_pem;
gnutls_datum_t b64_data;
gnutls_datum_t salt, enc_key;
unsigned char *key_data;
const char *begin;
Jun 29, 2012
Jun 29, 2012
792
char *pass, *p;
Jun 19, 2012
Jun 19, 2012
793
char *pem_start = pem_header;
Jun 29, 2012
Jun 29, 2012
794
int ret, err, i;
Jun 19, 2012
Jun 19, 2012
795
796
797
798
799
800
if (type == 'E')
begin = "EC PRIVATE KEY";
else if (type == 'R')
begin = "RSA PRIVATE KEY";
else if (type == 'D')
Mar 10, 2013
Mar 10, 2013
801
begin = "DSA PRIVATE KEY";
Jun 19, 2012
Jun 19, 2012
802
803
804
805
806
807
808
809
810
811
812
813
else
return -EINVAL;
while (*pem_header == '\r' || *pem_header == '\n')
pem_header++;
if (strncmp(pem_header, "DEK-Info: ", 10)) {
vpn_progress(vpninfo, PRG_ERR,
_("Missing DEK-Info: header from OpenSSL encrypted key\n"));
return -EIO;
}
pem_header += 10;
Jun 29, 2012
Jun 29, 2012
814
815
816
817
818
p = strchr(pem_header, ',');
if (!p) {
vpn_progress(vpninfo, PRG_ERR,
_("Cannot determine PEM encryption type\n"));
return -EINVAL;
Jun 29, 2012
Jun 29, 2012
819
}
Jun 19, 2012
Jun 19, 2012
820
Jun 29, 2012
Jun 29, 2012
821
822
823
824
825
826
827
828
*p = 0;
cipher = gnutls_cipher_get_id(pem_header);
/* GnuTLS calls this '3DES-CBC' but all other names match */
if (cipher == GNUTLS_CIPHER_UNKNOWN &&
!strcmp(pem_header, "DES-EDE3-CBC"))
cipher = GNUTLS_CIPHER_3DES_CBC;
if (cipher == GNUTLS_CIPHER_UNKNOWN) {
Jun 19, 2012
Jun 19, 2012
829
830
831
832
833
vpn_progress(vpninfo, PRG_ERR,
_("Unsupported PEM encryption type: %s\n"),
pem_header);
return -EINVAL;
}
Jun 29, 2012
Jun 29, 2012
834
835
836
837
838
pem_header = p + 1;
/* No supported algorithms have an IV larger than this, and dynamically
allocating it would be painful. */
salt.size = 64;
Jun 19, 2012
Jun 19, 2012
839
840
841
842
843
844
845
846
847
848
849
salt.data = malloc(salt.size);
if (!salt.data)
return -ENOMEM;
for (i = 0; i < salt.size * 2; i++) {
unsigned char x;
char *c = &pem_header[i];
if (*c >= '0' && *c <= '9')
x = (*c) - '0';
else if (*c >= 'A' && *c <= 'F')
x = (*c) - 'A' + 10;
Jun 29, 2012
Jun 29, 2012
850
851
852
853
else if ((*c == '\r' || *c == '\n') && i >= 16 && !(i % 16)) {
salt.size = i / 2;
break;
} else {
Jun 19, 2012
Jun 19, 2012
854
855
856
857
858
859
860
861
862
863
864
865
866
867
vpn_progress(vpninfo, PRG_ERR,
_("Invalid salt in encrypted PEM file\n"));
ret = -EINVAL;
goto out_salt;
}
if (i & 1)
salt.data[i/2] |= x;
else
salt.data[i/2] = x << 4;
}
pem_header += salt.size * 2;
if (*pem_header != '\r' && *pem_header != '\n') {
vpn_progress(vpninfo, PRG_ERR,
Jun 29, 2012
Jun 29, 2012
868
_("Invalid salt in encrypted PEM file\n"));
Jun 19, 2012
Jun 19, 2012
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
ret = -EINVAL;
goto out_salt;
}
while (*pem_header == '\n' || *pem_header == '\r')
pem_header++;
/* pem_header should now point to the start of the base64 content.
Put a -----BEGIN banner in place before it, so that we can use
gnutls_pem_base64_decode_alloc(). The banner has to match the
-----END banner, so make sure we get it right... */
pem_header -= 6;
memcpy(pem_header, "-----\n", 6);
pem_header -= strlen(begin);
memcpy(pem_header, begin, strlen(begin));
pem_header -= 11;
memcpy(pem_header, "-----BEGIN ", 11);
constructed_pem.data = (void *)pem_header;
constructed_pem.size = pem_size - (pem_header - pem_start);
err = gnutls_pem_base64_decode_alloc(begin, &constructed_pem, &b64_data);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Error base64-decoding encrypted PEM file: %s\n"),
gnutls_strerror(err));
ret = -EINVAL;
goto out_salt;
}
if (b64_data.size < 16) {
/* Just to be sure our parsing is OK */
vpn_progress(vpninfo, PRG_ERR,
_("Encrypted PEM file too short\n"));
ret = -EINVAL;
goto out_b64;
}
ret = -ENOMEM;
enc_key.size = gnutls_cipher_get_key_size(cipher);
enc_key.data = malloc(enc_key.size);
if (!enc_key.data)
goto out_b64;
key_data = malloc(b64_data.size);
if (!key_data)
goto out_enc_key;
pass = vpninfo->cert_password;
vpninfo->cert_password = NULL;
while (1) {
memcpy(key_data, b64_data.data, b64_data.size);
ret = openssl_hash_password(vpninfo, pass, &enc_key, &salt);
if (ret)
goto out;
err = gnutls_cipher_init(&handle, cipher, &enc_key, &salt);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to initialise cipher for decrypting PEM file: %s\n"),
gnutls_strerror(err));
gnutls_cipher_deinit(handle);
ret = -EIO;
goto out;
}
err = gnutls_cipher_decrypt(handle, key_data, b64_data.size);
gnutls_cipher_deinit(handle);
if (err) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to decrypt PEM key: %s\n"),
gnutls_strerror(err));
ret = -EIO;
goto out;
}
/* We have to strip any padding for GnuTLS to accept it.
So a bit more ASN.1 parsing for us.
FIXME: Consolidate with similar code in gnutls_tpm.c */
if (key_data[0] == 0x30) {
gnutls_datum_t key_datum;
int blocksize = gnutls_cipher_get_block_size(cipher);
int keylen = key_data[1];
int ofs = 2;
if (keylen & 0x80) {
int lenlen = keylen & 0x7f;
keylen = 0;
if (lenlen > 3)
goto fail;
while (lenlen) {
keylen <<= 8;
keylen |= key_data[ofs++];
lenlen--;
}
}
keylen += ofs;
Aug 23, 2016
Aug 23, 2016
969
970
/* If there appears to be more or less padding than required, fail */
if (b64_data.size - keylen > blocksize || b64_data.size < keylen + 1)
Jun 19, 2012
Jun 19, 2012
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
goto fail;
/* If the padding bytes aren't all equal to the amount of padding, fail */
ofs = keylen;
while (ofs < b64_data.size) {
if (key_data[ofs] != b64_data.size - keylen)
goto fail;
ofs++;
}
key_datum.data = key_data;
key_datum.size = keylen;
err = gnutls_x509_privkey_import(key, &key_datum, GNUTLS_X509_FMT_DER);
if (!err) {
ret = 0;
goto out;
}
}
fail:
if (pass) {
vpn_progress(vpninfo, PRG_ERR, _("Decrypting PEM key failed\n"));
free(pass);
Mar 19, 2014
Mar 19, 2014
993
pass = NULL;
Jun 19, 2012
Jun 19, 2012
994
995
996
997
998
999
1000
}
err = request_passphrase(vpninfo, "openconnect_pem",
&pass, _("Enter PEM pass phrase:"));
if (err) {
ret = -EINVAL;
goto out;
}