1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1 |
/*
|
2 |
* OpenVPN -- An application to securely tunnel IP networks
|
|
3 |
* over a single TCP/UDP port, with support for SSL/TLS-based
|
|
4 |
* session authentication and key exchange,
|
|
5 |
* packet encryption, packet authentication, and
|
|
6 |
* packet compression.
|
|
7 |
*
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
8 |
* Copyright (C) 2002-2008 OpenVPN Solutions LLC <info@openvpn.net>
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
9 |
*
|
10 |
* This program is free software; you can redistribute it and/or modify
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
11 |
* it under the terms of the GNU General Public License version 2
|
12 |
* as published by the Free Software Foundation.
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
13 |
*
|
14 |
* This program is distributed in the hope that it will be useful,
|
|
15 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17 |
* GNU General Public License for more details.
|
|
18 |
*
|
|
19 |
* You should have received a copy of the GNU General Public License
|
|
20 |
* along with this program (see the file COPYING included with this
|
|
21 |
* distribution); if not, write to the Free Software Foundation, Inc.,
|
|
22 |
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
23 |
*/
|
|
24 |
||
25 |
/*
|
|
26 |
* The routines in this file deal with dynamically negotiating
|
|
27 |
* the data channel HMAC and cipher keys through a TLS session.
|
|
28 |
*
|
|
29 |
* Both the TLS session and the data channel are multiplexed
|
|
30 |
* over the same TCP/UDP port.
|
|
31 |
*/
|
|
32 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
33 |
#include "syshead.h" |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
34 |
|
35 |
#if defined(USE_CRYPTO) && defined(USE_SSL)
|
|
36 |
||
37 |
#include "ssl.h" |
|
38 |
#include "error.h" |
|
39 |
#include "common.h" |
|
40 |
#include "integer.h" |
|
41 |
#include "socket.h" |
|
42 |
#include "thread.h" |
|
43 |
#include "misc.h" |
|
44 |
#include "fdmisc.h" |
|
45 |
#include "interval.h" |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
46 |
#include "perf.h" |
47 |
#include "status.h" |
|
48 |
#include "gremlin.h" |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
49 |
#include "pkcs11.h" |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
50 |
#include "list.h" |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
51 |
|
52 |
#ifdef WIN32
|
|
53 |
#include "cryptoapi.h" |
|
54 |
#endif
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
55 |
|
56 |
#include "memdbg.h" |
|
57 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
58 |
#ifndef ENABLE_OCC
|
59 |
static const char ssl_default_options_string[] = "V0 UNDEF"; |
|
60 |
#endif
|
|
61 |
||
62 |
static inline const char * |
|
63 |
local_options_string (const struct tls_session *session) |
|
64 |
{
|
|
65 |
#ifdef ENABLE_OCC
|
|
66 |
return session->opt->local_options; |
|
67 |
#else
|
|
68 |
return ssl_default_options_string; |
|
69 |
#endif
|
|
70 |
}
|
|
71 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
72 |
#ifdef MEASURE_TLS_HANDSHAKE_STATS
|
73 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
74 |
static int tls_handshake_success; /* GLOBAL */ |
75 |
static int tls_handshake_error; /* GLOBAL */ |
|
76 |
static int tls_packets_generated; /* GLOBAL */ |
|
77 |
static int tls_packets_sent; /* GLOBAL */ |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
78 |
|
79 |
#define INCR_SENT ++tls_packets_sent
|
|
80 |
#define INCR_GENERATED ++tls_packets_generated
|
|
81 |
#define INCR_SUCCESS ++tls_handshake_success
|
|
82 |
#define INCR_ERROR ++tls_handshake_error
|
|
83 |
||
84 |
void
|
|
85 |
show_tls_performance_stats(void) |
|
86 |
{
|
|
87 |
msg (D_TLS_DEBUG_LOW, "TLS Handshakes, success=%f%% (good=%d, bad=%d), retransmits=%f%%", |
|
88 |
(double) tls_handshake_success / (tls_handshake_success + tls_handshake_error) * 100.0, |
|
89 |
tls_handshake_success, tls_handshake_error, |
|
90 |
(double) (tls_packets_sent - tls_packets_generated) / tls_packets_generated * 100.0); |
|
91 |
}
|
|
92 |
#else
|
|
93 |
||
94 |
#define INCR_SENT
|
|
95 |
#define INCR_GENERATED
|
|
96 |
#define INCR_SUCCESS
|
|
97 |
#define INCR_ERROR
|
|
98 |
||
99 |
#endif
|
|
100 |
||
101 |
#ifdef BIO_DEBUG
|
|
102 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
103 |
#warning BIO_DEBUG defined
|
104 |
||
105 |
static FILE *biofp; /* GLOBAL */ |
|
106 |
static bool biofp_toggle; /* GLOBAL */ |
|
107 |
static time_t biofp_last_open; /* GLOBAL */ |
|
108 |
static const int biofp_reopen_interval = 600; /* GLOBAL */ |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
109 |
|
110 |
static void |
|
111 |
close_biofp() |
|
112 |
{
|
|
113 |
if (biofp) |
|
114 |
{
|
|
115 |
ASSERT (!fclose (biofp)); |
|
116 |
biofp = NULL; |
|
117 |
}
|
|
118 |
}
|
|
119 |
||
120 |
static void |
|
121 |
open_biofp() |
|
122 |
{
|
|
123 |
const time_t current = time (NULL); |
|
124 |
const pid_t pid = getpid (); |
|
125 |
||
126 |
if (biofp_last_open + biofp_reopen_interval < current) |
|
127 |
close_biofp(); |
|
128 |
if (!biofp) |
|
129 |
{
|
|
130 |
char fn[256]; |
|
131 |
openvpn_snprintf(fn, sizeof(fn), "bio/%d-%d.log", pid, biofp_toggle); |
|
132 |
biofp = fopen (fn, "w"); |
|
133 |
ASSERT (biofp); |
|
134 |
biofp_last_open = time (NULL); |
|
135 |
biofp_toggle ^= 1; |
|
136 |
}
|
|
137 |
}
|
|
138 |
||
139 |
static void |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
140 |
bio_debug_data (const char *mode, BIO *bio, const uint8_t *buf, int len, const char *desc) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
141 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
142 |
struct gc_arena gc = gc_new (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
143 |
if (len > 0) |
144 |
{
|
|
145 |
open_biofp(); |
|
146 |
fprintf(biofp, "BIO_%s %s time=" time_format " bio=" ptr_format " len=%d data=%s\n", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
147 |
mode, desc, time (NULL), (ptr_type)bio, len, format_hex (buf, len, 0, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
148 |
fflush (biofp); |
149 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
150 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
151 |
}
|
152 |
||
153 |
static void |
|
154 |
bio_debug_oc (const char *mode, BIO *bio) |
|
155 |
{
|
|
156 |
open_biofp(); |
|
157 |
fprintf(biofp, "BIO %s time=" time_format " bio=" ptr_format "\n", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
158 |
mode, time (NULL), (ptr_type)bio); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
159 |
fflush (biofp); |
160 |
}
|
|
161 |
||
162 |
#endif
|
|
163 |
||
164 |
/*
|
|
165 |
* Max number of bytes we will add
|
|
166 |
* for data structures common to both
|
|
167 |
* data and control channel packets.
|
|
168 |
* (opcode only).
|
|
169 |
*/
|
|
170 |
void
|
|
171 |
tls_adjust_frame_parameters(struct frame *frame) |
|
172 |
{
|
|
173 |
frame_add_to_extra_frame (frame, 1); /* space for opcode */ |
|
174 |
}
|
|
175 |
||
176 |
/*
|
|
177 |
* Max number of bytes we will add
|
|
178 |
* to control channel packet.
|
|
179 |
*/
|
|
180 |
static void |
|
181 |
tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame, |
|
182 |
struct frame *frame) |
|
183 |
{
|
|
184 |
/*
|
|
185 |
* frame->extra_frame is already initialized with tls_auth buffer requirements,
|
|
186 |
* if --tls-auth is enabled.
|
|
187 |
*/
|
|
188 |
||
189 |
/* inherit link MTU and extra_link from data channel */
|
|
190 |
frame->link_mtu = data_channel_frame->link_mtu; |
|
191 |
frame->extra_link = data_channel_frame->extra_link; |
|
192 |
||
193 |
/* set extra_frame */
|
|
194 |
tls_adjust_frame_parameters (frame); |
|
195 |
reliable_ack_adjust_frame_parameters (frame, CONTROL_SEND_ACK_MAX); |
|
196 |
frame_add_to_extra_frame (frame, SID_SIZE + sizeof (packet_id_type)); |
|
197 |
||
198 |
/* set dynamic link MTU to minimum value */
|
|
199 |
frame_set_mtu_dynamic (frame, 0, SET_MTU_TUN); |
|
200 |
}
|
|
201 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
202 |
/*
|
203 |
* Allocate space in SSL objects
|
|
204 |
* in which to store a struct tls_session
|
|
205 |
* pointer back to parent.
|
|
206 |
*/
|
|
207 |
||
208 |
static int mydata_index; /* GLOBAL */ |
|
209 |
||
210 |
static void |
|
211 |
ssl_set_mydata_index () |
|
212 |
{
|
|
213 |
mydata_index = SSL_get_ex_new_index (0, "struct session *", NULL, NULL, NULL); |
|
214 |
ASSERT (mydata_index >= 0); |
|
215 |
}
|
|
216 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
217 |
void
|
218 |
init_ssl_lib () |
|
219 |
{
|
|
220 |
SSL_library_init (); |
|
221 |
SSL_load_error_strings (); |
|
222 |
OpenSSL_add_all_algorithms (); |
|
223 |
||
224 |
init_crypto_lib(); |
|
225 |
||
226 |
/*
|
|
227 |
* If you build the OpenSSL library and OpenVPN with
|
|
228 |
* CRYPTO_MDEBUG, you will get a listing of OpenSSL
|
|
229 |
* memory leaks on program termination.
|
|
230 |
*/
|
|
231 |
#ifdef CRYPTO_MDEBUG
|
|
232 |
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); |
|
233 |
#endif
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
234 |
|
235 |
ssl_set_mydata_index (); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
236 |
}
|
237 |
||
238 |
void
|
|
239 |
free_ssl_lib () |
|
240 |
{
|
|
241 |
#ifdef CRYPTO_MDEBUG
|
|
242 |
FILE* fp = fopen ("sdlog", "w"); |
|
243 |
ASSERT (fp); |
|
244 |
CRYPTO_mem_leaks_fp (fp); |
|
245 |
fclose (fp); |
|
246 |
#endif
|
|
247 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
248 |
uninit_crypto_lib (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
249 |
EVP_cleanup (); |
250 |
ERR_free_strings (); |
|
251 |
}
|
|
252 |
||
253 |
/*
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
254 |
* OpenSSL library calls pem_password_callback if the
|
255 |
* private key is protected by a password.
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
256 |
*/
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
257 |
|
258 |
static struct user_pass passbuf; /* GLOBAL */ |
|
259 |
||
260 |
void
|
|
261 |
pem_password_setup (const char *auth_file) |
|
262 |
{
|
|
263 |
if (!strlen (passbuf.password)) |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
264 |
get_user_pass (&passbuf, auth_file, UP_TYPE_PRIVATE_KEY, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_PASSWORD_ONLY); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
265 |
}
|
266 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
267 |
int
|
268 |
pem_password_callback (char *buf, int size, int rwflag, void *u) |
|
269 |
{
|
|
270 |
if (buf) |
|
271 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
272 |
/* prompt for password even if --askpass wasn't specified */
|
273 |
pem_password_setup (NULL); |
|
274 |
strncpynt (buf, passbuf.password, size); |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
275 |
purge_user_pass (&passbuf, false); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
276 |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
277 |
return strlen (buf); |
278 |
}
|
|
279 |
return 0; |
|
280 |
}
|
|
281 |
||
282 |
/*
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
283 |
* Auth username/password handling
|
284 |
*/
|
|
285 |
||
286 |
static bool auth_user_pass_enabled; /* GLOBAL */ |
|
287 |
static struct user_pass auth_user_pass; /* GLOBAL */ |
|
288 |
||
289 |
void
|
|
290 |
auth_user_pass_setup (const char *auth_file) |
|
291 |
{
|
|
292 |
auth_user_pass_enabled = true; |
|
293 |
if (!auth_user_pass.defined) |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
294 |
{
|
295 |
#if AUTO_USERID
|
|
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
296 |
get_user_pass_auto_userid (&auth_user_pass, auth_file); |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
297 |
#else
|
298 |
get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE); |
|
299 |
#endif
|
|
300 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
301 |
}
|
302 |
||
303 |
/*
|
|
304 |
* Disable password caching
|
|
305 |
*/
|
|
306 |
void
|
|
307 |
ssl_set_auth_nocache (void) |
|
308 |
{
|
|
309 |
passbuf.nocache = true; |
|
310 |
auth_user_pass.nocache = true; |
|
311 |
}
|
|
312 |
||
313 |
/*
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
314 |
* Forget private key password AND auth-user-pass username/password.
|
315 |
*/
|
|
316 |
void
|
|
317 |
ssl_purge_auth (void) |
|
318 |
{
|
|
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
319 |
#ifdef USE_PKCS11
|
320 |
pkcs11_logout (); |
|
321 |
#endif
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
322 |
purge_user_pass (&passbuf, true); |
323 |
purge_user_pass (&auth_user_pass, true); |
|
324 |
}
|
|
325 |
||
326 |
/*
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
327 |
* OpenSSL callback to get a temporary RSA key, mostly
|
328 |
* used for export ciphers.
|
|
329 |
*/
|
|
330 |
static RSA * |
|
331 |
tmp_rsa_cb (SSL * s, int is_export, int keylength) |
|
332 |
{
|
|
333 |
static RSA *rsa_tmp = NULL; |
|
334 |
if (rsa_tmp == NULL) |
|
335 |
{
|
|
336 |
msg (D_HANDSHAKE, "Generating temp (%d bit) RSA key", keylength); |
|
337 |
rsa_tmp = RSA_generate_key (keylength, RSA_F4, NULL, NULL); |
|
338 |
}
|
|
339 |
return (rsa_tmp); |
|
340 |
}
|
|
341 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
342 |
#ifdef USE_OLD_EXTRACT_X509_FIELD
|
343 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
344 |
/*
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
345 |
* Extract a field from an X509 subject name.
|
346 |
*
|
|
347 |
* Example:
|
|
348 |
*
|
|
349 |
* /C=US/ST=CO/L=Denver/O=ORG/CN=Test-CA/Email=jim@yonan.net
|
|
350 |
*
|
|
351 |
* The common name is 'Test-CA'
|
|
352 |
*/
|
|
353 |
static void |
|
354 |
extract_x509_field (const char *x509, const char *field_name, char *out, int size) |
|
355 |
{
|
|
356 |
char field_buf[256]; |
|
357 |
struct buffer x509_buf; |
|
358 |
||
359 |
ASSERT (size > 0); |
|
360 |
*out = '\0'; |
|
361 |
buf_set_read (&x509_buf, (uint8_t *)x509, strlen (x509)); |
|
362 |
while (buf_parse (&x509_buf, '/', field_buf, sizeof (field_buf))) |
|
363 |
{
|
|
364 |
struct buffer component_buf; |
|
365 |
char field_name_buf[64]; |
|
366 |
char field_value_buf[256]; |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
367 |
buf_set_read (&component_buf, (const uint8_t *) field_buf, strlen (field_buf)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
368 |
buf_parse (&component_buf, '=', field_name_buf, sizeof (field_name_buf)); |
369 |
buf_parse (&component_buf, '=', field_value_buf, sizeof (field_value_buf)); |
|
370 |
if (!strcmp (field_name_buf, field_name)) |
|
371 |
{
|
|
372 |
strncpynt (out, field_value_buf, size); |
|
373 |
break; |
|
374 |
}
|
|
375 |
}
|
|
376 |
}
|
|
377 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
378 |
#else
|
379 |
||
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
380 |
/*
|
381 |
* Extract a field from an X509 subject name.
|
|
382 |
*
|
|
383 |
* Example:
|
|
384 |
*
|
|
385 |
* /C=US/ST=CO/L=Denver/O=ORG/CN=First-CN/CN=Test-CA/Email=jim@yonan.net
|
|
386 |
*
|
|
387 |
* The common name is 'Test-CA'
|
|
388 |
*/
|
|
389 |
static void |
|
390 |
extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, int size) |
|
391 |
{
|
|
392 |
int lastpos = -1; |
|
393 |
int tmp = -1; |
|
394 |
X509_NAME_ENTRY *x509ne = 0; |
|
395 |
ASN1_STRING *asn1 = 0; |
|
396 |
unsigned char *buf = 0; |
|
397 |
int nid = OBJ_txt2nid(field_name); |
|
398 |
||
399 |
ASSERT (size > 0); |
|
400 |
*out = '\0'; |
|
401 |
do { |
|
402 |
lastpos = tmp; |
|
403 |
tmp = X509_NAME_get_index_by_NID(x509, nid, lastpos); |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
404 |
} while (tmp > -1); |
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
405 |
|
406 |
/* Nothing found */
|
|
407 |
if (lastpos == -1) |
|
408 |
return; |
|
409 |
||
410 |
x509ne = X509_NAME_get_entry(x509, lastpos); |
|
411 |
if (!x509ne) |
|
412 |
return; |
|
413 |
||
414 |
asn1 = X509_NAME_ENTRY_get_data(x509ne); |
|
415 |
if (!asn1) |
|
416 |
return; |
|
417 |
tmp = ASN1_STRING_to_UTF8(&buf, asn1); |
|
418 |
if (tmp <= 0) |
|
419 |
return; |
|
420 |
||
421 |
strncpynt(out, (char *)buf, size); |
|
422 |
OPENSSL_free(buf); |
|
423 |
}
|
|
424 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
425 |
#endif
|
426 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
427 |
static void |
428 |
setenv_untrusted (struct tls_session *session) |
|
429 |
{
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
430 |
setenv_link_socket_actual (session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
431 |
}
|
432 |
||
433 |
static void |
|
434 |
set_common_name (struct tls_session *session, const char *common_name) |
|
435 |
{
|
|
436 |
if (session->common_name) |
|
437 |
{
|
|
438 |
free (session->common_name); |
|
439 |
session->common_name = NULL; |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
440 |
#ifdef ENABLE_PF
|
441 |
session->common_name_hashval = 0; |
|
442 |
#endif
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
443 |
}
|
444 |
if (common_name) |
|
445 |
{
|
|
446 |
session->common_name = string_alloc (common_name, NULL); |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
447 |
#ifdef ENABLE_PF
|
448 |
{
|
|
449 |
const uint32_t len = (uint32_t) strlen (common_name); |
|
450 |
if (len) |
|
451 |
session->common_name_hashval = hash_func ((const uint8_t*)common_name, len+1, 0); |
|
452 |
else
|
|
453 |
session->common_name_hashval = 0; |
|
454 |
}
|
|
455 |
#endif
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
456 |
}
|
457 |
}
|
|
458 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
459 |
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
460 |
||
461 |
bool verify_cert_eku (X509 *x509, const char * const expected_oid) { |
|
462 |
||
463 |
EXTENDED_KEY_USAGE *eku = NULL; |
|
464 |
bool fFound = false; |
|
465 |
||
466 |
if ((eku = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i (x509, NID_ext_key_usage, NULL, NULL)) == NULL) { |
|
467 |
msg (D_HANDSHAKE, "Certificate does not have extended key usage extension"); |
|
468 |
}
|
|
469 |
else { |
|
470 |
int i; |
|
471 |
||
472 |
msg (D_HANDSHAKE, "Validating certificate extended key usage"); |
|
473 |
for(i = 0; !fFound && i < sk_ASN1_OBJECT_num (eku); i++) { |
|
474 |
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value (eku, i); |
|
475 |
char szOid[1024]; |
|
476 |
||
477 |
if (!fFound && OBJ_obj2txt (szOid, sizeof (szOid), oid, 0) != -1) { |
|
478 |
msg (D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", szOid, expected_oid); |
|
479 |
if (!strcmp (expected_oid, szOid)) { |
|
480 |
fFound = true; |
|
481 |
}
|
|
482 |
}
|
|
483 |
if (!fFound && OBJ_obj2txt (szOid, sizeof (szOid), oid, 1) != -1) { |
|
484 |
msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", szOid, expected_oid); |
|
485 |
if (!strcmp (expected_oid, szOid)) { |
|
486 |
fFound = true; |
|
487 |
}
|
|
488 |
}
|
|
489 |
}
|
|
490 |
}
|
|
491 |
||
492 |
if (eku != NULL) { |
|
493 |
sk_ASN1_OBJECT_pop_free (eku, ASN1_OBJECT_free); |
|
494 |
}
|
|
495 |
||
496 |
return fFound; |
|
497 |
}
|
|
498 |
||
499 |
bool verify_cert_ku (X509 *x509, const unsigned * const expected_ku, int expected_len) { |
|
500 |
||
501 |
ASN1_BIT_STRING *ku = NULL; |
|
502 |
bool fFound = false; |
|
503 |
||
504 |
if ((ku = (ASN1_BIT_STRING *)X509_get_ext_d2i (x509, NID_key_usage, NULL, NULL)) == NULL) { |
|
505 |
msg (D_HANDSHAKE, "Certificate does not have key usage extension"); |
|
506 |
}
|
|
507 |
else { |
|
508 |
unsigned nku = 0; |
|
509 |
int i; |
|
510 |
for (i=0;i<8;i++) { |
|
511 |
if (ASN1_BIT_STRING_get_bit (ku, i)) { |
|
512 |
nku |= 1<<(7-i); |
|
513 |
}
|
|
514 |
}
|
|
515 |
||
516 |
/*
|
|
517 |
* Fixup if no LSB bits
|
|
518 |
*/
|
|
519 |
if ((nku & 0xff) == 0) { |
|
520 |
nku >>= 8; |
|
521 |
}
|
|
522 |
||
523 |
msg (D_HANDSHAKE, "Validating certificate key usage"); |
|
524 |
for (i=0;!fFound && i<expected_len;i++) { |
|
525 |
if (expected_ku[i] != 0) { |
|
526 |
msg (D_HANDSHAKE, "++ Certificate has key usage %04x, expects %04x", nku, expected_ku[i]); |
|
527 |
||
528 |
if (nku == expected_ku[i]) { |
|
529 |
fFound = true; |
|
530 |
}
|
|
531 |
}
|
|
532 |
}
|
|
533 |
}
|
|
534 |
||
535 |
if (ku != NULL) { |
|
536 |
ASN1_BIT_STRING_free (ku); |
|
537 |
}
|
|
538 |
||
539 |
return fFound; |
|
540 |
}
|
|
541 |
||
542 |
#endif /* OPENSSL_VERSION_NUMBER */ |
|
543 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
544 |
/*
|
545 |
* nsCertType checking
|
|
546 |
*/
|
|
547 |
||
548 |
#define verify_nsCertType(x, usage) (((x)->ex_flags & EXFLAG_NSCERT) && ((x)->ex_nscert & (usage)))
|
|
549 |
||
550 |
static const char * |
|
551 |
print_nsCertType (int type) |
|
552 |
{
|
|
553 |
switch (type) |
|
554 |
{
|
|
555 |
case NS_SSL_SERVER: |
|
556 |
return "SERVER"; |
|
557 |
case NS_SSL_CLIENT: |
|
558 |
return "CLIENT"; |
|
559 |
default: |
|
560 |
return "?"; |
|
561 |
}
|
|
562 |
}
|
|
563 |
||
564 |
/*
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
565 |
* Our verify callback function -- check
|
566 |
* that an incoming peer certificate is good.
|
|
567 |
*/
|
|
568 |
||
569 |
static int |
|
570 |
verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
|
571 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
572 |
char subject[256]; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
573 |
char envname[64]; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
574 |
char common_name[TLS_CN_LEN]; |
575 |
SSL *ssl; |
|
576 |
struct tls_session *session; |
|
577 |
const struct tls_options *opt; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
578 |
const int max_depth = 8; |
579 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
580 |
/* get the tls_session pointer */
|
581 |
ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); |
|
582 |
ASSERT (ssl); |
|
583 |
session = (struct tls_session *) SSL_get_ex_data (ssl, mydata_index); |
|
584 |
ASSERT (session); |
|
585 |
opt = session->opt; |
|
586 |
ASSERT (opt); |
|
587 |
||
588 |
session->verified = false; |
|
589 |
||
590 |
/* get the X509 name */
|
|
591 |
X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), subject, |
|
592 |
sizeof (subject)); |
|
593 |
subject[sizeof (subject) - 1] = '\0'; |
|
594 |
||
595 |
/* enforce character class restrictions in X509 name */
|
|
596 |
string_mod (subject, X509_NAME_CHAR_CLASS, 0, '_'); |
|
597 |
||
598 |
/* extract the common name */
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
599 |
#ifdef USE_OLD_EXTRACT_X509_FIELD
|
600 |
extract_x509_field (subject, "CN", common_name, TLS_CN_LEN); |
|
601 |
#else
|
|
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
602 |
extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN); |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
603 |
#endif
|
604 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
605 |
string_mod (common_name, COMMON_NAME_CHAR_CLASS, 0, '_'); |
606 |
||
607 |
#if 0 /* print some debugging info */ |
|
608 |
msg (D_LOW, "LOCAL OPT: %s", opt->local_options);
|
|
609 |
msg (D_LOW, "X509: %s", subject);
|
|
610 |
#endif
|
|
611 |
||
612 |
/* did peer present cert which was signed our root cert? */
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
613 |
if (!preverify_ok) |
614 |
{
|
|
615 |
/* Remote site specified a certificate, but it's not correct */
|
|
616 |
msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
617 |
ctx->error_depth, X509_verify_cert_error_string (ctx->error), subject); |
618 |
goto err; /* Reject connection */ |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
619 |
}
|
620 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
621 |
/* warn if cert chain is too deep */
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
622 |
if (ctx->error_depth >= max_depth) |
623 |
msg (M_WARN, "TLS Warning: Convoluted certificate chain detected with depth [%d] greater than %d", ctx->error_depth, max_depth); |
|
624 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
625 |
/* save common name in session object */
|
626 |
if (ctx->error_depth == 0) |
|
627 |
set_common_name (session, common_name); |
|
628 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
629 |
/* export subject name string as environmental variable */
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
630 |
session->verify_maxlevel = max_int (session->verify_maxlevel, ctx->error_depth); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
631 |
openvpn_snprintf (envname, sizeof(envname), "tls_id_%d", ctx->error_depth); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
632 |
setenv_str (opt->es, envname, subject); |
633 |
||
634 |
#if 0
|
|
635 |
/* export common name string as environmental variable */
|
|
636 |
openvpn_snprintf (envname, sizeof(envname), "tls_common_name_%d", ctx->error_depth);
|
|
637 |
setenv_str (opt->es, envname, common_name);
|
|
638 |
#endif
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
639 |
|
640 |
/* export serial number as environmental variable */
|
|
641 |
{
|
|
642 |
const int serial = (int) ASN1_INTEGER_get (X509_get_serialNumber (ctx->current_cert)); |
|
643 |
openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", ctx->error_depth); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
644 |
setenv_int (opt->es, envname, serial); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
645 |
}
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
646 |
|
647 |
/* export current untrusted IP */
|
|
648 |
setenv_untrusted (session); |
|
649 |
||
650 |
/* verify certificate nsCertType */
|
|
651 |
if (opt->ns_cert_type && ctx->error_depth == 0) |
|
652 |
{
|
|
653 |
if (verify_nsCertType (ctx->current_cert, opt->ns_cert_type)) |
|
654 |
{
|
|
655 |
msg (D_HANDSHAKE, "VERIFY OK: nsCertType=%s", |
|
656 |
print_nsCertType (opt->ns_cert_type)); |
|
657 |
}
|
|
658 |
else
|
|
659 |
{
|
|
660 |
msg (D_HANDSHAKE, "VERIFY nsCertType ERROR: %s, require nsCertType=%s", |
|
661 |
subject, print_nsCertType (opt->ns_cert_type)); |
|
662 |
goto err; /* Reject connection */ |
|
663 |
}
|
|
664 |
}
|
|
665 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
666 |
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
667 |
||
668 |
/* verify certificate ku */
|
|
669 |
if (opt->remote_cert_ku[0] != 0 && ctx->error_depth == 0) |
|
670 |
{
|
|
671 |
if (verify_cert_ku (ctx->current_cert, opt->remote_cert_ku, MAX_PARMS)) |
|
672 |
{
|
|
673 |
msg (D_HANDSHAKE, "VERIFY KU OK"); |
|
674 |
}
|
|
675 |
else
|
|
676 |
{
|
|
677 |
msg (D_HANDSHAKE, "VERIFY KU ERROR"); |
|
678 |
goto err; /* Reject connection */ |
|
679 |
}
|
|
680 |
}
|
|
681 |
||
682 |
/* verify certificate eku */
|
|
683 |
if (opt->remote_cert_eku != NULL && ctx->error_depth == 0) |
|
684 |
{
|
|
685 |
if (verify_cert_eku (ctx->current_cert, opt->remote_cert_eku)) |
|
686 |
{
|
|
687 |
msg (D_HANDSHAKE, "VERIFY EKU OK"); |
|
688 |
}
|
|
689 |
else
|
|
690 |
{
|
|
691 |
msg (D_HANDSHAKE, "VERIFY EKU ERROR"); |
|
692 |
goto err; /* Reject connection */ |
|
693 |
}
|
|
694 |
}
|
|
695 |
||
696 |
#endif /* OPENSSL_VERSION_NUMBER */ |
|
697 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
698 |
/* verify X509 name or common name against --tls-remote */
|
699 |
if (opt->verify_x509name && strlen (opt->verify_x509name) > 0 && ctx->error_depth == 0) |
|
700 |
{
|
|
701 |
if (strcmp (opt->verify_x509name, subject) == 0 |
|
702 |
|| strncmp (opt->verify_x509name, common_name, strlen (opt->verify_x509name)) == 0) |
|
703 |
msg (D_HANDSHAKE, "VERIFY X509NAME OK: %s", subject); |
|
704 |
else
|
|
705 |
{
|
|
706 |
msg (D_HANDSHAKE, "VERIFY X509NAME ERROR: %s, must be %s", |
|
707 |
subject, opt->verify_x509name); |
|
708 |
goto err; /* Reject connection */ |
|
709 |
}
|
|
710 |
}
|
|
711 |
||
712 |
/* call --tls-verify plug-in(s) */
|
|
713 |
if (plugin_defined (opt->plugins, OPENVPN_PLUGIN_TLS_VERIFY)) |
|
714 |
{
|
|
715 |
char command[256]; |
|
716 |
struct buffer out; |
|
717 |
int ret; |
|
718 |
||
719 |
buf_set_write (&out, (uint8_t*)command, sizeof (command)); |
|
720 |
buf_printf (&out, "%d %s", |
|
721 |
ctx->error_depth, |
|
722 |
subject); |
|
723 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
724 |
ret = plugin_call (opt->plugins, OPENVPN_PLUGIN_TLS_VERIFY, command, NULL, opt->es); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
725 |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
726 |
if (ret == OPENVPN_PLUGIN_FUNC_SUCCESS) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
727 |
{
|
728 |
msg (D_HANDSHAKE, "VERIFY PLUGIN OK: depth=%d, %s", |
|
729 |
ctx->error_depth, subject); |
|
730 |
}
|
|
731 |
else
|
|
732 |
{
|
|
733 |
msg (D_HANDSHAKE, "VERIFY PLUGIN ERROR: depth=%d, %s", |
|
734 |
ctx->error_depth, subject); |
|
735 |
goto err; /* Reject connection */ |
|
736 |
}
|
|
737 |
}
|
|
738 |
||
739 |
/* run --tls-verify script */
|
|
740 |
if (opt->verify_command) |
|
741 |
{
|
|
742 |
char command[256]; |
|
743 |
struct buffer out; |
|
744 |
int ret; |
|
745 |
||
746 |
setenv_str (opt->es, "script_type", "tls-verify"); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
747 |
|
748 |
buf_set_write (&out, (uint8_t*)command, sizeof (command)); |
|
749 |
buf_printf (&out, "%s %d %s", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
750 |
opt->verify_command, |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
751 |
ctx->error_depth, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
752 |
subject); |
753 |
dmsg (D_TLS_DEBUG, "TLS: executing verify command: %s", command); |
|
754 |
ret = openvpn_system (command, opt->es, S_SCRIPT); |
|
755 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
756 |
if (system_ok (ret)) |
757 |
{
|
|
758 |
msg (D_HANDSHAKE, "VERIFY SCRIPT OK: depth=%d, %s", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
759 |
ctx->error_depth, subject); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
760 |
}
|
761 |
else
|
|
762 |
{
|
|
763 |
if (!system_executed (ret)) |
|
764 |
msg (M_ERR, "Verify command failed to execute: %s", command); |
|
765 |
msg (D_HANDSHAKE, "VERIFY SCRIPT ERROR: depth=%d, %s", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
766 |
ctx->error_depth, subject); |
767 |
goto err; /* Reject connection */ |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
768 |
}
|
769 |
}
|
|
770 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
771 |
/* check peer cert against CRL */
|
772 |
if (opt->crl_file) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
773 |
{
|
774 |
X509_CRL *crl=NULL; |
|
775 |
X509_REVOKED *revoked; |
|
776 |
BIO *in=NULL; |
|
777 |
int n,i,retval = 0; |
|
778 |
||
779 |
in=BIO_new(BIO_s_file()); |
|
780 |
||
781 |
if (in == NULL) { |
|
782 |
msg (M_ERR, "CRL: BIO err"); |
|
783 |
goto end; |
|
784 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
785 |
if (BIO_read_filename(in, opt->crl_file) <= 0) { |
786 |
msg (M_ERR, "CRL: cannot read: %s", opt->crl_file); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
787 |
goto end; |
788 |
}
|
|
789 |
crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); |
|
790 |
if (crl == NULL) { |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
791 |
msg (M_ERR, "CRL: cannot read CRL from file %s", opt->crl_file); |
792 |
goto end; |
|
793 |
}
|
|
794 |
||
795 |
if (X509_NAME_cmp(X509_CRL_get_issuer(crl), X509_get_issuer_name(ctx->current_cert)) != 0) { |
|
796 |
msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of certificate %s", opt->crl_file, subject); |
|
797 |
retval = 1; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
798 |
goto end; |
799 |
}
|
|
800 |
||
801 |
n = sk_num(X509_CRL_get_REVOKED(crl)); |
|
802 |
||
803 |
for (i = 0; i < n; i++) { |
|
804 |
revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i); |
|
805 |
if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(ctx->current_cert)) == 0) { |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
806 |
msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
807 |
goto end; |
808 |
}
|
|
809 |
}
|
|
810 |
||
811 |
retval = 1; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
812 |
msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
813 |
|
814 |
end: |
|
815 |
||
816 |
BIO_free(in); |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
817 |
if (crl) |
818 |
X509_CRL_free (crl); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
819 |
if (!retval) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
820 |
goto err; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
821 |
}
|
822 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
823 |
msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", ctx->error_depth, subject); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
824 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
825 |
session->verified = true; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
826 |
return 1; /* Accept connection */ |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
827 |
|
828 |
err: |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
829 |
ERR_clear_error (); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
830 |
return 0; /* Reject connection */ |
831 |
}
|
|
832 |
||
833 |
void
|
|
834 |
tls_set_common_name (struct tls_multi *multi, const char *common_name) |
|
835 |
{
|
|
836 |
if (multi) |
|
837 |
set_common_name (&multi->session[TM_ACTIVE], common_name); |
|
838 |
}
|
|
839 |
||
840 |
const char * |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
841 |
tls_common_name (const struct tls_multi *multi, const bool null) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
842 |
{
|
843 |
const char *ret = NULL; |
|
844 |
if (multi) |
|
845 |
ret = multi->session[TM_ACTIVE].common_name; |
|
846 |
if (ret && strlen (ret)) |
|
847 |
return ret; |
|
848 |
else if (null) |
|
849 |
return NULL; |
|
850 |
else
|
|
851 |
return "UNDEF"; |
|
852 |
}
|
|
853 |
||
854 |
void
|
|
855 |
tls_lock_common_name (struct tls_multi *multi) |
|
856 |
{
|
|
857 |
const char *cn = multi->session[TM_ACTIVE].common_name; |
|
858 |
if (cn && !multi->locked_cn) |
|
859 |
multi->locked_cn = string_alloc (cn, NULL); |
|
860 |
}
|
|
861 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
862 |
#ifdef ENABLE_DEF_AUTH
|
863 |
/* key_state_test_auth_control_file return values,
|
|
864 |
NOTE: acf_merge indexing depends on these values */
|
|
865 |
#define ACF_UNDEFINED 0
|
|
866 |
#define ACF_SUCCEEDED 1
|
|
867 |
#define ACF_DISABLED 2
|
|
868 |
#define ACF_FAILED 3
|
|
869 |
#endif
|
|
870 |
||
871 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
872 |
static inline unsigned int |
|
873 |
man_def_auth_test (const struct key_state *ks) |
|
874 |
{
|
|
875 |
if (management_enable_def_auth (management)) |
|
876 |
return ks->mda_status; |
|
877 |
else
|
|
878 |
return ACF_DISABLED; |
|
879 |
}
|
|
880 |
#endif
|
|
881 |
||
882 |
#ifdef PLUGIN_DEF_AUTH
|
|
883 |
||
884 |
/*
|
|
885 |
* auth_control_file functions
|
|
886 |
*/
|
|
887 |
||
888 |
static void |
|
889 |
key_state_rm_auth_control_file (struct key_state *ks) |
|
890 |
{
|
|
891 |
if (ks && ks->auth_control_file) |
|
892 |
{
|
|
893 |
delete_file (ks->auth_control_file); |
|
894 |
free (ks->auth_control_file); |
|
895 |
ks->auth_control_file = NULL; |
|
896 |
}
|
|
897 |
}
|
|
898 |
||
899 |
static void |
|
900 |
key_state_gen_auth_control_file (struct key_state *ks, const struct tls_options *opt) |
|
901 |
{
|
|
902 |
struct gc_arena gc = gc_new (); |
|
903 |
const char *acf; |
|
904 |
||
905 |
key_state_rm_auth_control_file (ks); |
|
906 |
acf = create_temp_filename (opt->tmp_dir, "acf", &gc); |
|
907 |
ks->auth_control_file = string_alloc (acf, NULL); |
|
908 |
setenv_str (opt->es, "auth_control_file", ks->auth_control_file); |
|
909 |
||
910 |
gc_free (&gc); |
|
911 |
}
|
|
912 |
||
913 |
static unsigned int |
|
914 |
key_state_test_auth_control_file (struct key_state *ks) |
|
915 |
{
|
|
916 |
if (ks && ks->auth_control_file) |
|
917 |
{
|
|
918 |
unsigned int ret = ks->auth_control_status; |
|
919 |
if (ret == ACF_UNDEFINED) |
|
920 |
{
|
|
921 |
FILE *fp = fopen (ks->auth_control_file, "r"); |
|
922 |
if (fp) |
|
923 |
{
|
|
924 |
const int c = fgetc (fp); |
|
925 |
if (c == '1') |
|
926 |
ret = ACF_SUCCEEDED; |
|
927 |
else if (c == '0') |
|
928 |
ret = ACF_FAILED; |
|
929 |
fclose (fp); |
|
930 |
ks->auth_control_status = ret; |
|
931 |
}
|
|
932 |
}
|
|
933 |
return ret; |
|
934 |
}
|
|
935 |
return ACF_DISABLED; |
|
936 |
}
|
|
937 |
||
938 |
#endif
|
|
939 |
||
940 |
/*
|
|
941 |
* Return current session authentication state. Return
|
|
942 |
* value is TLS_AUTHENTICATION_x.
|
|
943 |
*/
|
|
944 |
||
945 |
int
|
|
946 |
tls_authentication_status (struct tls_multi *multi, const int latency) |
|
947 |
{
|
|
948 |
bool deferred = false; |
|
949 |
bool success = false; |
|
950 |
bool active = false; |
|
951 |
||
952 |
#ifdef ENABLE_DEF_AUTH
|
|
953 |
static const unsigned char acf_merge[] = |
|
954 |
{
|
|
955 |
ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_UNDEFINED */ |
|
956 |
ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_SUCCEEDED */ |
|
957 |
ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_DISABLED */ |
|
958 |
ACF_FAILED, /* s1=ACF_UNDEFINED s2=ACF_FAILED */ |
|
959 |
ACF_UNDEFINED, /* s1=ACF_SUCCEEDED s2=ACF_UNDEFINED */ |
|
960 |
ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_SUCCEEDED */ |
|
961 |
ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_DISABLED */ |
|
962 |
ACF_FAILED, /* s1=ACF_SUCCEEDED s2=ACF_FAILED */ |
|
963 |
ACF_UNDEFINED, /* s1=ACF_DISABLED s2=ACF_UNDEFINED */ |
|
964 |
ACF_SUCCEEDED, /* s1=ACF_DISABLED s2=ACF_SUCCEEDED */ |
|
965 |
ACF_DISABLED, /* s1=ACF_DISABLED s2=ACF_DISABLED */ |
|
966 |
ACF_FAILED, /* s1=ACF_DISABLED s2=ACF_FAILED */ |
|
967 |
ACF_FAILED, /* s1=ACF_FAILED s2=ACF_UNDEFINED */ |
|
968 |
ACF_FAILED, /* s1=ACF_FAILED s2=ACF_SUCCEEDED */ |
|
969 |
ACF_FAILED, /* s1=ACF_FAILED s2=ACF_DISABLED */ |
|
970 |
ACF_FAILED /* s1=ACF_FAILED s2=ACF_FAILED */ |
|
971 |
};
|
|
972 |
#endif
|
|
973 |
||
974 |
if (multi) |
|
975 |
{
|
|
976 |
int i; |
|
977 |
||
978 |
#ifdef ENABLE_DEF_AUTH
|
|
979 |
if (latency && multi->tas_last && multi->tas_last + latency >= now) |
|
980 |
return TLS_AUTHENTICATION_UNDEFINED; |
|
981 |
multi->tas_last = now; |
|
982 |
#endif
|
|
983 |
||
984 |
for (i = 0; i < KEY_SCAN_SIZE; ++i) |
|
985 |
{
|
|
986 |
struct key_state *ks = multi->key_scan[i]; |
|
987 |
if (DECRYPT_KEY_ENABLED (multi, ks)) |
|
988 |
{
|
|
989 |
active = true; |
|
990 |
if (ks->authenticated) |
|
991 |
{
|
|
992 |
#ifdef ENABLE_DEF_AUTH
|
|
993 |
unsigned int s1 = ACF_DISABLED; |
|
994 |
unsigned int s2 = ACF_DISABLED; |
|
995 |
#ifdef PLUGIN_DEF_AUTH
|
|
996 |
s1 = key_state_test_auth_control_file (ks); |
|
997 |
#endif
|
|
998 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
999 |
s2 = man_def_auth_test (ks); |
|
1000 |
#endif
|
|
1001 |
ASSERT (s1 < 4 && s2 < 4); |
|
1002 |
switch (acf_merge[(s1<<2) + s2]) |
|
1003 |
{
|
|
1004 |
case ACF_SUCCEEDED: |
|
1005 |
case ACF_DISABLED: |
|
1006 |
success = true; |
|
1007 |
ks->auth_deferred = false; |
|
1008 |
break; |
|
1009 |
case ACF_UNDEFINED: |
|
1010 |
if (now < ks->auth_deferred_expire) |
|
1011 |
deferred = true; |
|
1012 |
break; |
|
1013 |
case ACF_FAILED: |
|
1014 |
ks->authenticated = false; |
|
1015 |
break; |
|
1016 |
default: |
|
1017 |
ASSERT (0); |
|
1018 |
}
|
|
1019 |
#else
|
|
1020 |
success = true; |
|
1021 |
#endif
|
|
1022 |
}
|
|
1023 |
}
|
|
1024 |
}
|
|
1025 |
}
|
|
1026 |
||
1027 |
#if 0
|
|
1028 |
dmsg (D_TLS_ERRORS, "TAS: a=%d s=%d d=%d", active, success, deferred);
|
|
1029 |
#endif
|
|
1030 |
||
1031 |
if (success) |
|
1032 |
return TLS_AUTHENTICATION_SUCCEEDED; |
|
1033 |
else if (!active || deferred) |
|
1034 |
return TLS_AUTHENTICATION_DEFERRED; |
|
1035 |
else
|
|
1036 |
return TLS_AUTHENTICATION_FAILED; |
|
1037 |
}
|
|
1038 |
||
1039 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1040 |
bool
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1041 |
tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1042 |
{
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1043 |
bool ret = false; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1044 |
if (multi) |
1045 |
{
|
|
1046 |
int i; |
|
1047 |
for (i = 0; i < KEY_SCAN_SIZE; ++i) |
|
1048 |
{
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1049 |
struct key_state *ks = multi->key_scan[i]; |
1050 |
if (ks->mda_key_id == mda_key_id) |
|
1051 |
{
|
|
1052 |
ks->mda_status = auth ? ACF_SUCCEEDED : ACF_FAILED; |
|
1053 |
ret = true; |
|
1054 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1055 |
}
|
1056 |
}
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1057 |
return ret; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1058 |
}
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1059 |
#endif
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1060 |
|
1061 |
void
|
|
1062 |
tls_deauthenticate (struct tls_multi *multi) |
|
1063 |
{
|
|
1064 |
if (multi) |
|
1065 |
{
|
|
1066 |
int i, j; |
|
1067 |
for (i = 0; i < TM_SIZE; ++i) |
|
1068 |
for (j = 0; j < KS_SIZE; ++j) |
|
1069 |
multi->session[i].key[j].authenticated = false; |
|
1070 |
}
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1071 |
}
|
1072 |
||
1073 |
/*
|
|
1074 |
* Print debugging information on SSL/TLS session negotiation.
|
|
1075 |
*/
|
|
1076 |
static void |
|
1077 |
info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret) |
|
1078 |
{
|
|
1079 |
if (where & SSL_CB_LOOP) |
|
1080 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1081 |
dmsg (D_HANDSHAKE_VERBOSE, "SSL state (%s): %s", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1082 |
where & SSL_ST_CONNECT ? "connect" : |
1083 |
where & SSL_ST_ACCEPT ? "accept" : |
|
1084 |
"undefined", SSL_state_string_long (s)); |
|
1085 |
}
|
|
1086 |
else if (where & SSL_CB_ALERT) |
|
1087 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1088 |
dmsg (D_HANDSHAKE_VERBOSE, "SSL alert (%s): %s: %s", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1089 |
where & SSL_CB_READ ? "read" : "write", |
1090 |
SSL_alert_type_string_long (ret), |
|
1091 |
SSL_alert_desc_string_long (ret)); |
|
1092 |
}
|
|
1093 |
}
|
|
1094 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1095 |
#if ENABLE_INLINE_FILES
|
1096 |
||
1097 |
static int |
|
1098 |
use_inline_load_verify_locations (SSL_CTX *ctx, const char *ca_string) |
|
1099 |
{
|
|
1100 |
X509_STORE *store = NULL; |
|
1101 |
X509* cert = NULL; |
|
1102 |
BIO *in = NULL; |
|
1103 |
int ret = 0; |
|
1104 |
||
1105 |
in = BIO_new_mem_buf ((char *)ca_string, -1); |
|
1106 |
if (!in) |
|
1107 |
goto err; |
|
1108 |
||
1109 |
for (;;) |
|
1110 |
{
|
|
1111 |
if (!PEM_read_bio_X509 (in, &cert, 0, NULL)) |
|
1112 |
{
|
|
1113 |
ret = 1; |
|
1114 |
break; |
|
1115 |
}
|
|
1116 |
if (!cert) |
|
1117 |
break; |
|
1118 |
||
1119 |
store = SSL_CTX_get_cert_store (ctx); |
|
1120 |
if (!store) |
|
1121 |
break; |
|
1122 |
||
1123 |
if (!X509_STORE_add_cert (store, cert)) |
|
1124 |
break; |
|
1125 |
||
1126 |
if (cert) |
|
1127 |
{
|
|
1128 |
X509_free (cert); |
|
1129 |
cert = NULL; |
|
1130 |
}
|
|
1131 |
}
|
|
1132 |
||
1133 |
err: |
|
1134 |
if (cert) |
|
1135 |
X509_free (cert); |
|
1136 |
if (in) |
|
1137 |
BIO_free (in); |
|
1138 |
return ret; |
|
1139 |
}
|
|
1140 |
||
1141 |
static int |
|
1142 |
xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) |
|
1143 |
{
|
|
1144 |
return(X509_NAME_cmp(*a,*b)); |
|
1145 |
}
|
|
1146 |
||
1147 |
static STACK_OF(X509_NAME) * |
|
1148 |
use_inline_load_client_CA_file (SSL_CTX *ctx, const char *ca_string) |
|
1149 |
{
|
|
1150 |
BIO *in = NULL; |
|
1151 |
X509 *x = NULL; |
|
1152 |
X509_NAME *xn = NULL; |
|
1153 |
STACK_OF(X509_NAME) *ret = NULL, *sk; |
|
1154 |
||
1155 |
sk=sk_X509_NAME_new(xname_cmp); |
|
1156 |
||
1157 |
in = BIO_new_mem_buf ((char *)ca_string, -1); |
|
1158 |
if (!in) |
|
1159 |
goto err; |
|
1160 |
||
1161 |
if ((sk == NULL) || (in == NULL)) |
|
1162 |
goto err; |
|
1163 |
||
1164 |
for (;;) |
|
1165 |
{
|
|
1166 |
if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) |
|
1167 |
break; |
|
1168 |
if (ret == NULL) |
|
1169 |
{
|
|
1170 |
ret = sk_X509_NAME_new_null(); |
|
1171 |
if (ret == NULL) |
|
1172 |
goto err; |
|
1173 |
}
|
|
1174 |
if ((xn=X509_get_subject_name(x)) == NULL) goto err; |
|
1175 |
/* check for duplicates */
|
|
1176 |
xn=X509_NAME_dup(xn); |
|
1177 |
if (xn == NULL) goto err; |
|
1178 |
if (sk_X509_NAME_find(sk,xn) >= 0) |
|
1179 |
X509_NAME_free(xn); |
|
1180 |
else
|
|
1181 |
{
|
|
1182 |
sk_X509_NAME_push(sk,xn); |
|
1183 |
sk_X509_NAME_push(ret,xn); |
|
1184 |
}
|
|
1185 |
}
|
|
1186 |
||
1187 |
if (0) |
|
1188 |
{
|
|
1189 |
err: |
|
1190 |
if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free); |
|
1191 |
ret=NULL; |
|
1192 |
}
|
|
1193 |
if (sk != NULL) sk_X509_NAME_free(sk); |
|
1194 |
if (in != NULL) BIO_free(in); |
|
1195 |
if (x != NULL) X509_free(x); |
|
1196 |
if (ret != NULL) |
|
1197 |
ERR_clear_error(); |
|
1198 |
return(ret); |
|
1199 |
}
|
|
1200 |
||
1201 |
static int |
|
1202 |
use_inline_certificate_file (SSL_CTX *ctx, const char *cert_string) |
|
1203 |
{
|
|
1204 |
BIO *in = NULL; |
|
1205 |
X509 *x = NULL; |
|
1206 |
int ret = 0; |
|
1207 |
||
1208 |
in = BIO_new_mem_buf ((char *)cert_string, -1); |
|
1209 |
if (!in) |
|
1210 |
goto end; |
|
1211 |
||
1212 |
x = PEM_read_bio_X509 (in, |
|
1213 |
NULL, |
|
1214 |
ctx->default_passwd_callback, |
|
1215 |
ctx->default_passwd_callback_userdata); |
|
1216 |
if (!x) |
|
1217 |
goto end; |
|
1218 |
||
1219 |
ret = SSL_CTX_use_certificate(ctx, x); |
|
1220 |
||
1221 |
end: |
|
1222 |
if (x) |
|
1223 |
X509_free (x); |
|
1224 |
if (in) |
|
1225 |
BIO_free (in); |
|
1226 |
return ret; |
|
1227 |
}
|
|
1228 |
||
1229 |
static int |
|
1230 |
use_inline_PrivateKey_file (SSL_CTX *ctx, const char *key_string) |
|
1231 |
{
|
|
1232 |
BIO *in = NULL; |
|
1233 |
EVP_PKEY *pkey = NULL; |
|
1234 |
int ret = 0; |
|
1235 |
||
1236 |
in = BIO_new_mem_buf ((char *)key_string, -1); |
|
1237 |
if (!in) |
|
1238 |
goto end; |
|
1239 |
||
1240 |
pkey = PEM_read_bio_PrivateKey (in, |
|
1241 |
NULL, |
|
1242 |
ctx->default_passwd_callback, |
|
1243 |
ctx->default_passwd_callback_userdata); |
|
1244 |
if (!pkey) |
|
1245 |
goto end; |
|
1246 |
||
1247 |
ret = SSL_CTX_use_PrivateKey (ctx, pkey); |
|
1248 |
||
1249 |
end: |
|
1250 |
if (pkey) |
|
1251 |
EVP_PKEY_free (pkey); |
|
1252 |
if (in) |
|
1253 |
BIO_free (in); |
|
1254 |
return ret; |
|
1255 |
}
|
|
1256 |
||
1257 |
#endif
|
|
1258 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1259 |
/*
|
1260 |
* Initialize SSL context.
|
|
1261 |
* All files are in PEM format.
|
|
1262 |
*/
|
|
1263 |
SSL_CTX * |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1264 |
init_ssl (const struct options *options) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1265 |
{
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1266 |
SSL_CTX *ctx = NULL; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1267 |
DH *dh; |
1268 |
BIO *bio; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1269 |
bool using_cert_file = false; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1270 |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1271 |
ERR_clear_error (); |
1272 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1273 |
if (options->tls_server) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1274 |
{
|
1275 |
ctx = SSL_CTX_new (TLSv1_server_method ()); |
|
1276 |
if (ctx == NULL) |
|
1277 |
msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method"); |
|
1278 |
||
1279 |
SSL_CTX_set_tmp_rsa_callback (ctx, tmp_rsa_cb); |
|
1280 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1281 |
#if ENABLE_INLINE_FILES
|
1282 |
if (!strcmp (options->dh_file, INLINE_FILE_TAG) && options->dh_file_inline) |
|
1283 |
{
|
|
1284 |
if (!(bio = BIO_new_mem_buf ((char *)options->dh_file_inline, -1))) |
|
1285 |
msg (M_SSLERR, "Cannot open memory BIO for inline DH parameters"); |
|
1286 |
}
|
|
1287 |
else
|
|
1288 |
#endif
|
|
1289 |
{
|
|
1290 |
/* Get Diffie Hellman Parameters */
|
|
1291 |
if (!(bio = BIO_new_file (options->dh_file, "r"))) |
|
1292 |
msg (M_SSLERR, "Cannot open %s for DH parameters", options->dh_file); |
|
1293 |
}
|
|
1294 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1295 |
dh = PEM_read_bio_DHparams (bio, NULL, NULL, NULL); |
1296 |
BIO_free (bio); |
|
1297 |
if (!dh) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1298 |
msg (M_SSLERR, "Cannot load DH parameters from %s", options->dh_file); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1299 |
if (!SSL_CTX_set_tmp_dh (ctx, dh)) |
1300 |
msg (M_SSLERR, "SSL_CTX_set_tmp_dh"); |
|
1301 |
msg (D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key", |
|
1302 |
8 * DH_size (dh)); |
|
1303 |
DH_free (dh); |
|
1304 |
}
|
|
1305 |
else /* if client */ |
|
1306 |
{
|
|
1307 |
ctx = SSL_CTX_new (TLSv1_client_method ()); |
|
1308 |
if (ctx == NULL) |
|
1309 |
msg (M_SSLERR, "SSL_CTX_new TLSv1_client_method"); |
|
1310 |
}
|
|
1311 |
||
1312 |
/* Set SSL options */
|
|
1313 |
SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_OFF); |
|
1314 |
SSL_CTX_set_options (ctx, SSL_OP_SINGLE_DH_USE); |
|
1315 |
||
1316 |
/* Set callback for getting password from user to decrypt private key */
|
|
1317 |
SSL_CTX_set_default_passwd_cb (ctx, pem_password_callback); |
|
1318 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1319 |
if (options->pkcs12_file) |
1320 |
{
|
|
1321 |
/* Use PKCS #12 file for key, cert and CA certs */
|
|
1322 |
||
1323 |
FILE *fp; |
|
1324 |
EVP_PKEY *pkey; |
|
1325 |
X509 *cert; |
|
1326 |
STACK_OF(X509) *ca = NULL; |
|
1327 |
PKCS12 *p12; |
|
1328 |
int i; |
|
1329 |
char password[256]; |
|
1330 |
||
1331 |
/* Load the PKCS #12 file */
|
|
1332 |
if (!(fp = fopen(options->pkcs12_file, "rb"))) |
|
1333 |
msg (M_SSLERR, "Error opening file %s", options->pkcs12_file); |
|
1334 |
p12 = d2i_PKCS12_fp(fp, NULL); |
|
1335 |
fclose (fp); |
|
1336 |
if (!p12) msg (M_SSLERR, "Error reading PKCS#12 file %s", options->pkcs12_file); |
|
1337 |
||
1338 |
/* Parse the PKCS #12 file */
|
|
1339 |
if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) |
|
1340 |
{
|
|
1341 |
pem_password_callback (password, sizeof(password) - 1, 0, NULL); |
|
1342 |
/* Reparse the PKCS #12 file with password */
|
|
1343 |
ca = NULL; |
|
1344 |
if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1345 |
{
|
1346 |
PKCS12_free(p12); |
|
1347 |
msg (M_WARN|M_SSL, "Error parsing PKCS#12 file %s", options->pkcs12_file); |
|
1348 |
goto err; |
|
1349 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1350 |
}
|
1351 |
PKCS12_free(p12); |
|
1352 |
||
1353 |
/* Load Certificate */
|
|
1354 |
if (!SSL_CTX_use_certificate (ctx, cert)) |
|
1355 |
msg (M_SSLERR, "Cannot use certificate"); |
|
1356 |
||
1357 |
/* Load Private Key */
|
|
1358 |
if (!SSL_CTX_use_PrivateKey (ctx, pkey)) |
|
1359 |
msg (M_SSLERR, "Cannot use private key"); |
|
1360 |
warn_if_group_others_accessible (options->pkcs12_file); |
|
1361 |
||
1362 |
/* Check Private Key */
|
|
1363 |
if (!SSL_CTX_check_private_key (ctx)) |
|
1364 |
msg (M_SSLERR, "Private key does not match the certificate"); |
|
1365 |
||
1366 |
/* Set Certificate Verification chain */
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1367 |
if (!options->ca_file) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1368 |
{
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1369 |
if (ca && sk_num(ca)) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1370 |
{
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1371 |
for (i = 0; i < sk_X509_num(ca); i++) |
1372 |
{
|
|
1373 |
if (!X509_STORE_add_cert(ctx->cert_store,sk_X509_value(ca, i))) |
|
1374 |
msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); |
|
1375 |
if (!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) |
|
1376 |
msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); |
|
1377 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1378 |
}
|
1379 |
}
|
|
1380 |
}
|
|
1381 |
else
|
|
1382 |
{
|
|
1383 |
/* Use seperate PEM files for key, cert and CA certs */
|
|
1384 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1385 |
#ifdef ENABLE_PKCS11
|
1386 |
if (options->pkcs11_providers[0]) |
|
1387 |
{
|
|
1388 |
/* Load Certificate and Private Key */
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1389 |
if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_id_management, options->pkcs11_id)) |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1390 |
{
|
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
1391 |
msg (M_WARN, "Cannot load certificate \"%s\" using PKCS#11 interface", options->pkcs11_id); |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1392 |
goto err; |
1393 |
}
|
|
1394 |
}
|
|
1395 |
else
|
|
1396 |
#endif
|
|
1397 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1398 |
#ifdef WIN32
|
1399 |
if (options->cryptoapi_cert) |
|
1400 |
{
|
|
1401 |
/* Load Certificate and Private Key */
|
|
1402 |
if (!SSL_CTX_use_CryptoAPI_certificate (ctx, options->cryptoapi_cert)) |
|
1403 |
msg (M_SSLERR, "Cannot load certificate \"%s\" from Microsoft Certificate Store", |
|
1404 |
options->cryptoapi_cert); |
|
1405 |
}
|
|
1406 |
else
|
|
1407 |
#endif
|
|
1408 |
{
|
|
1409 |
/* Load Certificate */
|
|
1410 |
if (options->cert_file) |
|
1411 |
{
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1412 |
#if ENABLE_INLINE_FILES
|
1413 |
if (!strcmp (options->cert_file, INLINE_FILE_TAG) && options->cert_file_inline) |
|
1414 |
{
|
|
1415 |
if (!use_inline_certificate_file (ctx, options->cert_file_inline)) |
|
1416 |
msg (M_SSLERR, "Cannot load inline certificate file"); |
|
1417 |
}
|
|
1418 |
else
|
|
1419 |
#endif
|
|
1420 |
{
|
|
1421 |
if (!SSL_CTX_use_certificate_file (ctx, options->cert_file, SSL_FILETYPE_PEM)) |
|
1422 |
msg (M_SSLERR, "Cannot load certificate file %s", options->cert_file); |
|
1423 |
using_cert_file = true; |
|
1424 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1425 |
}
|
1426 |
||
1427 |
/* Load Private Key */
|
|
1428 |
if (options->priv_key_file) |
|
1429 |
{
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1430 |
int status; |
1431 |
||
1432 |
#if ENABLE_INLINE_FILES
|
|
1433 |
if (!strcmp (options->priv_key_file, INLINE_FILE_TAG) && options->priv_key_file_inline) |
|
1434 |
{
|
|
1435 |
status = use_inline_PrivateKey_file (ctx, options->priv_key_file_inline); |
|
1436 |
}
|
|
1437 |
else
|
|
1438 |
#endif
|
|
1439 |
{
|
|
1440 |
status = SSL_CTX_use_PrivateKey_file (ctx, options->priv_key_file, SSL_FILETYPE_PEM); |
|
1441 |
}
|
|
1442 |
if (!status) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1443 |
{
|
1444 |
#ifdef ENABLE_MANAGEMENT
|
|
1445 |
if (management && (ERR_GET_REASON (ERR_peek_error()) == EVP_R_BAD_DECRYPT)) |
|
1446 |
management_auth_failure (management, UP_TYPE_PRIVATE_KEY); |
|
1447 |
#endif
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1448 |
msg (M_WARN|M_SSL, "Cannot load private key file %s", options->priv_key_file); |
1449 |
goto err; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1450 |
}
|
1451 |
warn_if_group_others_accessible (options->priv_key_file); |
|
1452 |
||
1453 |
/* Check Private Key */
|
|
1454 |
if (!SSL_CTX_check_private_key (ctx)) |
|
1455 |
msg (M_SSLERR, "Private key does not match the certificate"); |
|
1456 |
}
|
|
1457 |
}
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1458 |
}
|
1459 |
||
1460 |
if (options->ca_file || options->ca_path) |
|
1461 |
{
|
|
1462 |
int status; |
|
1463 |
||
1464 |
#if ENABLE_INLINE_FILES
|
|
1.1.8
by Chuck Short
Import upstream version 2.1~rc7 |
1465 |
if (options->ca_file && !strcmp (options->ca_file, INLINE_FILE_TAG) && options->ca_file_inline) |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1466 |
{
|
1467 |
status = use_inline_load_verify_locations (ctx, options->ca_file_inline); |
|
1468 |
}
|
|
1469 |
else
|
|
1470 |
#endif
|
|
1471 |
{
|
|
1472 |
/* Load CA file for verifying peer supplied certificate */
|
|
1473 |
status = SSL_CTX_load_verify_locations (ctx, options->ca_file, options->ca_path); |
|
1474 |
}
|
|
1475 |
||
1476 |
if (!status) |
|
1477 |
msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", options->ca_file, options->ca_path); |
|
1478 |
||
1479 |
/* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
|
|
1480 |
if (options->ca_path) { |
|
1481 |
X509_STORE *store = SSL_CTX_get_cert_store(ctx); |
|
1482 |
||
1483 |
if (store) |
|
1484 |
{
|
|
1485 |
X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); |
|
1486 |
if (!X509_LOOKUP_add_dir(lookup, options->ca_path, X509_FILETYPE_PEM)) |
|
1487 |
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); |
|
1488 |
else
|
|
1489 |
msg(M_WARN, "WARNING: experimental option --capath %s", options->ca_path); |
|
1490 |
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
1491 |
X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); |
|
1492 |
#else
|
|
1493 |
msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath"); |
|
1494 |
#endif
|
|
1495 |
}
|
|
1496 |
else
|
|
1497 |
msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)"); |
|
1498 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1499 |
|
1500 |
/* Load names of CAs from file and use it as a client CA list */
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1501 |
if (options->ca_file) { |
1502 |
STACK_OF(X509_NAME) *cert_names = NULL; |
|
1503 |
#if ENABLE_INLINE_FILES
|
|
1504 |
if (!strcmp (options->ca_file, INLINE_FILE_TAG) && options->ca_file_inline) |
|
1505 |
{
|
|
1506 |
cert_names = use_inline_load_client_CA_file (ctx, options->ca_file_inline); |
|
1507 |
}
|
|
1508 |
else
|
|
1509 |
#endif
|
|
1510 |
{
|
|
1511 |
cert_names = SSL_load_client_CA_file (options->ca_file); |
|
1512 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1513 |
if (!cert_names) |
1514 |
msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", options->ca_file); |
|
1515 |
SSL_CTX_set_client_CA_list (ctx, cert_names); |
|
1516 |
}
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
1517 |
}
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1518 |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1519 |
/* Enable the use of certificate chains */
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1520 |
if (using_cert_file) |
1521 |
{
|
|
1522 |
if (!SSL_CTX_use_certificate_chain_file (ctx, options->cert_file)) |
|
1523 |
msg (M_SSLERR, "Cannot load certificate chain file %s (SSL_use_certificate_chain_file)", options->cert_file); |
|
1524 |
}
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1525 |
|
1526 |
/* Require peer certificate verification */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1527 |
#if P2MP_SERVER
|
1528 |
if (options->client_cert_not_required) |
|
1529 |
{
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
1530 |
msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION --client-cert-not-required may accept clients which do not present a certificate"); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1531 |
}
|
1532 |
else
|
|
1533 |
#endif
|
|
1534 |
SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, |
|
1535 |
verify_callback); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1536 |
|
1537 |
/* Connection information callback */
|
|
1538 |
SSL_CTX_set_info_callback (ctx, info_callback); |
|
1539 |
||
1540 |
/* Allowable ciphers */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1541 |
if (options->cipher_list) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1542 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1543 |
if (!SSL_CTX_set_cipher_list (ctx, options->cipher_list)) |
1544 |
msg (M_SSLERR, "Problem with cipher list: %s", options->cipher_list); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1545 |
}
|
1546 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1547 |
ERR_clear_error (); |
1548 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1549 |
return ctx; |
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1550 |
|
1551 |
err: |
|
1552 |
ERR_clear_error (); |
|
1553 |
if (ctx) |
|
1554 |
SSL_CTX_free (ctx); |
|
1555 |
return NULL; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1556 |
}
|
1557 |
||
1558 |
/*
|
|
1559 |
* Print a one line summary of SSL/TLS session handshake.
|
|
1560 |
*/
|
|
1561 |
static void |
|
1562 |
print_details (SSL * c_ssl, const char *prefix) |
|
1563 |
{
|
|
1564 |
SSL_CIPHER *ciph; |
|
1565 |
X509 *cert; |
|
1566 |
char s1[256]; |
|
1567 |
char s2[256]; |
|
1568 |
||
1569 |
s1[0] = s2[0] = 0; |
|
1570 |
ciph = SSL_get_current_cipher (c_ssl); |
|
1571 |
openvpn_snprintf (s1, sizeof (s1), "%s %s, cipher %s %s", |
|
1572 |
prefix, |
|
1573 |
SSL_get_version (c_ssl), |
|
1574 |
SSL_CIPHER_get_version (ciph), |
|
1575 |
SSL_CIPHER_get_name (ciph)); |
|
1576 |
cert = SSL_get_peer_certificate (c_ssl); |
|
1577 |
if (cert != NULL) |
|
1578 |
{
|
|
1579 |
EVP_PKEY *pkey = X509_get_pubkey (cert); |
|
1580 |
if (pkey != NULL) |
|
1581 |
{
|
|
1582 |
if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL |
|
1583 |
&& pkey->pkey.rsa->n != NULL) |
|
1584 |
{
|
|
1585 |
openvpn_snprintf (s2, sizeof (s2), ", %d bit RSA", |
|
1586 |
BN_num_bits (pkey->pkey.rsa->n)); |
|
1587 |
}
|
|
1588 |
else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL |
|
1589 |
&& pkey->pkey.dsa->p != NULL) |
|
1590 |
{
|
|
1591 |
openvpn_snprintf (s2, sizeof (s2), ", %d bit DSA", |
|
1592 |
BN_num_bits (pkey->pkey.dsa->p)); |
|
1593 |
}
|
|
1594 |
EVP_PKEY_free (pkey); |
|
1595 |
}
|
|
1596 |
X509_free (cert); |
|
1597 |
}
|
|
1598 |
/* The SSL API does not allow us to look at temporary RSA/DH keys,
|
|
1599 |
* otherwise we should print their lengths too */
|
|
1600 |
msg (D_HANDSHAKE, "%s%s", s1, s2); |
|
1601 |
}
|
|
1602 |
||
1603 |
/*
|
|
1604 |
* Show the TLS ciphers that are available for us to use
|
|
1605 |
* in the OpenSSL library.
|
|
1606 |
*/
|
|
1607 |
void
|
|
1608 |
show_available_tls_ciphers () |
|
1609 |
{
|
|
1610 |
SSL_CTX *ctx; |
|
1611 |
SSL *ssl; |
|
1612 |
const char *cipher_name; |
|
1613 |
int priority = 0; |
|
1614 |
||
1615 |
ctx = SSL_CTX_new (TLSv1_method ()); |
|
1616 |
if (!ctx) |
|
1617 |
msg (M_SSLERR, "Cannot create SSL_CTX object"); |
|
1618 |
ssl = SSL_new (ctx); |
|
1619 |
if (!ssl) |
|
1620 |
msg (M_SSLERR, "Cannot create SSL object"); |
|
1621 |
||
1622 |
printf ("Available TLS Ciphers,\n"); |
|
1623 |
printf ("listed in order of preference:\n\n"); |
|
1624 |
while ((cipher_name = SSL_get_cipher_list (ssl, priority++))) |
|
1625 |
printf ("%s\n", cipher_name); |
|
1626 |
printf ("\n"); |
|
1627 |
||
1628 |
SSL_free (ssl); |
|
1629 |
SSL_CTX_free (ctx); |
|
1630 |
}
|
|
1631 |
||
1632 |
/*
|
|
1633 |
* The OpenSSL library has a notion of preference in TLS
|
|
1634 |
* ciphers. Higher preference == more secure.
|
|
1635 |
* Return the highest preference cipher.
|
|
1636 |
*/
|
|
1637 |
void
|
|
1638 |
get_highest_preference_tls_cipher (char *buf, int size) |
|
1639 |
{
|
|
1640 |
SSL_CTX *ctx; |
|
1641 |
SSL *ssl; |
|
1642 |
const char *cipher_name; |
|
1643 |
||
1644 |
ctx = SSL_CTX_new (TLSv1_method ()); |
|
1645 |
if (!ctx) |
|
1646 |
msg (M_SSLERR, "Cannot create SSL_CTX object"); |
|
1647 |
ssl = SSL_new (ctx); |
|
1648 |
if (!ssl) |
|
1649 |
msg (M_SSLERR, "Cannot create SSL object"); |
|
1650 |
||
1651 |
cipher_name = SSL_get_cipher_list (ssl, 0); |
|
1652 |
strncpynt (buf, cipher_name, size); |
|
1653 |
||
1654 |
SSL_free (ssl); |
|
1655 |
SSL_CTX_free (ctx); |
|
1656 |
}
|
|
1657 |
||
1658 |
/*
|
|
1659 |
* Map internal constants to ascii names.
|
|
1660 |
*/
|
|
1661 |
static const char * |
|
1662 |
state_name (int state) |
|
1663 |
{
|
|
1664 |
switch (state) |
|
1665 |
{
|
|
1666 |
case S_UNDEF: |
|
1667 |
return "S_UNDEF"; |
|
1668 |
case S_INITIAL: |
|
1669 |
return "S_INITIAL"; |
|
1670 |
case S_PRE_START: |
|
1671 |
return "S_PRE_START"; |
|
1672 |
case S_START: |
|
1673 |
return "S_START"; |
|
1674 |
case S_SENT_KEY: |
|
1675 |
return "S_SENT_KEY"; |
|
1676 |
case S_GOT_KEY: |
|
1677 |
return "S_GOT_KEY"; |
|
1678 |
case S_ACTIVE: |
|
1679 |
return "S_ACTIVE"; |
|
1680 |
case S_NORMAL: |
|
1681 |
return "S_NORMAL"; |
|
1682 |
case S_ERROR: |
|
1683 |
return "S_ERROR"; |
|
1684 |
default: |
|
1685 |
return "S_???"; |
|
1686 |
}
|
|
1687 |
}
|
|
1688 |
||
1689 |
static const char * |
|
1690 |
packet_opcode_name (int op) |
|
1691 |
{
|
|
1692 |
switch (op) |
|
1693 |
{
|
|
1694 |
case P_CONTROL_HARD_RESET_CLIENT_V1: |
|
1695 |
return "P_CONTROL_HARD_RESET_CLIENT_V1"; |
|
1696 |
case P_CONTROL_HARD_RESET_SERVER_V1: |
|
1697 |
return "P_CONTROL_HARD_RESET_SERVER_V1"; |
|
1698 |
case P_CONTROL_HARD_RESET_CLIENT_V2: |
|
1699 |
return "P_CONTROL_HARD_RESET_CLIENT_V2"; |
|
1700 |
case P_CONTROL_HARD_RESET_SERVER_V2: |
|
1701 |
return "P_CONTROL_HARD_RESET_SERVER_V2"; |
|
1702 |
case P_CONTROL_SOFT_RESET_V1: |
|
1703 |
return "P_CONTROL_SOFT_RESET_V1"; |
|
1704 |
case P_CONTROL_V1: |
|
1705 |
return "P_CONTROL_V1"; |
|
1706 |
case P_ACK_V1: |
|
1707 |
return "P_ACK_V1"; |
|
1708 |
case P_DATA_V1: |
|
1709 |
return "P_DATA_V1"; |
|
1710 |
default: |
|
1711 |
return "P_???"; |
|
1712 |
}
|
|
1713 |
}
|
|
1714 |
||
1715 |
static const char * |
|
1716 |
session_index_name (int index) |
|
1717 |
{
|
|
1718 |
switch (index) |
|
1719 |
{
|
|
1720 |
case TM_ACTIVE: |
|
1721 |
return "TM_ACTIVE"; |
|
1722 |
case TM_UNTRUSTED: |
|
1723 |
return "TM_UNTRUSTED"; |
|
1724 |
case TM_LAME_DUCK: |
|
1725 |
return "TM_LAME_DUCK"; |
|
1726 |
default: |
|
1727 |
return "TM_???"; |
|
1728 |
}
|
|
1729 |
}
|
|
1730 |
||
1731 |
/*
|
|
1732 |
* For debugging.
|
|
1733 |
*/
|
|
1734 |
static const char * |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1735 |
print_key_id (struct tls_multi *multi, struct gc_arena *gc) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1736 |
{
|
1737 |
int i; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1738 |
struct buffer out = alloc_buf_gc (256, gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1739 |
|
1740 |
for (i = 0; i < KEY_SCAN_SIZE; ++i) |
|
1741 |
{
|
|
1742 |
struct key_state *ks = multi->key_scan[i]; |
|
1743 |
buf_printf (&out, " [key#%d state=%s id=%d sid=%s]", i, |
|
1744 |
state_name (ks->state), ks->key_id, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1745 |
session_id_print (&ks->session_id_remote, gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1746 |
}
|
1747 |
||
1748 |
return BSTR (&out); |
|
1749 |
}
|
|
1750 |
||
1751 |
/*
|
|
1752 |
* Given a key_method, return true if op
|
|
1753 |
* represents the required form of hard_reset.
|
|
1754 |
*
|
|
1755 |
* If key_method = 0, return true if any
|
|
1756 |
* form of hard reset is used.
|
|
1757 |
*/
|
|
1758 |
static bool |
|
1759 |
is_hard_reset (int op, int key_method) |
|
1760 |
{
|
|
1761 |
if (!key_method || key_method == 1) |
|
1762 |
if (op == P_CONTROL_HARD_RESET_CLIENT_V1 || op == P_CONTROL_HARD_RESET_SERVER_V1) |
|
1763 |
return true; |
|
1764 |
||
1765 |
if (!key_method || key_method >= 2) |
|
1766 |
if (op == P_CONTROL_HARD_RESET_CLIENT_V2 || op == P_CONTROL_HARD_RESET_SERVER_V2) |
|
1767 |
return true; |
|
1768 |
||
1769 |
return false; |
|
1770 |
}
|
|
1771 |
||
1772 |
/*
|
|
1773 |
* OpenVPN's interface to SSL/TLS authentication,
|
|
1774 |
* encryption, and decryption is exclusively
|
|
1775 |
* through "memory BIOs".
|
|
1776 |
*/
|
|
1777 |
static BIO * |
|
1778 |
getbio (BIO_METHOD * type, const char *desc) |
|
1779 |
{
|
|
1780 |
BIO *ret; |
|
1781 |
ret = BIO_new (type); |
|
1782 |
if (!ret) |
|
1783 |
msg (M_SSLERR, "Error creating %s BIO", desc); |
|
1784 |
return ret; |
|
1785 |
}
|
|
1786 |
||
1787 |
/*
|
|
1788 |
* Write to an OpenSSL BIO in non-blocking mode.
|
|
1789 |
*/
|
|
1790 |
static int |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1791 |
bio_write (struct tls_multi* multi, BIO *bio, const uint8_t *data, int size, const char *desc) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1792 |
{
|
1793 |
int i; |
|
1794 |
int ret = 0; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1795 |
ASSERT (size >= 0); |
1796 |
if (size) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1797 |
{
|
1798 |
/*
|
|
1799 |
* Free the L_TLS lock prior to calling BIO routines
|
|
1800 |
* so that foreground thread can still call
|
|
1801 |
* tls_pre_decrypt or tls_pre_encrypt,
|
|
1802 |
* allowing tunnel packet forwarding to continue.
|
|
1803 |
*/
|
|
1804 |
#ifdef BIO_DEBUG
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1805 |
bio_debug_data ("write", bio, data, size, desc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1806 |
#endif
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1807 |
i = BIO_write (bio, data, size); |
1808 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1809 |
if (i < 0) |
1810 |
{
|
|
1811 |
if (BIO_should_retry (bio)) |
|
1812 |
{
|
|
1813 |
;
|
|
1814 |
}
|
|
1815 |
else
|
|
1816 |
{
|
|
1817 |
msg (D_TLS_ERRORS | M_SSL, "TLS ERROR: BIO write %s error", |
|
1818 |
desc); |
|
1819 |
ret = -1; |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1820 |
ERR_clear_error (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1821 |
}
|
1822 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1823 |
else if (i != size) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1824 |
{
|
1825 |
msg (D_TLS_ERRORS | M_SSL, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1826 |
"TLS ERROR: BIO write %s incomplete %d/%d", desc, i, size); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1827 |
ret = -1; |
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1828 |
ERR_clear_error (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1829 |
}
|
1830 |
else
|
|
1831 |
{ /* successful write */ |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1832 |
dmsg (D_HANDSHAKE_VERBOSE, "BIO write %s %d bytes", desc, i); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1833 |
ret = 1; |
1834 |
}
|
|
1835 |
}
|
|
1836 |
return ret; |
|
1837 |
}
|
|
1838 |
||
1839 |
/*
|
|
1840 |
* Read from an OpenSSL BIO in non-blocking mode.
|
|
1841 |
*/
|
|
1842 |
static int |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1843 |
bio_read (struct tls_multi* multi, BIO *bio, struct buffer *buf, int maxlen, const char *desc) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1844 |
{
|
1845 |
int i; |
|
1846 |
int ret = 0; |
|
1847 |
ASSERT (buf->len >= 0); |
|
1848 |
if (buf->len) |
|
1849 |
{
|
|
1850 |
;
|
|
1851 |
}
|
|
1852 |
else
|
|
1853 |
{
|
|
1854 |
int len = buf_forward_capacity (buf); |
|
1855 |
if (maxlen < len) |
|
1856 |
len = maxlen; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1857 |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1858 |
/*
|
1859 |
* BIO_read brackets most of the serious RSA
|
|
1860 |
* key negotiation number crunching.
|
|
1861 |
*/
|
|
1862 |
i = BIO_read (bio, BPTR (buf), len); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1863 |
|
1864 |
VALGRIND_MAKE_READABLE ((void *) &i, sizeof (i)); |
|
1865 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1866 |
#ifdef BIO_DEBUG
|
1867 |
bio_debug_data ("read", bio, BPTR (buf), i, desc); |
|
1868 |
#endif
|
|
1869 |
if (i < 0) |
|
1870 |
{
|
|
1871 |
if (BIO_should_retry (bio)) |
|
1872 |
{
|
|
1873 |
;
|
|
1874 |
}
|
|
1875 |
else
|
|
1876 |
{
|
|
1877 |
msg (D_TLS_ERRORS | M_SSL, "TLS_ERROR: BIO read %s error", |
|
1878 |
desc); |
|
1879 |
buf->len = 0; |
|
1880 |
ret = -1; |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
1881 |
ERR_clear_error (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1882 |
}
|
1883 |
}
|
|
1884 |
else if (!i) |
|
1885 |
{
|
|
1886 |
buf->len = 0; |
|
1887 |
}
|
|
1888 |
else
|
|
1889 |
{ /* successful read */ |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1890 |
dmsg (D_HANDSHAKE_VERBOSE, "BIO read %s %d bytes", desc, i); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1891 |
buf->len = i; |
1892 |
ret = 1; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1893 |
VALGRIND_MAKE_READABLE ((void *) BPTR (buf), BLEN (buf)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1894 |
}
|
1895 |
}
|
|
1896 |
return ret; |
|
1897 |
}
|
|
1898 |
||
1899 |
/*
|
|
1900 |
* Inline functions for reading from and writing
|
|
1901 |
* to BIOs.
|
|
1902 |
*/
|
|
1903 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1904 |
static void |
1905 |
bio_write_post (const int status, struct buffer *buf) |
|
1906 |
{
|
|
1907 |
if (status == 1) /* success status return from bio_write? */ |
|
1908 |
{
|
|
1909 |
memset (BPTR (buf), 0, BLEN (buf)); /* erase data just written */ |
|
1910 |
buf->len = 0; |
|
1911 |
}
|
|
1912 |
}
|
|
1913 |
||
1914 |
static int |
|
1915 |
key_state_write_plaintext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf) |
|
1916 |
{
|
|
1917 |
int ret; |
|
1918 |
perf_push (PERF_BIO_WRITE_PLAINTEXT); |
|
1919 |
ret = bio_write (multi, ks->ssl_bio, BPTR(buf), BLEN(buf), "tls_write_plaintext"); |
|
1920 |
bio_write_post (ret, buf); |
|
1921 |
perf_pop (); |
|
1922 |
return ret; |
|
1923 |
}
|
|
1924 |
||
1925 |
static int |
|
1926 |
key_state_write_plaintext_const (struct tls_multi *multi, struct key_state *ks, const uint8_t *data, int len) |
|
1927 |
{
|
|
1928 |
int ret; |
|
1929 |
perf_push (PERF_BIO_WRITE_PLAINTEXT); |
|
1930 |
ret = bio_write (multi, ks->ssl_bio, data, len, "tls_write_plaintext_const"); |
|
1931 |
perf_pop (); |
|
1932 |
return ret; |
|
1933 |
}
|
|
1934 |
||
1935 |
static int |
|
1936 |
key_state_write_ciphertext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf) |
|
1937 |
{
|
|
1938 |
int ret; |
|
1939 |
perf_push (PERF_BIO_WRITE_CIPHERTEXT); |
|
1940 |
ret = bio_write (multi, ks->ct_in, BPTR(buf), BLEN(buf), "tls_write_ciphertext"); |
|
1941 |
bio_write_post (ret, buf); |
|
1942 |
perf_pop (); |
|
1943 |
return ret; |
|
1944 |
}
|
|
1945 |
||
1946 |
static int |
|
1947 |
key_state_read_plaintext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf, |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1948 |
int maxlen) |
1949 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1950 |
int ret; |
1951 |
perf_push (PERF_BIO_READ_PLAINTEXT); |
|
1952 |
ret = bio_read (multi, ks->ssl_bio, buf, maxlen, "tls_read_plaintext"); |
|
1953 |
perf_pop (); |
|
1954 |
return ret; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1955 |
}
|
1956 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1957 |
static int |
1958 |
key_state_read_ciphertext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf, |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1959 |
int maxlen) |
1960 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1961 |
int ret; |
1962 |
perf_push (PERF_BIO_READ_CIPHERTEXT); |
|
1963 |
ret = bio_read (multi, ks->ct_out, buf, maxlen, "tls_read_ciphertext"); |
|
1964 |
perf_pop (); |
|
1965 |
return ret; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1966 |
}
|
1967 |
||
1968 |
/*
|
|
1969 |
* Initialize a key_state. Each key_state corresponds to
|
|
1970 |
* a specific SSL/TLS session.
|
|
1971 |
*/
|
|
1972 |
static void |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1973 |
key_state_init (struct tls_session *session, struct key_state *ks) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1974 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1975 |
update_time (); |
1976 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1977 |
/*
|
1978 |
* Build TLS object that reads/writes ciphertext
|
|
1979 |
* to/from memory BIOs.
|
|
1980 |
*/
|
|
1981 |
CLEAR (*ks); |
|
1982 |
||
1983 |
ks->ssl = SSL_new (session->opt->ssl_ctx); |
|
1984 |
if (!ks->ssl) |
|
1985 |
msg (M_SSLERR, "SSL_new failed"); |
|
1986 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
1987 |
/* put session * in ssl object so we can access it
|
1988 |
from verify callback*/
|
|
1989 |
SSL_set_ex_data (ks->ssl, mydata_index, session); |
|
1990 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
1991 |
ks->ssl_bio = getbio (BIO_f_ssl (), "ssl_bio"); |
1992 |
ks->ct_in = getbio (BIO_s_mem (), "ct_in"); |
|
1993 |
ks->ct_out = getbio (BIO_s_mem (), "ct_out"); |
|
1994 |
||
1995 |
#ifdef BIO_DEBUG
|
|
1996 |
bio_debug_oc ("open ssl_bio", ks->ssl_bio); |
|
1997 |
bio_debug_oc ("open ct_in", ks->ct_in); |
|
1998 |
bio_debug_oc ("open ct_out", ks->ct_out); |
|
1999 |
#endif
|
|
2000 |
||
2001 |
if (session->opt->server) |
|
2002 |
SSL_set_accept_state (ks->ssl); |
|
2003 |
else
|
|
2004 |
SSL_set_connect_state (ks->ssl); |
|
2005 |
||
2006 |
SSL_set_bio (ks->ssl, ks->ct_in, ks->ct_out); |
|
2007 |
BIO_set_ssl (ks->ssl_bio, ks->ssl, BIO_NOCLOSE); |
|
2008 |
||
2009 |
/* Set control-channel initiation mode */
|
|
2010 |
ks->initial_opcode = session->initial_opcode; |
|
2011 |
session->initial_opcode = P_CONTROL_SOFT_RESET_V1; |
|
2012 |
ks->state = S_INITIAL; |
|
2013 |
ks->key_id = session->key_id; |
|
2014 |
||
2015 |
/*
|
|
2016 |
* key_id increments to KEY_ID_MASK then recycles back to 1.
|
|
2017 |
* This way you know that if key_id is 0, it is the first key.
|
|
2018 |
*/
|
|
2019 |
++session->key_id; |
|
2020 |
session->key_id &= P_KEY_ID_MASK; |
|
2021 |
if (!session->key_id) |
|
2022 |
session->key_id = 1; |
|
2023 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2024 |
/* allocate key source material object */
|
2025 |
ALLOC_OBJ_CLEAR (ks->key_src, struct key_source2); |
|
2026 |
||
2027 |
/* allocate reliability objects */
|
|
2028 |
ALLOC_OBJ_CLEAR (ks->send_reliable, struct reliable); |
|
2029 |
ALLOC_OBJ_CLEAR (ks->rec_reliable, struct reliable); |
|
2030 |
ALLOC_OBJ_CLEAR (ks->rec_ack, struct reliable_ack); |
|
2031 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2032 |
/* allocate buffers */
|
2033 |
ks->plaintext_read_buf = alloc_buf (PLAINTEXT_BUFFER_SIZE); |
|
2034 |
ks->plaintext_write_buf = alloc_buf (PLAINTEXT_BUFFER_SIZE); |
|
2035 |
ks->ack_write_buf = alloc_buf (BUF_SIZE (&session->opt->frame)); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2036 |
reliable_init (ks->send_reliable, BUF_SIZE (&session->opt->frame), |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2037 |
FRAME_HEADROOM (&session->opt->frame), TLS_RELIABLE_N_SEND_BUFFERS, |
2038 |
ks->key_id ? false : session->opt->xmit_hold); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2039 |
reliable_init (ks->rec_reliable, BUF_SIZE (&session->opt->frame), |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2040 |
FRAME_HEADROOM (&session->opt->frame), TLS_RELIABLE_N_REC_BUFFERS, |
2041 |
false); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2042 |
reliable_set_timeout (ks->send_reliable, session->opt->packet_timeout); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2043 |
|
2044 |
/* init packet ID tracker */
|
|
2045 |
packet_id_init (&ks->packet_id, |
|
2046 |
session->opt->replay_window, |
|
2047 |
session->opt->replay_time); |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
2048 |
|
2049 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
2050 |
ks->mda_key_id = session->opt->mda_context->mda_key_id_counter++; |
|
2051 |
#endif
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2052 |
}
|
2053 |
||
2054 |
static void |
|
2055 |
key_state_free (struct key_state *ks, bool clear) |
|
2056 |
{
|
|
2057 |
ks->state = S_UNDEF; |
|
2058 |
||
2059 |
if (ks->ssl) { |
|
2060 |
#ifdef BIO_DEBUG
|
|
2061 |
bio_debug_oc ("close ssl_bio", ks->ssl_bio); |
|
2062 |
bio_debug_oc ("close ct_in", ks->ct_in); |
|
2063 |
bio_debug_oc ("close ct_out", ks->ct_out); |
|
2064 |
#endif
|
|
2065 |
BIO_free_all(ks->ssl_bio); |
|
2066 |
SSL_free (ks->ssl); |
|
2067 |
}
|
|
2068 |
||
2069 |
free_key_ctx_bi (&ks->key); |
|
2070 |
free_buf (&ks->plaintext_read_buf); |
|
2071 |
free_buf (&ks->plaintext_write_buf); |
|
2072 |
free_buf (&ks->ack_write_buf); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2073 |
|
2074 |
if (ks->send_reliable) |
|
2075 |
{
|
|
2076 |
reliable_free (ks->send_reliable); |
|
2077 |
free (ks->send_reliable); |
|
2078 |
}
|
|
2079 |
||
2080 |
if (ks->rec_reliable) |
|
2081 |
{
|
|
2082 |
reliable_free (ks->rec_reliable); |
|
2083 |
free (ks->rec_reliable); |
|
2084 |
}
|
|
2085 |
||
2086 |
if (ks->rec_ack) |
|
2087 |
free (ks->rec_ack); |
|
2088 |
||
2089 |
if (ks->key_src) |
|
2090 |
free (ks->key_src); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2091 |
|
2092 |
packet_id_free (&ks->packet_id); |
|
2093 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
2094 |
#ifdef PLUGIN_DEF_AUTH
|
2095 |
key_state_rm_auth_control_file (ks); |
|
2096 |
#endif
|
|
2097 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2098 |
if (clear) |
2099 |
CLEAR (*ks); |
|
2100 |
}
|
|
2101 |
||
2102 |
/*
|
|
2103 |
* Must be called if we move a tls_session in memory.
|
|
2104 |
*/
|
|
2105 |
static inline void tls_session_set_self_referential_pointers (struct tls_session* session) { |
|
2106 |
session->tls_auth.packet_id = &session->tls_auth_pid; |
|
2107 |
}
|
|
2108 |
||
2109 |
/*
|
|
2110 |
* Initialize a TLS session. A TLS session normally has 2 key_state objects,
|
|
2111 |
* one for the current key, and one for the lame duck (i.e. retiring) key.
|
|
2112 |
*/
|
|
2113 |
static void |
|
2114 |
tls_session_init (struct tls_multi *multi, struct tls_session *session) |
|
2115 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2116 |
struct gc_arena gc = gc_new (); |
2117 |
||
2118 |
dmsg (D_TLS_DEBUG, "TLS: tls_session_init: entry"); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2119 |
|
2120 |
CLEAR (*session); |
|
2121 |
||
2122 |
/* Set options data to point to parent's option structure */
|
|
2123 |
session->opt = &multi->opt; |
|
2124 |
||
2125 |
/* Randomize session # if it is 0 */
|
|
2126 |
while (!session_id_defined(&session->session_id)) |
|
2127 |
session_id_random (&session->session_id); |
|
2128 |
||
2129 |
/* Are we a TLS server or client? */
|
|
2130 |
ASSERT (session->opt->key_method >= 1); |
|
2131 |
if (session->opt->key_method == 1) |
|
2132 |
{
|
|
2133 |
session->initial_opcode = session->opt->server ? |
|
2134 |
P_CONTROL_HARD_RESET_SERVER_V1 : P_CONTROL_HARD_RESET_CLIENT_V1; |
|
2135 |
}
|
|
2136 |
else /* session->opt->key_method >= 2 */ |
|
2137 |
{
|
|
2138 |
session->initial_opcode = session->opt->server ? |
|
2139 |
P_CONTROL_HARD_RESET_SERVER_V2 : P_CONTROL_HARD_RESET_CLIENT_V2; |
|
2140 |
}
|
|
2141 |
||
2142 |
/* Initialize control channel authentication parameters */
|
|
2143 |
session->tls_auth = session->opt->tls_auth; |
|
2144 |
||
2145 |
/* Set session internal pointers (also called if session object is moved in memory) */
|
|
2146 |
tls_session_set_self_referential_pointers (session); |
|
2147 |
||
2148 |
/* initialize packet ID replay window for --tls-auth */
|
|
2149 |
packet_id_init (session->tls_auth.packet_id, |
|
2150 |
session->opt->replay_window, |
|
2151 |
session->opt->replay_time); |
|
2152 |
||
2153 |
/* load most recent packet-id to replay protect on --tls-auth */
|
|
2154 |
packet_id_persist_load_obj (session->tls_auth.pid_persist, session->tls_auth.packet_id); |
|
2155 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2156 |
key_state_init (session, &session->key[KS_PRIMARY]); |
2157 |
||
2158 |
dmsg (D_TLS_DEBUG, "TLS: tls_session_init: new session object, sid=%s", |
|
2159 |
session_id_print (&session->session_id, &gc)); |
|
2160 |
||
2161 |
gc_free (&gc); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2162 |
}
|
2163 |
||
2164 |
static void |
|
2165 |
tls_session_free (struct tls_session *session, bool clear) |
|
2166 |
{
|
|
2167 |
int i; |
|
2168 |
||
2169 |
if (session->tls_auth.packet_id) |
|
2170 |
packet_id_free (session->tls_auth.packet_id); |
|
2171 |
||
2172 |
for (i = 0; i < KS_SIZE; ++i) |
|
2173 |
key_state_free (&session->key[i], false); |
|
2174 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2175 |
if (session->common_name) |
2176 |
free (session->common_name); |
|
2177 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2178 |
if (clear) |
2179 |
CLEAR (*session); |
|
2180 |
}
|
|
2181 |
||
2182 |
static void |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2183 |
move_session (struct tls_multi* multi, int dest, int src, bool reinit_src) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2184 |
{
|
2185 |
msg (D_TLS_DEBUG_LOW, "TLS: move_session: dest=%s src=%s reinit_src=%d", |
|
2186 |
session_index_name(dest), |
|
2187 |
session_index_name(src), |
|
2188 |
reinit_src); |
|
2189 |
ASSERT (src != dest); |
|
2190 |
ASSERT (src >= 0 && src < TM_SIZE); |
|
2191 |
ASSERT (dest >= 0 && dest < TM_SIZE); |
|
2192 |
tls_session_free (&multi->session[dest], false); |
|
2193 |
multi->session[dest] = multi->session[src]; |
|
2194 |
tls_session_set_self_referential_pointers (&multi->session[dest]); |
|
2195 |
||
2196 |
if (reinit_src) |
|
2197 |
tls_session_init (multi, &multi->session[src]); |
|
2198 |
else
|
|
2199 |
CLEAR (multi->session[src]); |
|
2200 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2201 |
dmsg (D_TLS_DEBUG, "TLS: move_session: exit"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2202 |
}
|
2203 |
||
2204 |
static void |
|
2205 |
reset_session (struct tls_multi *multi, struct tls_session *session) |
|
2206 |
{
|
|
2207 |
tls_session_free (session, false); |
|
2208 |
tls_session_init (multi, session); |
|
2209 |
}
|
|
2210 |
||
2211 |
#if 0
|
|
2212 |
/*
|
|
2213 |
* Transmit a TLS reset on our untrusted channel.
|
|
2214 |
*/
|
|
2215 |
static void
|
|
2216 |
initiate_untrusted_session (struct tls_multi *multi, struct sockaddr_in *to)
|
|
2217 |
{
|
|
2218 |
struct tls_session *session = &multi->session[TM_UNTRUSTED];
|
|
2219 |
struct key_state *ks = &session->key[KS_PRIMARY];
|
|
2220 |
||
2221 |
reset_session (multi, session);
|
|
2222 |
ks->remote_addr = *to;
|
|
2223 |
msg (D_TLS_DEBUG_LOW, "TLS: initiate_untrusted_session: addr=%s", print_sockaddr (to));
|
|
2224 |
}
|
|
2225 |
#endif
|
|
2226 |
||
2227 |
/*
|
|
2228 |
* Used to determine in how many seconds we should be
|
|
2229 |
* called again.
|
|
2230 |
*/
|
|
2231 |
static inline void |
|
2232 |
compute_earliest_wakeup (interval_t *earliest, interval_t seconds_from_now) { |
|
2233 |
if (seconds_from_now < *earliest) |
|
2234 |
*earliest = seconds_from_now; |
|
2235 |
if (*earliest < 0) |
|
2236 |
*earliest = 0; |
|
2237 |
}
|
|
2238 |
||
2239 |
/*
|
|
2240 |
* Return true if "lame duck" or retiring key has expired and can
|
|
2241 |
* no longer be used.
|
|
2242 |
*/
|
|
2243 |
static inline bool |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2244 |
lame_duck_must_die (const struct tls_session* session, interval_t *wakeup) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2245 |
{
|
2246 |
const struct key_state* lame = &session->key[KS_LAME_DUCK]; |
|
2247 |
if (lame->state >= S_INITIAL) |
|
2248 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2249 |
const time_t local_now = now; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2250 |
ASSERT (lame->must_die); /* a lame duck key must always have an expiration */ |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2251 |
if (local_now < lame->must_die) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2252 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2253 |
compute_earliest_wakeup (wakeup, lame->must_die - local_now); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2254 |
return false; |
2255 |
}
|
|
2256 |
else
|
|
2257 |
return true; |
|
2258 |
}
|
|
2259 |
else if (lame->state == S_ERROR) |
|
2260 |
return true; |
|
2261 |
else
|
|
2262 |
return false; |
|
2263 |
}
|
|
2264 |
||
2265 |
/*
|
|
2266 |
* A tls_multi object fully encapsulates OpenVPN's TLS state.
|
|
2267 |
* See ssl.h for more comments.
|
|
2268 |
*/
|
|
2269 |
struct tls_multi * |
|
2270 |
tls_multi_init (struct tls_options *tls_options) |
|
2271 |
{
|
|
2272 |
struct tls_multi *ret; |
|
2273 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2274 |
ALLOC_OBJ_CLEAR (ret, struct tls_multi); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2275 |
|
2276 |
/* get command line derived options */
|
|
2277 |
ret->opt = *tls_options; |
|
2278 |
||
2279 |
/* set up pointer to HMAC object for TLS packet authentication */
|
|
2280 |
ret->opt.tls_auth.key_ctx_bi = &ret->opt.tls_auth_key; |
|
2281 |
||
2282 |
/* set up list of keys to be scanned by data channel encrypt and decrypt routines */
|
|
2283 |
ASSERT (SIZE (ret->key_scan) == 3); |
|
2284 |
ret->key_scan[0] = &ret->session[TM_ACTIVE].key[KS_PRIMARY]; |
|
2285 |
ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK]; |
|
2286 |
ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK]; |
|
2287 |
||
2288 |
return ret; |
|
2289 |
}
|
|
2290 |
||
2291 |
/*
|
|
2292 |
* Finalize our computation of frame sizes.
|
|
2293 |
*/
|
|
2294 |
void
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2295 |
tls_multi_init_finalize (struct tls_multi* multi, const struct frame* frame) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2296 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2297 |
tls_init_control_channel_frame_parameters (frame, &multi->opt.frame); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2298 |
|
2299 |
/* initialize the active and untrusted sessions */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2300 |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2301 |
tls_session_init (multi, &multi->session[TM_ACTIVE]); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2302 |
|
2303 |
if (!multi->opt.single_session) |
|
2304 |
tls_session_init (multi, &multi->session[TM_UNTRUSTED]); |
|
2305 |
}
|
|
2306 |
||
2307 |
/*
|
|
2308 |
* Initialize and finalize a standalone tls-auth verification object.
|
|
2309 |
*/
|
|
2310 |
||
2311 |
struct tls_auth_standalone * |
|
2312 |
tls_auth_standalone_init (struct tls_options *tls_options, |
|
2313 |
struct gc_arena *gc) |
|
2314 |
{
|
|
2315 |
struct tls_auth_standalone *tas; |
|
2316 |
||
2317 |
ALLOC_OBJ_CLEAR_GC (tas, struct tls_auth_standalone, gc); |
|
2318 |
||
2319 |
/* set up pointer to HMAC object for TLS packet authentication */
|
|
2320 |
tas->tls_auth_key = tls_options->tls_auth_key; |
|
2321 |
tas->tls_auth_options.key_ctx_bi = &tas->tls_auth_key; |
|
2322 |
tas->tls_auth_options.flags |= CO_PACKET_ID_LONG_FORM; |
|
2323 |
||
2324 |
/* get initial frame parms, still need to finalize */
|
|
2325 |
tas->frame = tls_options->frame; |
|
2326 |
||
2327 |
return tas; |
|
2328 |
}
|
|
2329 |
||
2330 |
void
|
|
2331 |
tls_auth_standalone_finalize (struct tls_auth_standalone *tas, |
|
2332 |
const struct frame *frame) |
|
2333 |
{
|
|
2334 |
tls_init_control_channel_frame_parameters (frame, &tas->frame); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2335 |
}
|
2336 |
||
2337 |
/*
|
|
2338 |
* Set local and remote option compatibility strings.
|
|
2339 |
* Used to verify compatibility of local and remote option
|
|
2340 |
* sets.
|
|
2341 |
*/
|
|
2342 |
void
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2343 |
tls_multi_init_set_options (struct tls_multi* multi, |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2344 |
const char *local, |
2345 |
const char *remote) |
|
2346 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2347 |
#ifdef ENABLE_OCC
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2348 |
/* initialize options string */
|
2349 |
multi->opt.local_options = local; |
|
2350 |
multi->opt.remote_options = remote; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2351 |
#endif
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2352 |
}
|
2353 |
||
2354 |
void
|
|
2355 |
tls_multi_free (struct tls_multi *multi, bool clear) |
|
2356 |
{
|
|
2357 |
int i; |
|
2358 |
||
2359 |
ASSERT (multi); |
|
2360 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2361 |
if (multi->locked_cn) |
2362 |
free (multi->locked_cn); |
|
2363 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2364 |
for (i = 0; i < TM_SIZE; ++i) |
2365 |
tls_session_free (&multi->session[i], false); |
|
2366 |
||
2367 |
if (clear) |
|
2368 |
CLEAR (*multi); |
|
2369 |
||
2370 |
free(multi); |
|
2371 |
}
|
|
2372 |
||
2373 |
/*
|
|
2374 |
* Move a packet authentication HMAC + related fields to or from the front
|
|
2375 |
* of the buffer so it can be processed by encrypt/decrypt.
|
|
2376 |
*/
|
|
2377 |
||
2378 |
/*
|
|
2379 |
* Dependent on hmac size, opcode size, and session_id size.
|
|
2380 |
* Will assert if too small.
|
|
2381 |
*/
|
|
2382 |
#define SWAP_BUF_SIZE 256
|
|
2383 |
||
2384 |
static bool |
|
2385 |
swap_hmac (struct buffer *buf, const struct crypto_options *co, bool incoming) |
|
2386 |
{
|
|
2387 |
struct key_ctx *ctx; |
|
2388 |
||
2389 |
ASSERT (co); |
|
2390 |
||
2391 |
ctx = (incoming ? &co->key_ctx_bi->decrypt : &co->key_ctx_bi->encrypt); |
|
2392 |
ASSERT (ctx->hmac); |
|
2393 |
||
2394 |
{
|
|
2395 |
/* hmac + packet_id (8 bytes) */
|
|
2396 |
const int hmac_size = HMAC_size (ctx->hmac) + packet_id_size (true); |
|
2397 |
||
2398 |
/* opcode + session_id */
|
|
2399 |
const int osid_size = 1 + SID_SIZE; |
|
2400 |
||
2401 |
int e1, e2; |
|
2402 |
uint8_t *b = BPTR (buf); |
|
2403 |
uint8_t buf1[SWAP_BUF_SIZE]; |
|
2404 |
uint8_t buf2[SWAP_BUF_SIZE]; |
|
2405 |
||
2406 |
if (incoming) |
|
2407 |
{
|
|
2408 |
e1 = osid_size; |
|
2409 |
e2 = hmac_size; |
|
2410 |
}
|
|
2411 |
else
|
|
2412 |
{
|
|
2413 |
e1 = hmac_size; |
|
2414 |
e2 = osid_size; |
|
2415 |
}
|
|
2416 |
||
2417 |
ASSERT (e1 <= SWAP_BUF_SIZE && e2 <= SWAP_BUF_SIZE); |
|
2418 |
||
2419 |
if (buf->len >= e1 + e2) |
|
2420 |
{
|
|
2421 |
memcpy (buf1, b, e1); |
|
2422 |
memcpy (buf2, b + e1, e2); |
|
2423 |
memcpy (b, buf2, e2); |
|
2424 |
memcpy (b + e2, buf1, e1); |
|
2425 |
return true; |
|
2426 |
}
|
|
2427 |
else
|
|
2428 |
return false; |
|
2429 |
}
|
|
2430 |
}
|
|
2431 |
||
2432 |
#undef SWAP_BUF_SIZE
|
|
2433 |
||
2434 |
/*
|
|
2435 |
* Write a control channel authentication record.
|
|
2436 |
*/
|
|
2437 |
static void |
|
2438 |
write_control_auth (struct tls_session *session, |
|
2439 |
struct key_state *ks, |
|
2440 |
struct buffer *buf, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2441 |
struct link_socket_actual **to_link_addr, |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2442 |
int opcode, |
2443 |
int max_ack, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2444 |
bool prepend_ack) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2445 |
{
|
2446 |
uint8_t *header; |
|
2447 |
struct buffer null = clear_buf (); |
|
2448 |
||
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2449 |
ASSERT (link_socket_actual_defined (&ks->remote_addr)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2450 |
ASSERT (reliable_ack_write |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2451 |
(ks->rec_ack, buf, &ks->session_id_remote, max_ack, prepend_ack)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2452 |
ASSERT (session_id_write_prepend (&session->session_id, buf)); |
2453 |
ASSERT (header = buf_prepend (buf, 1)); |
|
2454 |
*header = ks->key_id | (opcode << P_OPCODE_SHIFT); |
|
2455 |
if (session->tls_auth.key_ctx_bi->encrypt.hmac) |
|
2456 |
{
|
|
2457 |
/* no encryption, only write hmac */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2458 |
openvpn_encrypt (buf, null, &session->tls_auth, NULL); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2459 |
ASSERT (swap_hmac (buf, &session->tls_auth, false)); |
2460 |
}
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2461 |
*to_link_addr = &ks->remote_addr; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2462 |
}
|
2463 |
||
2464 |
/*
|
|
2465 |
* Read a control channel authentication record.
|
|
2466 |
*/
|
|
2467 |
static bool |
|
2468 |
read_control_auth (struct buffer *buf, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2469 |
const struct crypto_options *co, |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2470 |
const struct link_socket_actual *from) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2471 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2472 |
struct gc_arena gc = gc_new (); |
2473 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2474 |
if (co->key_ctx_bi->decrypt.hmac) |
2475 |
{
|
|
2476 |
struct buffer null = clear_buf (); |
|
2477 |
||
2478 |
/* move the hmac record to the front of the packet */
|
|
2479 |
if (!swap_hmac (buf, co, true)) |
|
2480 |
{
|
|
2481 |
msg (D_TLS_ERRORS, |
|
2482 |
"TLS Error: cannot locate HMAC in incoming packet from %s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2483 |
print_link_socket_actual (from, &gc)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2484 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2485 |
return false; |
2486 |
}
|
|
2487 |
||
2488 |
/* authenticate only (no decrypt) and remove the hmac record
|
|
2489 |
from the head of the buffer */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2490 |
openvpn_decrypt (buf, null, co, NULL); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2491 |
if (!buf->len) |
2492 |
{
|
|
2493 |
msg (D_TLS_ERRORS, |
|
2494 |
"TLS Error: incoming packet authentication failed from %s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
2495 |
print_link_socket_actual (from, &gc)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2496 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2497 |
return false; |
2498 |
}
|
|
2499 |
||
2500 |
}
|
|
2501 |
||
2502 |
/* advance buffer pointer past opcode & session_id since our caller
|
|
2503 |
already read it */
|
|
2504 |
buf_advance (buf, SID_SIZE + 1); |
|
2505 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2506 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2507 |
return true; |
2508 |
}
|
|
2509 |
||
2510 |
/*
|
|
2511 |
* For debugging, print contents of key_source2 structure.
|
|
2512 |
*/
|
|
2513 |
||
2514 |
static void |
|
2515 |
key_source_print (const struct key_source *k, |
|
2516 |
const char *prefix) |
|
2517 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2518 |
struct gc_arena gc = gc_new (); |
2519 |
||
2520 |
VALGRIND_MAKE_READABLE ((void *)k->pre_master, sizeof (k->pre_master)); |
|
2521 |
VALGRIND_MAKE_READABLE ((void *)k->random1, sizeof (k->random1)); |
|
2522 |
VALGRIND_MAKE_READABLE ((void *)k->random2, sizeof (k->random2)); |
|
2523 |
||
2524 |
dmsg (D_SHOW_KEY_SOURCE, |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2525 |
"%s pre_master: %s", |
2526 |
prefix, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2527 |
format_hex (k->pre_master, sizeof (k->pre_master), 0, &gc)); |
2528 |
dmsg (D_SHOW_KEY_SOURCE, |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2529 |
"%s random1: %s", |
2530 |
prefix, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2531 |
format_hex (k->random1, sizeof (k->random1), 0, &gc)); |
2532 |
dmsg (D_SHOW_KEY_SOURCE, |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2533 |
"%s random2: %s", |
2534 |
prefix, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2535 |
format_hex (k->random2, sizeof (k->random2), 0, &gc)); |
2536 |
||
2537 |
gc_free (&gc); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2538 |
}
|
2539 |
||
2540 |
static void |
|
2541 |
key_source2_print (const struct key_source2 *k) |
|
2542 |
{
|
|
2543 |
key_source_print (&k->client, "Client"); |
|
2544 |
key_source_print (&k->server, "Server"); |
|
2545 |
}
|
|
2546 |
||
2547 |
/*
|
|
2548 |
* Use the TLS PRF function for generating data channel keys.
|
|
2549 |
* This code is taken from the OpenSSL library.
|
|
2550 |
*
|
|
2551 |
* TLS generates keys as such:
|
|
2552 |
*
|
|
2553 |
* master_secret[48] = PRF(pre_master_secret[48], "master secret",
|
|
2554 |
* ClientHello.random[32] + ServerHello.random[32])
|
|
2555 |
*
|
|
2556 |
* key_block[] = PRF(SecurityParameters.master_secret[48],
|
|
2557 |
* "key expansion",
|
|
2558 |
* SecurityParameters.server_random[32] +
|
|
2559 |
* SecurityParameters.client_random[32]);
|
|
2560 |
*
|
|
2561 |
* Notes:
|
|
2562 |
*
|
|
2563 |
* (1) key_block contains a full set of 4 keys.
|
|
2564 |
* (2) The pre-master secret is generated by the client.
|
|
2565 |
*/
|
|
2566 |
||
2567 |
static void |
|
2568 |
tls1_P_hash(const EVP_MD *md, |
|
2569 |
const uint8_t *sec, |
|
2570 |
int sec_len, |
|
2571 |
const uint8_t *seed, |
|
2572 |
int seed_len, |
|
2573 |
uint8_t *out, |
|
2574 |
int olen) |
|
2575 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2576 |
struct gc_arena gc = gc_new (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2577 |
int chunk,n; |
2578 |
unsigned int j; |
|
2579 |
HMAC_CTX ctx; |
|
2580 |
HMAC_CTX ctx_tmp; |
|
2581 |
uint8_t A1[EVP_MAX_MD_SIZE]; |
|
2582 |
unsigned int A1_len; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2583 |
|
2584 |
#ifdef ENABLE_DEBUG
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2585 |
const int olen_orig = olen; |
2586 |
const uint8_t *out_orig = out; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2587 |
#endif
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2588 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2589 |
dmsg (D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex (sec, sec_len, 0, &gc)); |
2590 |
dmsg (D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex (seed, seed_len, 0, &gc)); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2591 |
|
2592 |
chunk=EVP_MD_size(md); |
|
2593 |
||
2594 |
HMAC_CTX_init(&ctx); |
|
2595 |
HMAC_CTX_init(&ctx_tmp); |
|
2596 |
HMAC_Init_ex(&ctx,sec,sec_len,md, NULL); |
|
2597 |
HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL); |
|
2598 |
HMAC_Update(&ctx,seed,seed_len); |
|
2599 |
HMAC_Final(&ctx,A1,&A1_len); |
|
2600 |
||
2601 |
n=0; |
|
2602 |
for (;;) |
|
2603 |
{
|
|
2604 |
HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */ |
|
2605 |
HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */ |
|
2606 |
HMAC_Update(&ctx,A1,A1_len); |
|
2607 |
HMAC_Update(&ctx_tmp,A1,A1_len); |
|
2608 |
HMAC_Update(&ctx,seed,seed_len); |
|
2609 |
||
2610 |
if (olen > chunk) |
|
2611 |
{
|
|
2612 |
HMAC_Final(&ctx,out,&j); |
|
2613 |
out+=j; |
|
2614 |
olen-=j; |
|
2615 |
HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */ |
|
2616 |
}
|
|
2617 |
else /* last one */ |
|
2618 |
{
|
|
2619 |
HMAC_Final(&ctx,A1,&A1_len); |
|
2620 |
memcpy(out,A1,olen); |
|
2621 |
break; |
|
2622 |
}
|
|
2623 |
}
|
|
2624 |
HMAC_CTX_cleanup(&ctx); |
|
2625 |
HMAC_CTX_cleanup(&ctx_tmp); |
|
2626 |
CLEAR (A1); |
|
2627 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2628 |
dmsg (D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex (out_orig, olen_orig, 0, &gc)); |
2629 |
gc_free (&gc); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2630 |
}
|
2631 |
||
2632 |
static void |
|
2633 |
tls1_PRF(uint8_t *label, |
|
2634 |
int label_len, |
|
2635 |
const uint8_t *sec, |
|
2636 |
int slen, |
|
2637 |
uint8_t *out1, |
|
2638 |
int olen) |
|
2639 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2640 |
struct gc_arena gc = gc_new (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2641 |
const EVP_MD *md5 = EVP_md5(); |
2642 |
const EVP_MD *sha1 = EVP_sha1(); |
|
2643 |
int len,i; |
|
2644 |
const uint8_t *S1,*S2; |
|
2645 |
uint8_t *out2; |
|
2646 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2647 |
out2 = (uint8_t *) gc_malloc (olen, false, &gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2648 |
|
2649 |
len=slen/2; |
|
2650 |
S1=sec; |
|
2651 |
S2= &(sec[len]); |
|
2652 |
len+=(slen&1); /* add for odd, make longer */ |
|
2653 |
||
2654 |
||
2655 |
tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen); |
|
2656 |
tls1_P_hash(sha1,S2,len,label,label_len,out2,olen); |
|
2657 |
||
2658 |
for (i=0; i<olen; i++) |
|
2659 |
out1[i]^=out2[i]; |
|
2660 |
||
2661 |
memset (out2, 0, olen); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2662 |
|
2663 |
dmsg (D_SHOW_KEY_SOURCE, "tls1_PRF out[%d]: %s", olen, format_hex (out1, olen, 0, &gc)); |
|
2664 |
||
2665 |
gc_free (&gc); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2666 |
}
|
2667 |
||
2668 |
static void |
|
2669 |
openvpn_PRF (const uint8_t *secret, |
|
2670 |
int secret_len, |
|
2671 |
const char *label, |
|
2672 |
const uint8_t *client_seed, |
|
2673 |
int client_seed_len, |
|
2674 |
const uint8_t *server_seed, |
|
2675 |
int server_seed_len, |
|
2676 |
const struct session_id *client_sid, |
|
2677 |
const struct session_id *server_sid, |
|
2678 |
uint8_t *output, |
|
2679 |
int output_len) |
|
2680 |
{
|
|
2681 |
/* concatenate seed components */
|
|
2682 |
||
2683 |
struct buffer seed = alloc_buf (strlen (label) |
|
2684 |
+ client_seed_len |
|
2685 |
+ server_seed_len |
|
2686 |
+ SID_SIZE * 2); |
|
2687 |
||
2688 |
ASSERT (buf_write (&seed, label, strlen (label))); |
|
2689 |
ASSERT (buf_write (&seed, client_seed, client_seed_len)); |
|
2690 |
ASSERT (buf_write (&seed, server_seed, server_seed_len)); |
|
2691 |
||
2692 |
if (client_sid) |
|
2693 |
ASSERT (buf_write (&seed, client_sid->id, SID_SIZE)); |
|
2694 |
if (server_sid) |
|
2695 |
ASSERT (buf_write (&seed, server_sid->id, SID_SIZE)); |
|
2696 |
||
2697 |
/* compute PRF */
|
|
2698 |
tls1_PRF (BPTR(&seed), BLEN(&seed), secret, secret_len, output, output_len); |
|
2699 |
||
2700 |
buf_clear (&seed); |
|
2701 |
free_buf (&seed); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2702 |
|
2703 |
VALGRIND_MAKE_READABLE ((void *)output, output_len); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2704 |
}
|
2705 |
||
2706 |
/*
|
|
2707 |
* Using source entropy from local and remote hosts, mix into
|
|
2708 |
* master key.
|
|
2709 |
*/
|
|
2710 |
static bool |
|
2711 |
generate_key_expansion (struct key_ctx_bi *key, |
|
2712 |
const struct key_type *key_type, |
|
2713 |
const struct key_source2 *key_src, |
|
2714 |
const struct session_id *client_sid, |
|
2715 |
const struct session_id *server_sid, |
|
2716 |
bool server) |
|
2717 |
{
|
|
2718 |
uint8_t master[48]; |
|
2719 |
struct key2 key2; |
|
2720 |
bool ret = false; |
|
2721 |
int i; |
|
2722 |
||
2723 |
CLEAR (master); |
|
2724 |
CLEAR (key2); |
|
2725 |
||
2726 |
/* debugging print of source key material */
|
|
2727 |
key_source2_print (key_src); |
|
2728 |
||
2729 |
/* compute master secret */
|
|
2730 |
openvpn_PRF (key_src->client.pre_master, |
|
2731 |
sizeof(key_src->client.pre_master), |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2732 |
KEY_EXPANSION_ID " master secret", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2733 |
key_src->client.random1, |
2734 |
sizeof(key_src->client.random1), |
|
2735 |
key_src->server.random1, |
|
2736 |
sizeof(key_src->server.random1), |
|
2737 |
NULL, |
|
2738 |
NULL, |
|
2739 |
master, |
|
2740 |
sizeof(master)); |
|
2741 |
||
2742 |
/* compute key expansion */
|
|
2743 |
openvpn_PRF (master, |
|
2744 |
sizeof(master), |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2745 |
KEY_EXPANSION_ID " key expansion", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2746 |
key_src->client.random2, |
2747 |
sizeof(key_src->client.random2), |
|
2748 |
key_src->server.random2, |
|
2749 |
sizeof(key_src->server.random2), |
|
2750 |
client_sid, |
|
2751 |
server_sid, |
|
2752 |
(uint8_t*)key2.keys, |
|
2753 |
sizeof(key2.keys)); |
|
2754 |
||
2755 |
key2.n = 2; |
|
2756 |
||
2757 |
key2_print (&key2, key_type, "Master Encrypt", "Master Decrypt"); |
|
2758 |
||
2759 |
/* check for weak keys */
|
|
2760 |
for (i = 0; i < 2; ++i) |
|
2761 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2762 |
fixup_key (&key2.keys[i], key_type); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2763 |
if (!check_key (&key2.keys[i], key_type)) |
2764 |
{
|
|
2765 |
msg (D_TLS_ERRORS, "TLS Error: Bad dynamic key generated"); |
|
2766 |
goto exit; |
|
2767 |
}
|
|
2768 |
}
|
|
2769 |
||
2770 |
/* Initialize OpenSSL key contexts */
|
|
2771 |
||
2772 |
ASSERT (server == true || server == false); |
|
2773 |
||
2774 |
init_key_ctx (&key->encrypt, |
|
2775 |
&key2.keys[(int)server], |
|
2776 |
key_type, |
|
2777 |
DO_ENCRYPT, |
|
2778 |
"Data Channel Encrypt"); |
|
2779 |
||
2780 |
init_key_ctx (&key->decrypt, |
|
2781 |
&key2.keys[1-(int)server], |
|
2782 |
key_type, |
|
2783 |
DO_DECRYPT, |
|
2784 |
"Data Channel Decrypt"); |
|
2785 |
||
2786 |
ret = true; |
|
2787 |
||
2788 |
exit: |
|
2789 |
CLEAR (master); |
|
2790 |
CLEAR (key2); |
|
2791 |
||
2792 |
return ret; |
|
2793 |
}
|
|
2794 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2795 |
static bool |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2796 |
random_bytes_to_buf (struct buffer *buf, |
2797 |
uint8_t *out, |
|
2798 |
int outlen) |
|
2799 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2800 |
if (!RAND_bytes (out, outlen)) |
2801 |
msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for key generation [SSL]"); |
|
2802 |
if (!buf_write (buf, out, outlen)) |
|
2803 |
return false; |
|
2804 |
return true; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2805 |
}
|
2806 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2807 |
static bool |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2808 |
key_source2_randomize_write (struct key_source2 *k2, |
2809 |
struct buffer *buf, |
|
2810 |
bool server) |
|
2811 |
{
|
|
2812 |
struct key_source *k = &k2->client; |
|
2813 |
if (server) |
|
2814 |
k = &k2->server; |
|
2815 |
||
2816 |
CLEAR (*k); |
|
2817 |
||
2818 |
if (!server) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2819 |
{
|
2820 |
if (!random_bytes_to_buf (buf, k->pre_master, sizeof (k->pre_master))) |
|
2821 |
return false; |
|
2822 |
}
|
|
2823 |
||
2824 |
if (!random_bytes_to_buf (buf, k->random1, sizeof (k->random1))) |
|
2825 |
return false; |
|
2826 |
if (!random_bytes_to_buf (buf, k->random2, sizeof (k->random2))) |
|
2827 |
return false; |
|
2828 |
||
2829 |
return true; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2830 |
}
|
2831 |
||
2832 |
static int |
|
2833 |
key_source2_read (struct key_source2 *k2, |
|
2834 |
struct buffer *buf, |
|
2835 |
bool server) |
|
2836 |
{
|
|
2837 |
struct key_source *k = &k2->client; |
|
2838 |
||
2839 |
if (!server) |
|
2840 |
k = &k2->server; |
|
2841 |
||
2842 |
CLEAR (*k); |
|
2843 |
||
2844 |
if (server) |
|
2845 |
{
|
|
2846 |
if (!buf_read (buf, k->pre_master, sizeof (k->pre_master))) |
|
2847 |
return 0; |
|
2848 |
}
|
|
2849 |
||
2850 |
if (!buf_read (buf, k->random1, sizeof (k->random1))) |
|
2851 |
return 0; |
|
2852 |
if (!buf_read (buf, k->random2, sizeof (k->random2))) |
|
2853 |
return 0; |
|
2854 |
||
2855 |
return 1; |
|
2856 |
}
|
|
2857 |
||
2858 |
/*
|
|
2859 |
* Macros for key_state_soft_reset & tls_process
|
|
2860 |
*/
|
|
2861 |
#define ks (&session->key[KS_PRIMARY]) /* primary key */ |
|
2862 |
#define ks_lame (&session->key[KS_LAME_DUCK]) /* retiring key */ |
|
2863 |
||
2864 |
/* true if no in/out acknowledgements pending */
|
|
2865 |
#define FULL_SYNC \
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2866 |
(reliable_empty(ks->send_reliable) && reliable_ack_empty (ks->rec_ack))
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2867 |
|
2868 |
/*
|
|
2869 |
* Move the active key to the lame duck key and reinitialize the
|
|
2870 |
* active key.
|
|
2871 |
*/
|
|
2872 |
static void |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2873 |
key_state_soft_reset (struct tls_session *session) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2874 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2875 |
ks->must_die = now + session->opt->transition_window; /* remaining lifetime of old key */ |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2876 |
key_state_free (ks_lame, false); |
2877 |
*ks_lame = *ks; |
|
2878 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2879 |
key_state_init (session, ks); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
2880 |
ks->session_id_remote = ks_lame->session_id_remote; |
2881 |
ks->remote_addr = ks_lame->remote_addr; |
|
2882 |
}
|
|
2883 |
||
2884 |
/*
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2885 |
* Read/write strings from/to a struct buffer with a u16 length prefix.
|
2886 |
*/
|
|
2887 |
||
2888 |
static bool |
|
2889 |
write_string (struct buffer *buf, const char *str, const int maxlen) |
|
2890 |
{
|
|
2891 |
const int len = strlen (str) + 1; |
|
2892 |
if (len < 1 || (maxlen >= 0 && len > maxlen)) |
|
2893 |
return false; |
|
2894 |
if (!buf_write_u16 (buf, len)) |
|
2895 |
return false; |
|
2896 |
if (!buf_write (buf, str, len)) |
|
2897 |
return false; |
|
2898 |
return true; |
|
2899 |
}
|
|
2900 |
||
2901 |
static bool |
|
2902 |
read_string (struct buffer *buf, char *str, const unsigned int capacity) |
|
2903 |
{
|
|
2904 |
const int len = buf_read_u16 (buf); |
|
2905 |
if (len < 1 || len > (int)capacity) |
|
2906 |
return false; |
|
2907 |
if (!buf_read (buf, str, len)) |
|
2908 |
return false; |
|
2909 |
str[len-1] = '\0'; |
|
2910 |
return true; |
|
2911 |
}
|
|
2912 |
||
2913 |
/*
|
|
2914 |
* Authenticate a client using username/password.
|
|
2915 |
* Runs on server.
|
|
2916 |
*
|
|
2917 |
* If you want to add new authentication methods,
|
|
2918 |
* this is the place to start.
|
|
2919 |
*/
|
|
2920 |
||
2921 |
static bool |
|
2922 |
verify_user_pass_script (struct tls_session *session, const struct user_pass *up) |
|
2923 |
{
|
|
2924 |
struct gc_arena gc = gc_new (); |
|
2925 |
struct buffer cmd = alloc_buf_gc (256, &gc); |
|
2926 |
const char *tmp_file = ""; |
|
2927 |
int retval; |
|
2928 |
bool ret = false; |
|
2929 |
||
2930 |
/* Is username defined? */
|
|
2931 |
if (strlen (up->username)) |
|
2932 |
{
|
|
2933 |
/* Set environmental variables prior to calling script */
|
|
2934 |
setenv_str (session->opt->es, "script_type", "user-pass-verify"); |
|
2935 |
||
2936 |
if (session->opt->auth_user_pass_verify_script_via_file) |
|
2937 |
{
|
|
2938 |
struct status_output *so; |
|
2939 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
2940 |
tmp_file = create_temp_filename (session->opt->tmp_dir, "up", &gc); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2941 |
so = status_open (tmp_file, 0, -1, NULL, STATUS_OUTPUT_WRITE); |
2942 |
status_printf (so, "%s", up->username); |
|
2943 |
status_printf (so, "%s", up->password); |
|
2944 |
if (!status_close (so)) |
|
2945 |
{
|
|
2946 |
msg (D_TLS_ERRORS, "TLS Auth Error: could not write username/password to file: %s", |
|
2947 |
tmp_file); |
|
2948 |
goto done; |
|
2949 |
}
|
|
2950 |
}
|
|
2951 |
else
|
|
2952 |
{
|
|
2953 |
setenv_str (session->opt->es, "username", up->username); |
|
2954 |
setenv_str (session->opt->es, "password", up->password); |
|
2955 |
}
|
|
2956 |
||
2957 |
/* setenv incoming cert common name for script */
|
|
2958 |
setenv_str (session->opt->es, "common_name", session->common_name); |
|
2959 |
||
2960 |
/* setenv client real IP address */
|
|
2961 |
setenv_untrusted (session); |
|
2962 |
||
2963 |
/* format command line */
|
|
2964 |
buf_printf (&cmd, "%s %s", session->opt->auth_user_pass_verify_script, tmp_file); |
|
2965 |
||
2966 |
/* call command */
|
|
2967 |
retval = openvpn_system (BSTR (&cmd), session->opt->es, S_SCRIPT); |
|
2968 |
||
2969 |
/* test return status of command */
|
|
2970 |
if (system_ok (retval)) |
|
2971 |
ret = true; |
|
2972 |
else if (!system_executed (retval)) |
|
2973 |
msg (D_TLS_ERRORS, "TLS Auth Error: user-pass-verify script failed to execute: %s", BSTR (&cmd)); |
|
2974 |
||
2975 |
if (!session->opt->auth_user_pass_verify_script_via_file) |
|
2976 |
setenv_del (session->opt->es, "password"); |
|
2977 |
}
|
|
2978 |
else
|
|
2979 |
{
|
|
2980 |
msg (D_TLS_ERRORS, "TLS Auth Error: peer provided a blank username"); |
|
2981 |
}
|
|
2982 |
||
2983 |
done: |
|
2984 |
if (strlen (tmp_file) > 0) |
|
2985 |
delete_file (tmp_file); |
|
2986 |
||
2987 |
gc_free (&gc); |
|
2988 |
return ret; |
|
2989 |
}
|
|
2990 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
2991 |
static int |
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
2992 |
verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up, const char *raw_username) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2993 |
{
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
2994 |
int retval = OPENVPN_PLUGIN_FUNC_ERROR; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
2995 |
|
2996 |
/* Is username defined? */
|
|
2997 |
if (strlen (up->username)) |
|
2998 |
{
|
|
2999 |
/* set username/password in private env space */
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3000 |
setenv_str (session->opt->es, "username", raw_username); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3001 |
setenv_str (session->opt->es, "password", up->password); |
3002 |
||
3003 |
/* setenv incoming cert common name for script */
|
|
3004 |
setenv_str (session->opt->es, "common_name", session->common_name); |
|
3005 |
||
3006 |
/* setenv client real IP address */
|
|
3007 |
setenv_untrusted (session); |
|
3008 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3009 |
#ifdef PLUGIN_DEF_AUTH
|
3010 |
/* generate filename for deferred auth control file */
|
|
3011 |
key_state_gen_auth_control_file (ks, session->opt); |
|
3012 |
#endif
|
|
3013 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3014 |
/* call command */
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3015 |
retval = plugin_call (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, NULL, NULL, session->opt->es); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3016 |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3017 |
#ifdef PLUGIN_DEF_AUTH
|
3018 |
/* purge auth control filename (and file itself) for non-deferred returns */
|
|
3019 |
if (retval != OPENVPN_PLUGIN_FUNC_DEFERRED) |
|
3020 |
key_state_rm_auth_control_file (ks); |
|
3021 |
#endif
|
|
3022 |
||
3023 |
setenv_del (session->opt->es, "password"); |
|
3024 |
setenv_str (session->opt->es, "username", up->username); |
|
3025 |
}
|
|
3026 |
else
|
|
3027 |
{
|
|
3028 |
msg (D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_plugin): peer provided a blank username"); |
|
3029 |
}
|
|
3030 |
||
3031 |
return retval; |
|
3032 |
}
|
|
3033 |
||
3034 |
/*
|
|
3035 |
* MANAGEMENT_DEF_AUTH internal ssl.c status codes
|
|
3036 |
*/
|
|
3037 |
#define KMDA_ERROR 0
|
|
3038 |
#define KMDA_SUCCESS 1
|
|
3039 |
#define KMDA_UNDEF 2
|
|
3040 |
#define KMDA_DEF 3
|
|
3041 |
||
3042 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
3043 |
static int |
|
3044 |
verify_user_pass_management (struct tls_session *session, const struct user_pass *up, const char *raw_username) |
|
3045 |
{
|
|
3046 |
int retval = KMDA_ERROR; |
|
3047 |
||
3048 |
/* Is username defined? */
|
|
3049 |
if (strlen (up->username)) |
|
3050 |
{
|
|
3051 |
/* set username/password in private env space */
|
|
3052 |
setenv_str (session->opt->es, "username", raw_username); |
|
3053 |
setenv_str (session->opt->es, "password", up->password); |
|
3054 |
||
3055 |
/* setenv incoming cert common name for script */
|
|
3056 |
setenv_str (session->opt->es, "common_name", session->common_name); |
|
3057 |
||
3058 |
/* setenv client real IP address */
|
|
3059 |
setenv_untrusted (session); |
|
3060 |
||
3061 |
if (management) |
|
3062 |
management_notify_client_needing_auth (management, ks->mda_key_id, session->opt->mda_context, session->opt->es); |
|
3063 |
||
3064 |
setenv_del (session->opt->es, "password"); |
|
3065 |
setenv_str (session->opt->es, "username", up->username); |
|
3066 |
||
3067 |
retval = KMDA_SUCCESS; |
|
3068 |
}
|
|
3069 |
else
|
|
3070 |
{
|
|
3071 |
msg (D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_management): peer provided a blank username"); |
|
3072 |
}
|
|
3073 |
||
3074 |
return retval; |
|
3075 |
}
|
|
3076 |
#endif
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3077 |
|
3078 |
/*
|
|
3079 |
* Handle the reading and writing of key data to and from
|
|
3080 |
* the TLS control channel (cleartext).
|
|
3081 |
*/
|
|
3082 |
||
3083 |
static bool |
|
3084 |
key_method_1_write (struct buffer *buf, struct tls_session *session) |
|
3085 |
{
|
|
3086 |
struct key key; |
|
3087 |
||
3088 |
ASSERT (session->opt->key_method == 1); |
|
3089 |
ASSERT (buf_init (buf, 0)); |
|
3090 |
||
3091 |
generate_key_random (&key, &session->opt->key_type); |
|
3092 |
if (!check_key (&key, &session->opt->key_type)) |
|
3093 |
{
|
|
3094 |
msg (D_TLS_ERRORS, "TLS Error: Bad encrypting key generated"); |
|
3095 |
return false; |
|
3096 |
}
|
|
3097 |
||
3098 |
if (!write_key (&key, &session->opt->key_type, buf)) |
|
3099 |
{
|
|
3100 |
msg (D_TLS_ERRORS, "TLS Error: write_key failed"); |
|
3101 |
return false; |
|
3102 |
}
|
|
3103 |
||
3104 |
init_key_ctx (&ks->key.encrypt, &key, &session->opt->key_type, |
|
3105 |
DO_ENCRYPT, "Data Channel Encrypt"); |
|
3106 |
CLEAR (key); |
|
3107 |
||
3108 |
/* send local options string */
|
|
3109 |
{
|
|
3110 |
const char *local_options = local_options_string (session); |
|
3111 |
const int optlen = strlen (local_options) + 1; |
|
3112 |
if (!buf_write (buf, local_options, optlen)) |
|
3113 |
{
|
|
3114 |
msg (D_TLS_ERRORS, "TLS Error: KM1 write options failed"); |
|
3115 |
return false; |
|
3116 |
}
|
|
3117 |
}
|
|
3118 |
||
3119 |
return true; |
|
3120 |
}
|
|
3121 |
||
3122 |
static bool |
|
3123 |
key_method_2_write (struct buffer *buf, struct tls_session *session) |
|
3124 |
{
|
|
3125 |
ASSERT (session->opt->key_method == 2); |
|
3126 |
ASSERT (buf_init (buf, 0)); |
|
3127 |
||
3128 |
/* write a uint32 0 */
|
|
3129 |
if (!buf_write_u32 (buf, 0)) |
|
3130 |
goto error; |
|
3131 |
||
3132 |
/* write key_method + flags */
|
|
3133 |
if (!buf_write_u8 (buf, (session->opt->key_method & KEY_METHOD_MASK))) |
|
3134 |
goto error; |
|
3135 |
||
3136 |
/* write key source material */
|
|
3137 |
if (!key_source2_randomize_write (ks->key_src, buf, session->opt->server)) |
|
3138 |
goto error; |
|
3139 |
||
3140 |
/* write options string */
|
|
3141 |
{
|
|
3142 |
if (!write_string (buf, local_options_string (session), TLS_OPTIONS_LEN)) |
|
3143 |
goto error; |
|
3144 |
}
|
|
3145 |
||
3146 |
/* write username/password if specified */
|
|
3147 |
if (auth_user_pass_enabled) |
|
3148 |
{
|
|
3149 |
auth_user_pass_setup (NULL); |
|
3150 |
if (!write_string (buf, auth_user_pass.username, -1)) |
|
3151 |
goto error; |
|
3152 |
if (!write_string (buf, auth_user_pass.password, -1)) |
|
3153 |
goto error; |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3154 |
purge_user_pass (&auth_user_pass, false); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3155 |
}
|
3156 |
||
3157 |
/*
|
|
3158 |
* generate tunnel keys if server
|
|
3159 |
*/
|
|
3160 |
if (session->opt->server) |
|
3161 |
{
|
|
3162 |
if (ks->authenticated) |
|
3163 |
{
|
|
3164 |
if (!generate_key_expansion (&ks->key, |
|
3165 |
&session->opt->key_type, |
|
3166 |
ks->key_src, |
|
3167 |
&ks->session_id_remote, |
|
3168 |
&session->session_id, |
|
3169 |
true)) |
|
3170 |
{
|
|
3171 |
msg (D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed"); |
|
3172 |
goto error; |
|
3173 |
}
|
|
3174 |
}
|
|
3175 |
||
3176 |
CLEAR (*ks->key_src); |
|
3177 |
}
|
|
3178 |
||
3179 |
return true; |
|
3180 |
||
3181 |
error: |
|
3182 |
msg (D_TLS_ERRORS, "TLS Error: Key Method #2 write failed"); |
|
3183 |
CLEAR (*ks->key_src); |
|
3184 |
return false; |
|
3185 |
}
|
|
3186 |
||
3187 |
static bool |
|
3188 |
key_method_1_read (struct buffer *buf, struct tls_session *session) |
|
3189 |
{
|
|
3190 |
int status; |
|
3191 |
struct key key; |
|
3192 |
||
3193 |
ASSERT (session->opt->key_method == 1); |
|
3194 |
||
3195 |
if (!session->verified) |
|
3196 |
{
|
|
3197 |
msg (D_TLS_ERRORS, |
|
3198 |
"TLS Error: Certificate verification failed (key-method 1)"); |
|
3199 |
goto error; |
|
3200 |
}
|
|
3201 |
||
3202 |
status = read_key (&key, &session->opt->key_type, buf); |
|
3203 |
if (status != 1) |
|
3204 |
{
|
|
3205 |
msg (D_TLS_ERRORS, |
|
3206 |
"TLS Error: Error reading data channel key from plaintext buffer"); |
|
3207 |
goto error; |
|
3208 |
}
|
|
3209 |
||
3210 |
if (!check_key (&key, &session->opt->key_type)) |
|
3211 |
{
|
|
3212 |
msg (D_TLS_ERRORS, "TLS Error: Bad decrypting key received from peer"); |
|
3213 |
goto error; |
|
3214 |
}
|
|
3215 |
||
3216 |
if (buf->len < 1) |
|
3217 |
{
|
|
3218 |
msg (D_TLS_ERRORS, "TLS Error: Missing options string"); |
|
3219 |
goto error; |
|
3220 |
}
|
|
3221 |
||
3222 |
#ifdef ENABLE_OCC
|
|
3223 |
/* compare received remote options string
|
|
3224 |
with our locally computed options string */
|
|
3225 |
if (!session->opt->disable_occ && |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3226 |
!options_cmp_equal_safe ((char *) BPTR (buf), session->opt->remote_options, buf->len)) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3227 |
{
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3228 |
options_warning_safe ((char *) BPTR (buf), session->opt->remote_options, buf->len); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3229 |
}
|
3230 |
#endif
|
|
3231 |
||
3232 |
buf_clear (buf); |
|
3233 |
||
3234 |
init_key_ctx (&ks->key.decrypt, &key, &session->opt->key_type, |
|
3235 |
DO_DECRYPT, "Data Channel Decrypt"); |
|
3236 |
CLEAR (key); |
|
3237 |
ks->authenticated = true; |
|
3238 |
return true; |
|
3239 |
||
3240 |
error: |
|
3241 |
buf_clear (buf); |
|
3242 |
CLEAR (key); |
|
3243 |
return false; |
|
3244 |
}
|
|
3245 |
||
3246 |
static bool |
|
3247 |
key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_session *session) |
|
3248 |
{
|
|
3249 |
struct gc_arena gc = gc_new (); |
|
3250 |
int key_method_flags; |
|
3251 |
char *options; |
|
3252 |
struct user_pass *up; |
|
3253 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3254 |
bool man_def_auth = KMDA_UNDEF; |
3255 |
||
3256 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
3257 |
if (management_enable_def_auth (management)) |
|
3258 |
man_def_auth = KMDA_DEF; |
|
3259 |
#endif
|
|
3260 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3261 |
ASSERT (session->opt->key_method == 2); |
3262 |
||
3263 |
/* allocate temporary objects */
|
|
3264 |
ALLOC_ARRAY_CLEAR_GC (options, char, TLS_OPTIONS_LEN, &gc); |
|
3265 |
||
3266 |
/* discard leading uint32 */
|
|
3267 |
ASSERT (buf_advance (buf, 4)); |
|
3268 |
||
3269 |
/* get key method */
|
|
3270 |
key_method_flags = buf_read_u8 (buf); |
|
3271 |
if ((key_method_flags & KEY_METHOD_MASK) != 2) |
|
3272 |
{
|
|
3273 |
msg (D_TLS_ERRORS, |
|
3274 |
"TLS ERROR: Unknown key_method/flags=%d received from remote host", |
|
3275 |
key_method_flags); |
|
3276 |
goto error; |
|
3277 |
}
|
|
3278 |
||
3279 |
/* get key source material (not actual keys yet) */
|
|
3280 |
if (!key_source2_read (ks->key_src, buf, session->opt->server)) |
|
3281 |
{
|
|
3282 |
msg (D_TLS_ERRORS, "TLS Error: Error reading remote data channel key source entropy from plaintext buffer"); |
|
3283 |
goto error; |
|
3284 |
}
|
|
3285 |
||
3286 |
/* get options */
|
|
3287 |
if (!read_string (buf, options, TLS_OPTIONS_LEN)) |
|
3288 |
{
|
|
3289 |
msg (D_TLS_ERRORS, "TLS Error: Failed to read required OCC options string"); |
|
3290 |
goto error; |
|
3291 |
}
|
|
3292 |
||
3293 |
/* should we check username/password? */
|
|
3294 |
ks->authenticated = false; |
|
3295 |
if (session->opt->auth_user_pass_verify_script |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3296 |
|| plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) |
3297 |
|| man_def_auth == KMDA_DEF) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3298 |
{
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3299 |
int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3300 |
bool s2 = true; |
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3301 |
char *raw_username; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3302 |
|
3303 |
/* get username/password from plaintext buffer */
|
|
3304 |
ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc); |
|
3305 |
if (!read_string (buf, up->username, USER_PASS_LEN) |
|
3306 |
|| !read_string (buf, up->password, USER_PASS_LEN)) |
|
3307 |
{
|
|
3308 |
msg (D_TLS_ERRORS, "TLS Error: Auth Username/Password was not provided by peer"); |
|
3309 |
CLEAR (*up); |
|
3310 |
goto error; |
|
3311 |
}
|
|
3312 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3313 |
/* preserve raw username before string_mod remapping, for plugins */
|
3314 |
ALLOC_ARRAY_CLEAR_GC (raw_username, char, USER_PASS_LEN, &gc); |
|
3315 |
strcpy (raw_username, up->username); |
|
3316 |
string_mod (raw_username, CC_PRINT, CC_CRLF, '_'); |
|
3317 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3318 |
/* enforce character class restrictions in username/password */
|
3319 |
string_mod (up->username, COMMON_NAME_CHAR_CLASS, 0, '_'); |
|
3320 |
string_mod (up->password, CC_PRINT, CC_CRLF, '_'); |
|
3321 |
||
3322 |
/* call plugin(s) and/or script */
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3323 |
#ifdef MANAGEMENT_DEF_AUTH
|
3324 |
if (man_def_auth == KMDA_DEF) |
|
3325 |
man_def_auth = verify_user_pass_management (session, up, raw_username); |
|
3326 |
#endif
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3327 |
if (plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)) |
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3328 |
s1 = verify_user_pass_plugin (session, up, raw_username); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3329 |
if (session->opt->auth_user_pass_verify_script) |
3330 |
s2 = verify_user_pass_script (session, up); |
|
3331 |
||
3332 |
/* auth succeeded? */
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3333 |
if ((s1 == OPENVPN_PLUGIN_FUNC_SUCCESS |
3334 |
#ifdef PLUGIN_DEF_AUTH
|
|
3335 |
|| s1 == OPENVPN_PLUGIN_FUNC_DEFERRED |
|
3336 |
#endif
|
|
3337 |
) && s2 && man_def_auth != KMDA_ERROR) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3338 |
{
|
3339 |
ks->authenticated = true; |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3340 |
#ifdef PLUGIN_DEF_AUTH
|
3341 |
if (s1 == OPENVPN_PLUGIN_FUNC_DEFERRED) |
|
3342 |
ks->auth_deferred = true; |
|
3343 |
#endif
|
|
3344 |
#ifdef MANAGEMENT_DEF_AUTH
|
|
3345 |
if (man_def_auth != KMDA_UNDEF) |
|
3346 |
ks->auth_deferred = true; |
|
3347 |
#endif
|
|
3348 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3349 |
if (session->opt->username_as_common_name) |
3350 |
set_common_name (session, up->username); |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3351 |
msg (D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s", |
3352 |
s1 == OPENVPN_PLUGIN_FUNC_SUCCESS ? "succeeded" : "deferred", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3353 |
up->username, |
3354 |
session->opt->username_as_common_name ? "[CN SET]" : ""); |
|
3355 |
}
|
|
3356 |
else
|
|
3357 |
{
|
|
3358 |
msg (D_TLS_ERRORS, "TLS Auth Error: Auth Username/Password verification failed for peer"); |
|
3359 |
}
|
|
3360 |
||
3361 |
CLEAR (*up); |
|
3362 |
}
|
|
3363 |
else
|
|
3364 |
{
|
|
3365 |
if (!session->verified) |
|
3366 |
{
|
|
3367 |
msg (D_TLS_ERRORS, |
|
3368 |
"TLS Error: Certificate verification failed (key-method 2)"); |
|
3369 |
goto error; |
|
3370 |
}
|
|
3371 |
ks->authenticated = true; |
|
3372 |
}
|
|
3373 |
||
3374 |
/* While it shouldn't really happen, don't allow the common name to be NULL */
|
|
3375 |
if (!session->common_name) |
|
3376 |
set_common_name (session, ""); |
|
3377 |
||
3378 |
/* Don't allow the CN to change once it's been locked */
|
|
3379 |
if (ks->authenticated && multi->locked_cn) |
|
3380 |
{
|
|
3381 |
const char *cn = session->common_name; |
|
3382 |
if (cn && strcmp (cn, multi->locked_cn)) |
|
3383 |
{
|
|
3384 |
msg (D_TLS_ERRORS, "TLS Auth Error: TLS object CN attempted to change from '%s' to '%s' -- tunnel disabled", |
|
3385 |
multi->locked_cn, |
|
3386 |
cn); |
|
3387 |
||
3388 |
/* change the common name back to its original value and disable the tunnel */
|
|
3389 |
set_common_name (session, multi->locked_cn); |
|
3390 |
tls_deauthenticate (multi); |
|
3391 |
}
|
|
3392 |
}
|
|
3393 |
||
3394 |
/* verify --client-config-dir based authentication */
|
|
3395 |
if (ks->authenticated && session->opt->client_config_dir_exclusive) |
|
3396 |
{
|
|
3397 |
const char *cn = session->common_name; |
|
3398 |
const char *path = gen_path (session->opt->client_config_dir_exclusive, cn, &gc); |
|
3399 |
if (!cn || !strcmp (cn, CCD_DEFAULT) || !test_file (path)) |
|
3400 |
{
|
|
3401 |
ks->authenticated = false; |
|
3402 |
msg (D_TLS_ERRORS, "TLS Auth Error: --client-config-dir authentication failed for common name '%s' file='%s'", |
|
3403 |
session->common_name, |
|
3404 |
path ? path : "UNDEF"); |
|
3405 |
}
|
|
3406 |
}
|
|
3407 |
||
3408 |
#ifdef ENABLE_OCC
|
|
3409 |
/* check options consistency */
|
|
3410 |
if (!session->opt->disable_occ && |
|
3411 |
!options_cmp_equal (options, session->opt->remote_options)) |
|
3412 |
{
|
|
3413 |
options_warning (options, session->opt->remote_options); |
|
3414 |
}
|
|
3415 |
#endif
|
|
3416 |
||
3417 |
buf_clear (buf); |
|
3418 |
||
3419 |
/*
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3420 |
* Call OPENVPN_PLUGIN_TLS_FINAL plugin if defined, for final
|
3421 |
* veto opportunity over authentication decision.
|
|
3422 |
*/
|
|
3423 |
if (ks->authenticated && plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL)) |
|
3424 |
{
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3425 |
if (plugin_call (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL, NULL, NULL, session->opt->es) != OPENVPN_PLUGIN_FUNC_SUCCESS) |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3426 |
ks->authenticated = false; |
3427 |
}
|
|
3428 |
||
3429 |
/*
|
|
3430 |
* Generate tunnel keys if client
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3431 |
*/
|
3432 |
if (!session->opt->server) |
|
3433 |
{
|
|
3434 |
if (!generate_key_expansion (&ks->key, |
|
3435 |
&session->opt->key_type, |
|
3436 |
ks->key_src, |
|
3437 |
&session->session_id, |
|
3438 |
&ks->session_id_remote, |
|
3439 |
false)) |
|
3440 |
{
|
|
3441 |
msg (D_TLS_ERRORS, "TLS Error: client generate_key_expansion failed"); |
|
3442 |
goto error; |
|
3443 |
}
|
|
3444 |
||
3445 |
CLEAR (*ks->key_src); |
|
3446 |
}
|
|
3447 |
||
3448 |
gc_free (&gc); |
|
3449 |
return true; |
|
3450 |
||
3451 |
error: |
|
3452 |
CLEAR (*ks->key_src); |
|
3453 |
buf_clear (buf); |
|
3454 |
gc_free (&gc); |
|
3455 |
return false; |
|
3456 |
}
|
|
3457 |
||
3458 |
/*
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3459 |
* This is the primary routine for processing TLS stuff inside the
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3460 |
* the main event loop. When this routine exits
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3461 |
* with non-error status, it will set *wakeup to the number of seconds
|
3462 |
* when it wants to be called again.
|
|
3463 |
*
|
|
3464 |
* Return value is true if we have placed a packet in *to_link which we
|
|
3465 |
* want to send to our peer.
|
|
3466 |
*/
|
|
3467 |
static bool |
|
3468 |
tls_process (struct tls_multi *multi, |
|
3469 |
struct tls_session *session, |
|
3470 |
struct buffer *to_link, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3471 |
struct link_socket_actual **to_link_addr, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3472 |
struct link_socket_info *to_link_socket_info, |
3473 |
interval_t *wakeup) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3474 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3475 |
struct gc_arena gc = gc_new (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3476 |
struct buffer *buf; |
3477 |
bool state_change = false; |
|
3478 |
bool active = false; |
|
3479 |
||
3480 |
/* Make sure we were initialized and that we're not in an error state */
|
|
3481 |
ASSERT (ks->state != S_UNDEF); |
|
3482 |
ASSERT (ks->state != S_ERROR); |
|
3483 |
ASSERT (session_id_defined (&session->session_id)); |
|
3484 |
||
3485 |
/* Should we trigger a soft reset? -- new key, keeps old key for a while */
|
|
3486 |
if (ks->state >= S_ACTIVE && |
|
3487 |
((session->opt->renegotiate_seconds |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3488 |
&& now >= ks->established + session->opt->renegotiate_seconds) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3489 |
|| (session->opt->renegotiate_bytes |
3490 |
&& ks->n_bytes >= session->opt->renegotiate_bytes) |
|
3491 |
|| (session->opt->renegotiate_packets |
|
3492 |
&& ks->n_packets >= session->opt->renegotiate_packets) |
|
3493 |
|| (packet_id_close_to_wrapping (&ks->packet_id.send)))) |
|
3494 |
{
|
|
3495 |
msg (D_TLS_DEBUG_LOW, "TLS: soft reset sec=%d bytes=%d/%d pkts=%d/%d", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3496 |
(int)(ks->established + session->opt->renegotiate_seconds - now), |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3497 |
ks->n_bytes, session->opt->renegotiate_bytes, |
3498 |
ks->n_packets, session->opt->renegotiate_packets); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3499 |
key_state_soft_reset (session); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3500 |
}
|
3501 |
||
3502 |
/* Kill lame duck key transition_window seconds after primary key negotiation */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3503 |
if (lame_duck_must_die (session, wakeup)) { |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3504 |
key_state_free (ks_lame, true); |
3505 |
msg (D_TLS_DEBUG_LOW, "TLS: tls_process: killed expiring key"); |
|
3506 |
}
|
|
3507 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3508 |
/*mutex_cycle (multi->mutex);*/
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3509 |
|
3510 |
do
|
|
3511 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3512 |
update_time (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3513 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3514 |
dmsg (D_TLS_DEBUG, "TLS: tls_process: chg=%d ks=%s lame=%s to_link->len=%d wakeup=%d", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3515 |
state_change, |
3516 |
state_name (ks->state), |
|
3517 |
state_name (ks_lame->state), |
|
3518 |
to_link->len, |
|
3519 |
*wakeup); |
|
3520 |
||
3521 |
state_change = false; |
|
3522 |
||
3523 |
/*
|
|
3524 |
* TLS activity is finished once we get to S_ACTIVE,
|
|
3525 |
* though we will still process acknowledgements.
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3526 |
*
|
3527 |
* CHANGED with 2.0 -> now we may send tunnel configuration
|
|
3528 |
* info over the control channel.
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3529 |
*/
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3530 |
if (true) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3531 |
{
|
3532 |
/* Initial handshake */
|
|
3533 |
if (ks->state == S_INITIAL) |
|
3534 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3535 |
buf = reliable_get_buf_output_sequenced (ks->send_reliable); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3536 |
if (buf) |
3537 |
{
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3538 |
ks->auth_deferred_expire = ks->must_negotiate = now + session->opt->handshake_window; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3539 |
|
3540 |
/* null buffer */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3541 |
reliable_mark_active_outgoing (ks->send_reliable, buf, ks->initial_opcode); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3542 |
INCR_GENERATED; |
3543 |
||
3544 |
ks->state = S_PRE_START; |
|
3545 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3546 |
dmsg (D_TLS_DEBUG, "TLS: Initial Handshake, sid=%s", |
3547 |
session_id_print (&session->session_id, &gc)); |
|
3548 |
||
3549 |
#ifdef ENABLE_MANAGEMENT
|
|
3550 |
if (management && ks->initial_opcode != P_CONTROL_SOFT_RESET_V1) |
|
3551 |
{
|
|
3552 |
management_set_state (management, |
|
3553 |
OPENVPN_STATE_WAIT, |
|
3554 |
NULL, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3555 |
0, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3556 |
0); |
3557 |
}
|
|
3558 |
#endif
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3559 |
}
|
3560 |
}
|
|
3561 |
||
3562 |
/* Are we timed out on receive? */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3563 |
if (now >= ks->must_negotiate) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3564 |
{
|
3565 |
if (ks->state < S_ACTIVE) |
|
3566 |
{
|
|
3567 |
msg (D_TLS_ERRORS, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3568 |
"TLS Error: TLS key negotiation failed to occur within %d seconds (check your network connectivity)", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3569 |
session->opt->handshake_window); |
3570 |
goto error; |
|
3571 |
}
|
|
3572 |
else /* assume that ks->state == S_ACTIVE */ |
|
3573 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3574 |
dmsg (D_TLS_DEBUG_MED, "STATE S_NORMAL"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3575 |
ks->state = S_NORMAL; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3576 |
ks->must_negotiate = 0; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3577 |
}
|
3578 |
}
|
|
3579 |
||
3580 |
/* Wait for Initial Handshake ACK */
|
|
3581 |
if (ks->state == S_PRE_START && FULL_SYNC) |
|
3582 |
{
|
|
3583 |
ks->state = S_START; |
|
3584 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3585 |
dmsg (D_TLS_DEBUG_MED, "STATE S_START"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3586 |
}
|
3587 |
||
3588 |
/* Wait for ACK */
|
|
3589 |
if (((ks->state == S_GOT_KEY && !session->opt->server) || |
|
3590 |
(ks->state == S_SENT_KEY && session->opt->server))) |
|
3591 |
{
|
|
3592 |
if (FULL_SYNC) |
|
3593 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3594 |
ks->established = now; |
3595 |
dmsg (D_TLS_DEBUG_MED, "STATE S_ACTIVE"); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3596 |
if (check_debug_level (D_HANDSHAKE)) |
3597 |
print_details (ks->ssl, "Control Channel:"); |
|
3598 |
state_change = true; |
|
3599 |
ks->state = S_ACTIVE; |
|
3600 |
INCR_SUCCESS; |
|
3601 |
||
3602 |
/* Set outgoing address for data channel packets */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3603 |
link_socket_set_outgoing_addr (NULL, to_link_socket_info, &ks->remote_addr, session->common_name, session->opt->es); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3604 |
|
3605 |
#ifdef MEASURE_TLS_HANDSHAKE_STATS
|
|
3606 |
show_tls_performance_stats(); |
|
3607 |
#endif
|
|
3608 |
}
|
|
3609 |
}
|
|
3610 |
||
3611 |
/* Reliable buffer to outgoing TCP/UDP (send up to CONTROL_SEND_ACK_MAX ACKs
|
|
3612 |
for previously received packets) */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3613 |
if (!to_link->len && reliable_can_send (ks->send_reliable)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3614 |
{
|
3615 |
int opcode; |
|
3616 |
struct buffer b; |
|
3617 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3618 |
buf = reliable_send (ks->send_reliable, &opcode); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3619 |
ASSERT (buf); |
3620 |
b = *buf; |
|
3621 |
INCR_SENT; |
|
3622 |
||
3623 |
write_control_auth (session, ks, &b, to_link_addr, opcode, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3624 |
CONTROL_SEND_ACK_MAX, true); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3625 |
*to_link = b; |
3626 |
active = true; |
|
3627 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3628 |
dmsg (D_TLS_DEBUG, "Reliable -> TCP/UDP"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3629 |
break; |
3630 |
}
|
|
3631 |
||
3632 |
#ifndef TLS_AGGREGATE_ACK
|
|
3633 |
/* Send 1 or more ACKs (each received control packet gets one ACK) */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3634 |
if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3635 |
{
|
3636 |
buf = &ks->ack_write_buf; |
|
3637 |
ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); |
|
3638 |
write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3639 |
RELIABLE_ACK_SIZE, false); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3640 |
*to_link = *buf; |
3641 |
active = true; |
|
3642 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3643 |
dmsg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3644 |
break; |
3645 |
}
|
|
3646 |
#endif
|
|
3647 |
||
3648 |
/* Write incoming ciphertext to TLS object */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3649 |
buf = reliable_get_buf_sequenced (ks->rec_reliable); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3650 |
if (buf) |
3651 |
{
|
|
3652 |
int status = 0; |
|
3653 |
if (buf->len) |
|
3654 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3655 |
status = key_state_write_ciphertext (multi, ks, buf); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3656 |
if (status == -1) |
3657 |
{
|
|
3658 |
msg (D_TLS_ERRORS, |
|
3659 |
"TLS Error: Incoming Ciphertext -> TLS object write error"); |
|
3660 |
goto error; |
|
3661 |
}
|
|
3662 |
}
|
|
3663 |
else
|
|
3664 |
{
|
|
3665 |
status = 1; |
|
3666 |
}
|
|
3667 |
if (status == 1) |
|
3668 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3669 |
reliable_mark_deleted (ks->rec_reliable, buf, true); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3670 |
state_change = true; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3671 |
dmsg (D_TLS_DEBUG, "Incoming Ciphertext -> TLS"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3672 |
}
|
3673 |
}
|
|
3674 |
||
3675 |
/* Read incoming plaintext from TLS object */
|
|
3676 |
buf = &ks->plaintext_read_buf; |
|
3677 |
if (!buf->len) |
|
3678 |
{
|
|
3679 |
int status; |
|
3680 |
||
3681 |
ASSERT (buf_init (buf, 0)); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3682 |
status = key_state_read_plaintext (multi, ks, buf, PLAINTEXT_BUFFER_SIZE); |
3683 |
update_time (); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3684 |
if (status == -1) |
3685 |
{
|
|
3686 |
msg (D_TLS_ERRORS, "TLS Error: TLS object -> incoming plaintext read error"); |
|
3687 |
goto error; |
|
3688 |
}
|
|
3689 |
if (status == 1) |
|
3690 |
{
|
|
3691 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3692 |
dmsg (D_TLS_DEBUG, "TLS -> Incoming Plaintext"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3693 |
}
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3694 |
#if 0 /* show null plaintext reads */ |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3695 |
if (!status)
|
3696 |
msg (M_INFO, "TLS plaintext read -> NULL return");
|
|
3697 |
#endif
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3698 |
}
|
3699 |
||
3700 |
/* Send Key */
|
|
3701 |
buf = &ks->plaintext_write_buf; |
|
3702 |
if (!buf->len && ((ks->state == S_START && !session->opt->server) || |
|
3703 |
(ks->state == S_GOT_KEY && session->opt->server))) |
|
3704 |
{
|
|
3705 |
if (session->opt->key_method == 1) |
|
3706 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3707 |
if (!key_method_1_write (buf, session)) |
3708 |
goto error; |
|
3709 |
}
|
|
3710 |
else if (session->opt->key_method == 2) |
|
3711 |
{
|
|
3712 |
if (!key_method_2_write (buf, session)) |
|
3713 |
goto error; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3714 |
}
|
3715 |
else
|
|
3716 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3717 |
ASSERT (0); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3718 |
}
|
3719 |
||
3720 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3721 |
dmsg (D_TLS_DEBUG_MED, "STATE S_SENT_KEY"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3722 |
ks->state = S_SENT_KEY; |
3723 |
}
|
|
3724 |
||
3725 |
/* Receive Key */
|
|
3726 |
buf = &ks->plaintext_read_buf; |
|
3727 |
if (buf->len |
|
3728 |
&& ((ks->state == S_SENT_KEY && !session->opt->server) |
|
3729 |
|| (ks->state == S_START && session->opt->server))) |
|
3730 |
{
|
|
3731 |
if (session->opt->key_method == 1) |
|
3732 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3733 |
if (!key_method_1_read (buf, session)) |
3734 |
goto error; |
|
3735 |
}
|
|
3736 |
else if (session->opt->key_method == 2) |
|
3737 |
{
|
|
3738 |
if (!key_method_2_read (buf, multi, session)) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3739 |
goto error; |
3740 |
}
|
|
3741 |
else
|
|
3742 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3743 |
ASSERT (0); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3744 |
}
|
3745 |
||
3746 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3747 |
dmsg (D_TLS_DEBUG_MED, "STATE S_GOT_KEY"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3748 |
ks->state = S_GOT_KEY; |
3749 |
}
|
|
3750 |
||
3751 |
/* Write outgoing plaintext to TLS object */
|
|
3752 |
buf = &ks->plaintext_write_buf; |
|
3753 |
if (buf->len) |
|
3754 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3755 |
int status = key_state_write_plaintext (multi, ks, buf); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3756 |
if (status == -1) |
3757 |
{
|
|
3758 |
msg (D_TLS_ERRORS, |
|
3759 |
"TLS ERROR: Outgoing Plaintext -> TLS object write error"); |
|
3760 |
goto error; |
|
3761 |
}
|
|
3762 |
if (status == 1) |
|
3763 |
{
|
|
3764 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3765 |
dmsg (D_TLS_DEBUG, "Outgoing Plaintext -> TLS"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3766 |
}
|
3767 |
}
|
|
3768 |
||
3769 |
/* Outgoing Ciphertext to reliable buffer */
|
|
3770 |
if (ks->state >= S_START) |
|
3771 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3772 |
buf = reliable_get_buf_output_sequenced (ks->send_reliable); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3773 |
if (buf) |
3774 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3775 |
int status = key_state_read_ciphertext (multi, ks, buf, PAYLOAD_SIZE_DYNAMIC (&multi->opt.frame)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3776 |
if (status == -1) |
3777 |
{
|
|
3778 |
msg (D_TLS_ERRORS, |
|
3779 |
"TLS Error: Ciphertext -> reliable TCP/UDP transport read error"); |
|
3780 |
goto error; |
|
3781 |
}
|
|
3782 |
if (status == 1) |
|
3783 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3784 |
reliable_mark_active_outgoing (ks->send_reliable, buf, P_CONTROL_V1); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3785 |
INCR_GENERATED; |
3786 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3787 |
dmsg (D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3788 |
}
|
3789 |
}
|
|
3790 |
}
|
|
3791 |
}
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3792 |
/*mutex_cycle (multi->mutex);*/
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3793 |
}
|
3794 |
while (state_change); |
|
3795 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3796 |
update_time (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3797 |
|
3798 |
#ifdef TLS_AGGREGATE_ACK
|
|
3799 |
/* Send 1 or more ACKs (each received control packet gets one ACK) */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3800 |
if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3801 |
{
|
3802 |
buf = &ks->ack_write_buf; |
|
3803 |
ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); |
|
3804 |
write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3805 |
RELIABLE_ACK_SIZE, false); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3806 |
*to_link = *buf; |
3807 |
active = true; |
|
3808 |
state_change = true; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3809 |
dmsg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3810 |
}
|
3811 |
#endif
|
|
3812 |
||
3813 |
/* When should we wake up again? */
|
|
3814 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3815 |
if (ks->state >= S_INITIAL) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3816 |
{
|
3817 |
compute_earliest_wakeup (wakeup, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3818 |
reliable_send_timeout (ks->send_reliable)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3819 |
|
3820 |
if (ks->must_negotiate) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3821 |
compute_earliest_wakeup (wakeup, ks->must_negotiate - now); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3822 |
}
|
3823 |
||
3824 |
if (ks->established && session->opt->renegotiate_seconds) |
|
3825 |
compute_earliest_wakeup (wakeup, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3826 |
ks->established + session->opt->renegotiate_seconds - now); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3827 |
|
3828 |
/* prevent event-loop spinning by setting minimum wakeup of 1 second */
|
|
3829 |
if (*wakeup <= 0) |
|
3830 |
{
|
|
3831 |
*wakeup = 1; |
|
3832 |
||
3833 |
/* if we had something to send to remote, but to_link was busy,
|
|
3834 |
let caller know we need to be called again soon */
|
|
3835 |
active = true; |
|
3836 |
}
|
|
3837 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3838 |
dmsg (D_TLS_DEBUG, "TLS: tls_process: timeout set to %d", *wakeup); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3839 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3840 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3841 |
return active; |
3842 |
}
|
|
3843 |
||
3844 |
error: |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3845 |
ERR_clear_error (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3846 |
ks->state = S_ERROR; |
3847 |
msg (D_TLS_ERRORS, "TLS Error: TLS handshake failed"); |
|
3848 |
INCR_ERROR; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3849 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3850 |
return false; |
3851 |
}
|
|
3852 |
||
3853 |
#undef ks
|
|
3854 |
#undef ks_lame
|
|
3855 |
||
3856 |
/*
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3857 |
* Called by the top-level event loop.
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3858 |
*
|
3859 |
* Basically decides if we should call tls_process for
|
|
3860 |
* the active or untrusted sessions.
|
|
3861 |
*/
|
|
3862 |
||
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3863 |
int
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3864 |
tls_multi_process (struct tls_multi *multi, |
3865 |
struct buffer *to_link, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3866 |
struct link_socket_actual **to_link_addr, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3867 |
struct link_socket_info *to_link_socket_info, |
3868 |
interval_t *wakeup) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3869 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3870 |
struct gc_arena gc = gc_new (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3871 |
int i; |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3872 |
int active = TLSMP_INACTIVE; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3873 |
bool error = false; |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3874 |
int tas; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3875 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3876 |
perf_push (PERF_TLS_MULTI_PROCESS); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3877 |
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3878 |
ERR_clear_error (); |
3879 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3880 |
/*
|
3881 |
* Process each session object having state of S_INITIAL or greater,
|
|
3882 |
* and which has a defined remote IP addr.
|
|
3883 |
*/
|
|
3884 |
||
3885 |
for (i = 0; i < TM_SIZE; ++i) |
|
3886 |
{
|
|
3887 |
struct tls_session *session = &multi->session[i]; |
|
3888 |
struct key_state *ks = &session->key[KS_PRIMARY]; |
|
3889 |
struct key_state *ks_lame = &session->key[KS_LAME_DUCK]; |
|
3890 |
||
3891 |
/* set initial remote address */
|
|
3892 |
if (i == TM_ACTIVE && ks->state == S_INITIAL && |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3893 |
link_socket_actual_defined (&to_link_socket_info->lsa->actual)) |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3894 |
ks->remote_addr = to_link_socket_info->lsa->actual; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3895 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3896 |
dmsg (D_TLS_DEBUG, |
3897 |
"TLS: tls_multi_process: i=%d state=%s, mysid=%s, stored-sid=%s, stored-ip=%s", |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3898 |
i, |
3899 |
state_name (ks->state), |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3900 |
session_id_print (&session->session_id, &gc), |
3901 |
session_id_print (&ks->session_id_remote, &gc), |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3902 |
print_link_socket_actual (&ks->remote_addr, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3903 |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3904 |
if (ks->state >= S_INITIAL && link_socket_actual_defined (&ks->remote_addr)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3905 |
{
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3906 |
struct link_socket_actual *tla = NULL; |
3907 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3908 |
update_time (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3909 |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3910 |
if (tls_process (multi, session, to_link, &tla, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3911 |
to_link_socket_info, wakeup)) |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3912 |
active = TLSMP_ACTIVE; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3913 |
|
3914 |
/*
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
3915 |
* If tls_process produced an outgoing packet,
|
3916 |
* return the link_socket_actual object (which
|
|
3917 |
* contains the outgoing address).
|
|
3918 |
*/
|
|
3919 |
if (tla) |
|
3920 |
{
|
|
3921 |
multi->to_link_addr = *tla; |
|
3922 |
*to_link_addr = &multi->to_link_addr; |
|
3923 |
}
|
|
3924 |
||
3925 |
/*
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3926 |
* If tls_process hits an error:
|
3927 |
* (1) If the session has an unexpired lame duck key, preserve it.
|
|
3928 |
* (2) Reinitialize the session.
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3929 |
* (3) Increment soft error count
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3930 |
*/
|
3931 |
if (ks->state == S_ERROR) |
|
3932 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3933 |
++multi->n_soft_errors; |
3934 |
||
3935 |
if (i == TM_ACTIVE) |
|
3936 |
error = true; |
|
3937 |
||
3938 |
if (i == TM_ACTIVE |
|
3939 |
&& ks_lame->state >= S_ACTIVE |
|
3940 |
&& !multi->opt.single_session) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3941 |
move_session (multi, TM_LAME_DUCK, TM_ACTIVE, true); |
3942 |
else
|
|
3943 |
reset_session (multi, session); |
|
3944 |
}
|
|
3945 |
}
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
3946 |
/*mutex_cycle (multi->mutex);*/
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3947 |
}
|
3948 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3949 |
update_time (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3950 |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3951 |
tas = tls_authentication_status (multi, TLS_MULTI_AUTH_STATUS_INTERVAL); |
3952 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3953 |
/*
|
3954 |
* If lame duck session expires, kill it.
|
|
3955 |
*/
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3956 |
if (lame_duck_must_die (&multi->session[TM_LAME_DUCK], wakeup)) { |
3957 |
tls_session_free (&multi->session[TM_LAME_DUCK], true); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3958 |
msg (D_TLS_DEBUG_LOW, "TLS: tls_multi_process: killed expiring key"); |
3959 |
}
|
|
3960 |
||
3961 |
/*
|
|
3962 |
* If untrusted session achieves TLS authentication,
|
|
3963 |
* move it to active session, usurping any prior session.
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3964 |
*
|
3965 |
* A semi-trusted session is one in which the certificate authentication
|
|
3966 |
* succeeded (if cert verification is enabled) but the username/password
|
|
3967 |
* verification failed. A semi-trusted session can forward data on the
|
|
3968 |
* TLS control channel but not on the tunnel channel.
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
3969 |
*/
|
3970 |
if (DECRYPT_KEY_ENABLED (multi, &multi->session[TM_UNTRUSTED].key[KS_PRIMARY])) { |
|
3971 |
move_session (multi, TM_ACTIVE, TM_UNTRUSTED, true); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3972 |
msg (D_TLS_DEBUG_LOW, "TLS: tls_multi_process: untrusted session promoted to %strusted", |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
3973 |
tas == TLS_AUTHENTICATION_SUCCEEDED ? "" : "semi-"); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
3974 |
}
|
3975 |
||
3976 |
/*
|
|
3977 |
* A hard error means that TM_ACTIVE hit an S_ERROR state and that no
|
|
3978 |
* other key state objects are S_ACTIVE or higher.
|
|
3979 |
*/
|
|
3980 |
if (error) |
|
3981 |
{
|
|
3982 |
for (i = 0; i < (int) SIZE (multi->key_scan); ++i) |
|
3983 |
{
|
|
3984 |
if (multi->key_scan[i]->state >= S_ACTIVE) |
|
3985 |
goto nohard; |
|
3986 |
}
|
|
3987 |
++multi->n_hard_errors; |
|
3988 |
}
|
|
3989 |
nohard: |
|
3990 |
||
3991 |
#ifdef ENABLE_DEBUG
|
|
3992 |
/* DEBUGGING -- flood peer with repeating connection attempts */
|
|
3993 |
{
|
|
3994 |
const int throw_level = GREMLIN_CONNECTION_FLOOD_LEVEL (multi->opt.gremlin); |
|
3995 |
if (throw_level) |
|
3996 |
{
|
|
3997 |
for (i = 0; i < (int) SIZE (multi->key_scan); ++i) |
|
3998 |
{
|
|
3999 |
if (multi->key_scan[i]->state >= throw_level) |
|
4000 |
{
|
|
4001 |
++multi->n_hard_errors; |
|
4002 |
++multi->n_soft_errors; |
|
4003 |
}
|
|
4004 |
}
|
|
4005 |
}
|
|
4006 |
}
|
|
4007 |
#endif
|
|
4008 |
||
4009 |
perf_pop (); |
|
4010 |
gc_free (&gc); |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
4011 |
|
4012 |
return (tas == TLS_AUTHENTICATION_FAILED) ? TLSMP_KILL : active; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4013 |
}
|
4014 |
||
4015 |
/*
|
|
4016 |
* Pre and post-process the encryption & decryption buffers in order
|
|
4017 |
* to implement a multiplexed TLS channel over the TCP/UDP port.
|
|
4018 |
*/
|
|
4019 |
||
4020 |
/*
|
|
4021 |
*
|
|
4022 |
* When we are in TLS mode, this is the first routine which sees
|
|
4023 |
* an incoming packet.
|
|
4024 |
*
|
|
4025 |
* If it's a data packet, we set opt so that our caller can
|
|
4026 |
* decrypt it. We also give our caller the appropriate decryption key.
|
|
4027 |
*
|
|
4028 |
* If it's a control packet, we authenticate it and process it,
|
|
4029 |
* possibly creating a new tls_session if it represents the
|
|
4030 |
* first packet of a new session. For control packets, we will
|
|
4031 |
* also zero the size of *buf so that our caller ignores the
|
|
4032 |
* packet on our return.
|
|
4033 |
*
|
|
4034 |
* Note that openvpn only allows one active session at a time,
|
|
4035 |
* so a new session (once authenticated) will always usurp
|
|
4036 |
* an old session.
|
|
4037 |
*
|
|
4038 |
* Return true if input was an authenticated control channel
|
|
4039 |
* packet.
|
|
4040 |
*
|
|
4041 |
* If we are running in TLS thread mode, all public routines
|
|
4042 |
* below this point must be called with the L_TLS lock held.
|
|
4043 |
*/
|
|
4044 |
||
4045 |
bool
|
|
4046 |
tls_pre_decrypt (struct tls_multi *multi, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4047 |
const struct link_socket_actual *from, |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4048 |
struct buffer *buf, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4049 |
struct crypto_options *opt) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4050 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4051 |
struct gc_arena gc = gc_new (); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4052 |
bool ret = false; |
4053 |
||
4054 |
if (buf->len > 0) |
|
4055 |
{
|
|
4056 |
int i; |
|
4057 |
int op; |
|
4058 |
int key_id; |
|
4059 |
||
4060 |
/* get opcode and key ID */
|
|
4061 |
{
|
|
4062 |
uint8_t c = *BPTR (buf); |
|
4063 |
op = c >> P_OPCODE_SHIFT; |
|
4064 |
key_id = c & P_KEY_ID_MASK; |
|
4065 |
}
|
|
4066 |
||
4067 |
if (op == P_DATA_V1) |
|
4068 |
{ /* data channel packet */ |
|
4069 |
for (i = 0; i < KEY_SCAN_SIZE; ++i) |
|
4070 |
{
|
|
4071 |
struct key_state *ks = multi->key_scan[i]; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4072 |
|
4073 |
/*
|
|
4074 |
* This is the basic test of TLS state compatibility between a local OpenVPN
|
|
4075 |
* instance and its remote peer.
|
|
4076 |
*
|
|
4077 |
* If the test fails, it tells us that we are getting a packet from a source
|
|
4078 |
* which claims reference to a prior negotiated TLS session, but the local
|
|
4079 |
* OpenVPN instance has no memory of such a negotiation.
|
|
4080 |
*
|
|
4081 |
* It almost always occurs on UDP sessions when the passive side of the
|
|
4082 |
* connection is restarted without the active side restarting as well (the
|
|
4083 |
* passive side is the server which only listens for the connections, the
|
|
4084 |
* active side is the client which initiates connections).
|
|
4085 |
*/
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4086 |
if (DECRYPT_KEY_ENABLED (multi, ks) |
4087 |
&& key_id == ks->key_id |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4088 |
&& ks->authenticated |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
4089 |
#ifdef ENABLE_DEF_AUTH
|
4090 |
&& !ks->auth_deferred |
|
4091 |
#endif
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4092 |
&& link_socket_actual_match (from, &ks->remote_addr)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4093 |
{
|
4094 |
/* return appropriate data channel decrypt key in opt */
|
|
4095 |
opt->key_ctx_bi = &ks->key; |
|
4096 |
opt->packet_id = multi->opt.replay ? &ks->packet_id : NULL; |
|
4097 |
opt->pid_persist = NULL; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4098 |
opt->flags &= multi->opt.crypto_flags_and; |
4099 |
opt->flags |= multi->opt.crypto_flags_or; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4100 |
ASSERT (buf_advance (buf, 1)); |
4101 |
++ks->n_packets; |
|
4102 |
ks->n_bytes += buf->len; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4103 |
dmsg (D_TLS_DEBUG, |
4104 |
"TLS: data channel, key_id=%d, IP=%s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4105 |
key_id, print_link_socket_actual (from, &gc)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4106 |
gc_free (&gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4107 |
return ret; |
4108 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4109 |
#if 0 /* keys out of sync? */ |
4110 |
else
|
|
4111 |
{
|
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
4112 |
dmsg (D_TLS_ERRORS, "TLS_PRE_DECRYPT: [%d] dken=%d rkid=%d lkid=%d auth=%d def=%d match=%d",
|
4113 |
i,
|
|
4114 |
DECRYPT_KEY_ENABLED (multi, ks),
|
|
4115 |
key_id,
|
|
4116 |
ks->key_id,
|
|
4117 |
ks->authenticated,
|
|
4118 |
#ifdef ENABLE_DEF_AUTH
|
|
4119 |
ks->auth_deferred,
|
|
4120 |
#else
|
|
4121 |
-1,
|
|
4122 |
#endif
|
|
4123 |
link_socket_actual_match (from, &ks->remote_addr)); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4124 |
}
|
4125 |
#endif
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4126 |
}
|
4127 |
||
4128 |
msg (D_TLS_ERRORS, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4129 |
"TLS Error: local/remote TLS keys are out of sync: %s [%d]", |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4130 |
print_link_socket_actual (from, &gc), key_id); |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
4131 |
goto error_lite; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4132 |
}
|
4133 |
else /* control channel packet */ |
|
4134 |
{
|
|
4135 |
bool do_burst = false; |
|
4136 |
bool new_link = false; |
|
4137 |
struct session_id sid; /* remote session ID */ |
|
4138 |
||
4139 |
/* verify legal opcode */
|
|
4140 |
if (op < P_FIRST_OPCODE || op > P_LAST_OPCODE) |
|
4141 |
{
|
|
4142 |
msg (D_TLS_ERRORS, |
|
4143 |
"TLS Error: unknown opcode received from %s op=%d", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4144 |
print_link_socket_actual (from, &gc), op); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4145 |
goto error; |
4146 |
}
|
|
4147 |
||
4148 |
/* hard reset ? */
|
|
4149 |
if (is_hard_reset (op, 0)) |
|
4150 |
{
|
|
4151 |
/* verify client -> server or server -> client connection */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4152 |
if (((op == P_CONTROL_HARD_RESET_CLIENT_V1 |
4153 |
|| op == P_CONTROL_HARD_RESET_CLIENT_V2) && !multi->opt.server) |
|
4154 |
|| ((op == P_CONTROL_HARD_RESET_SERVER_V1 |
|
4155 |
|| op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server)) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4156 |
{
|
4157 |
msg (D_TLS_ERRORS, |
|
4158 |
"TLS Error: client->client or server->server connection attempted from %s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4159 |
print_link_socket_actual (from, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4160 |
goto error; |
4161 |
}
|
|
4162 |
}
|
|
4163 |
||
4164 |
/*
|
|
4165 |
* Authenticate Packet
|
|
4166 |
*/
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4167 |
dmsg (D_TLS_DEBUG, "TLS: control channel, op=%s, IP=%s", |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4168 |
packet_opcode_name (op), print_link_socket_actual (from, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4169 |
|
4170 |
/* get remote session-id */
|
|
4171 |
{
|
|
4172 |
struct buffer tmp = *buf; |
|
4173 |
buf_advance (&tmp, 1); |
|
4174 |
if (!session_id_read (&sid, &tmp) || !session_id_defined (&sid)) |
|
4175 |
{
|
|
4176 |
msg (D_TLS_ERRORS, |
|
4177 |
"TLS Error: session-id not found in packet from %s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4178 |
print_link_socket_actual (from, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4179 |
goto error; |
4180 |
}
|
|
4181 |
}
|
|
4182 |
||
4183 |
/* use session ID to match up packet with appropriate tls_session object */
|
|
4184 |
for (i = 0; i < TM_SIZE; ++i) |
|
4185 |
{
|
|
4186 |
struct tls_session *session = &multi->session[i]; |
|
4187 |
struct key_state *ks = &session->key[KS_PRIMARY]; |
|
4188 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4189 |
dmsg (D_TLS_DEBUG, |
4190 |
"TLS: initial packet test, i=%d state=%s, mysid=%s, rec-sid=%s, rec-ip=%s, stored-sid=%s, stored-ip=%s", |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4191 |
i, |
4192 |
state_name (ks->state), |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4193 |
session_id_print (&session->session_id, &gc), |
4194 |
session_id_print (&sid, &gc), |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4195 |
print_link_socket_actual (from, &gc), |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4196 |
session_id_print (&ks->session_id_remote, &gc), |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4197 |
print_link_socket_actual (&ks->remote_addr, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4198 |
|
4199 |
if (session_id_equal (&ks->session_id_remote, &sid)) |
|
4200 |
/* found a match */
|
|
4201 |
{
|
|
4202 |
if (i == TM_LAME_DUCK) { |
|
4203 |
msg (D_TLS_ERRORS, |
|
4204 |
"TLS ERROR: received control packet with stale session-id=%s", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4205 |
session_id_print (&sid, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4206 |
goto error; |
4207 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4208 |
dmsg (D_TLS_DEBUG, |
4209 |
"TLS: found match, session[%d], sid=%s", |
|
4210 |
i, session_id_print (&sid, &gc)); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4211 |
break; |
4212 |
}
|
|
4213 |
}
|
|
4214 |
||
4215 |
/*
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4216 |
* Initial packet received.
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4217 |
*/
|
4218 |
||
4219 |
if (i == TM_SIZE && is_hard_reset (op, 0)) |
|
4220 |
{
|
|
4221 |
struct tls_session *session = &multi->session[TM_ACTIVE]; |
|
4222 |
struct key_state *ks = &session->key[KS_PRIMARY]; |
|
4223 |
||
4224 |
if (!is_hard_reset (op, multi->opt.key_method)) |
|
4225 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4226 |
msg (D_TLS_ERRORS, "TLS ERROR: initial packet local/remote key_method mismatch, local key_method=%d, op=%s", |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4227 |
multi->opt.key_method, |
4228 |
packet_opcode_name (op)); |
|
4229 |
goto error; |
|
4230 |
}
|
|
4231 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4232 |
/*
|
4233 |
* If we have no session currently in progress, the initial packet will
|
|
4234 |
* open a new session in TM_ACTIVE rather than TM_UNTRUSTED.
|
|
4235 |
*/
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4236 |
if (!session_id_defined (&ks->session_id_remote)) |
4237 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4238 |
if (multi->opt.single_session && multi->n_sessions) |
4239 |
{
|
|
4240 |
msg (D_TLS_ERRORS, |
|
1.1.4
by Alberto Gonzalez Iniesta
Import upstream version 2.0.6 |
4241 |
"TLS Error: Cannot accept new session request from %s due to session context expire or --single-session [1]", |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4242 |
print_link_socket_actual (from, &gc)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4243 |
goto error; |
4244 |
}
|
|
4245 |
||
4246 |
#ifdef ENABLE_MANAGEMENT
|
|
4247 |
if (management) |
|
4248 |
{
|
|
4249 |
management_set_state (management, |
|
4250 |
OPENVPN_STATE_AUTH, |
|
4251 |
NULL, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4252 |
0, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4253 |
0); |
4254 |
}
|
|
4255 |
#endif
|
|
4256 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4257 |
msg (D_TLS_DEBUG_LOW, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4258 |
"TLS: Initial packet from %s, sid=%s", |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4259 |
print_link_socket_actual (from, &gc), |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4260 |
session_id_print (&sid, &gc)); |
4261 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4262 |
do_burst = true; |
4263 |
new_link = true; |
|
4264 |
i = TM_ACTIVE; |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4265 |
session->untrusted_addr = *from; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4266 |
}
|
4267 |
}
|
|
4268 |
||
4269 |
if (i == TM_SIZE && is_hard_reset (op, 0)) |
|
4270 |
{
|
|
4271 |
/*
|
|
4272 |
* No match with existing sessions,
|
|
4273 |
* probably a new session.
|
|
4274 |
*/
|
|
4275 |
struct tls_session *session = &multi->session[TM_UNTRUSTED]; |
|
4276 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4277 |
/*
|
4278 |
* If --single-session, don't allow any hard-reset connection request
|
|
4279 |
* unless it the the first packet of the session.
|
|
4280 |
*/
|
|
4281 |
if (multi->opt.single_session) |
|
4282 |
{
|
|
4283 |
msg (D_TLS_ERRORS, |
|
1.1.4
by Alberto Gonzalez Iniesta
Import upstream version 2.0.6 |
4284 |
"TLS Error: Cannot accept new session request from %s due to session context expire or --single-session [2]", |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4285 |
print_link_socket_actual (from, &gc)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4286 |
goto error; |
4287 |
}
|
|
4288 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4289 |
if (!is_hard_reset (op, multi->opt.key_method)) |
4290 |
{
|
|
4291 |
msg (D_TLS_ERRORS, "TLS ERROR: new session local/remote key_method mismatch, local key_method=%d, op=%s", |
|
4292 |
multi->opt.key_method, |
|
4293 |
packet_opcode_name (op)); |
|
4294 |
goto error; |
|
4295 |
}
|
|
4296 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4297 |
if (!read_control_auth (buf, &session->tls_auth, from)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4298 |
goto error; |
4299 |
||
4300 |
/*
|
|
4301 |
* New session-initiating control packet is authenticated at this point,
|
|
4302 |
* assuming that the --tls-auth command line option was used.
|
|
4303 |
*
|
|
4304 |
* Without --tls-auth, we leave authentication entirely up to TLS.
|
|
4305 |
*/
|
|
4306 |
msg (D_TLS_DEBUG_LOW, |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4307 |
"TLS: new session incoming connection from %s", |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4308 |
print_link_socket_actual (from, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4309 |
|
4310 |
new_link = true; |
|
4311 |
i = TM_UNTRUSTED; |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4312 |
session->untrusted_addr = *from; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4313 |
}
|
4314 |
else
|
|
4315 |
{
|
|
4316 |
struct tls_session *session = &multi->session[i]; |
|
4317 |
struct key_state *ks = &session->key[KS_PRIMARY]; |
|
4318 |
||
4319 |
/*
|
|
4320 |
* Packet must belong to an existing session.
|
|
4321 |
*/
|
|
4322 |
if (i != TM_ACTIVE && i != TM_UNTRUSTED) |
|
4323 |
{
|
|
4324 |
msg (D_TLS_ERRORS, |
|
4325 |
"TLS Error: Unroutable control packet received from %s (si=%d op=%s)", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4326 |
print_link_socket_actual (from, &gc), |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4327 |
i, |
4328 |
packet_opcode_name (op)); |
|
4329 |
goto error; |
|
4330 |
}
|
|
4331 |
||
4332 |
/*
|
|
4333 |
* Verify remote IP address
|
|
4334 |
*/
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4335 |
if (!new_link && !link_socket_actual_match (&ks->remote_addr, from)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4336 |
{
|
4337 |
msg (D_TLS_ERRORS, "TLS Error: Received control packet from unexpected IP addr: %s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4338 |
print_link_socket_actual (from, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4339 |
goto error; |
4340 |
}
|
|
4341 |
||
4342 |
/*
|
|
4343 |
* Remote is requesting a key renegotiation
|
|
4344 |
*/
|
|
4345 |
if (op == P_CONTROL_SOFT_RESET_V1 |
|
4346 |
&& DECRYPT_KEY_ENABLED (multi, ks)) |
|
4347 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4348 |
if (!read_control_auth (buf, &session->tls_auth, from)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4349 |
goto error; |
4350 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4351 |
key_state_soft_reset (session); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4352 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4353 |
dmsg (D_TLS_DEBUG, |
4354 |
"TLS: received P_CONTROL_SOFT_RESET_V1 s=%d sid=%s", |
|
4355 |
i, session_id_print (&sid, &gc)); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4356 |
}
|
4357 |
else
|
|
4358 |
{
|
|
4359 |
/*
|
|
4360 |
* Remote responding to our key renegotiation request?
|
|
4361 |
*/
|
|
4362 |
if (op == P_CONTROL_SOFT_RESET_V1) |
|
4363 |
do_burst = true; |
|
4364 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4365 |
if (!read_control_auth (buf, &session->tls_auth, from)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4366 |
goto error; |
4367 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4368 |
dmsg (D_TLS_DEBUG, |
4369 |
"TLS: received control channel packet s#=%d sid=%s", |
|
4370 |
i, session_id_print (&sid, &gc)); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4371 |
}
|
4372 |
}
|
|
4373 |
||
4374 |
/*
|
|
4375 |
* We have an authenticated packet (if --tls-auth was set).
|
|
4376 |
* Now pass to our reliability level which deals with
|
|
4377 |
* packet acknowledgements, retransmits, sequencing, etc.
|
|
4378 |
*/
|
|
4379 |
{
|
|
4380 |
struct tls_session *session = &multi->session[i]; |
|
4381 |
struct key_state *ks = &session->key[KS_PRIMARY]; |
|
4382 |
||
4383 |
/* Make sure we were initialized and that we're not in an error state */
|
|
4384 |
ASSERT (ks->state != S_UNDEF); |
|
4385 |
ASSERT (ks->state != S_ERROR); |
|
4386 |
ASSERT (session_id_defined (&session->session_id)); |
|
4387 |
||
4388 |
/* Let our caller know we processed a control channel packet */
|
|
4389 |
ret = true; |
|
4390 |
||
4391 |
/*
|
|
4392 |
* Set our remote address and remote session_id
|
|
4393 |
*/
|
|
4394 |
if (new_link) |
|
4395 |
{
|
|
4396 |
ks->session_id_remote = sid; |
|
4397 |
ks->remote_addr = *from; |
|
4398 |
++multi->n_sessions; |
|
4399 |
}
|
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4400 |
else if (!link_socket_actual_match (&ks->remote_addr, from)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4401 |
{
|
4402 |
msg (D_TLS_ERRORS, |
|
4403 |
"TLS Error: Existing session control channel packet from unknown IP address: %s", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4404 |
print_link_socket_actual (from, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4405 |
goto error; |
4406 |
}
|
|
4407 |
||
4408 |
/*
|
|
4409 |
* Should we do a retransmit of all unacknowledged packets in
|
|
4410 |
* the send buffer? This improves the start-up efficiency of the
|
|
4411 |
* initial key negotiation after the 2nd peer comes online.
|
|
4412 |
*/
|
|
4413 |
if (do_burst && !session->burst) |
|
4414 |
{
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4415 |
reliable_schedule_now (ks->send_reliable); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4416 |
session->burst = true; |
4417 |
}
|
|
4418 |
||
4419 |
/* Check key_id */
|
|
4420 |
if (ks->key_id != key_id) |
|
4421 |
{
|
|
4422 |
msg (D_TLS_ERRORS, |
|
4423 |
"TLS ERROR: local/remote key IDs out of sync (%d/%d) ID: %s", |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4424 |
ks->key_id, key_id, print_key_id (multi, &gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4425 |
goto error; |
4426 |
}
|
|
4427 |
||
4428 |
/*
|
|
4429 |
* Process incoming ACKs for packets we can now
|
|
4430 |
* delete from reliable send buffer
|
|
4431 |
*/
|
|
4432 |
{
|
|
4433 |
/* buffers all packet IDs to delete from send_reliable */
|
|
4434 |
struct reliable_ack send_ack; |
|
4435 |
||
4436 |
send_ack.len = 0; |
|
4437 |
if (!reliable_ack_read (&send_ack, buf, &session->session_id)) |
|
4438 |
{
|
|
4439 |
msg (D_TLS_ERRORS, |
|
4440 |
"TLS Error: reading acknowledgement record from packet"); |
|
4441 |
goto error; |
|
4442 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4443 |
reliable_send_purge (ks->send_reliable, &send_ack); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4444 |
}
|
4445 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4446 |
if (op != P_ACK_V1 && reliable_can_get (ks->rec_reliable)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4447 |
{
|
4448 |
packet_id_type id; |
|
4449 |
||
4450 |
/* Extract the packet ID from the packet */
|
|
4451 |
if (reliable_ack_read_packet_id (buf, &id)) |
|
4452 |
{
|
|
4453 |
/* Avoid deadlock by rejecting packet that would de-sequentialize receive buffer */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4454 |
if (reliable_wont_break_sequentiality (ks->rec_reliable, id)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4455 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4456 |
if (reliable_not_replay (ks->rec_reliable, id)) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4457 |
{
|
4458 |
/* Save incoming ciphertext packet to reliable buffer */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4459 |
struct buffer *in = reliable_get_buf (ks->rec_reliable); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4460 |
ASSERT (in); |
4461 |
ASSERT (buf_copy (in, buf)); |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4462 |
reliable_mark_active_incoming (ks->rec_reliable, in, id, op); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4463 |
}
|
4464 |
||
4465 |
/* Process outgoing acknowledgment for packet just received, even if it's a replay */
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4466 |
reliable_ack_acknowledge_packet_id (ks->rec_ack, id); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4467 |
}
|
4468 |
}
|
|
4469 |
}
|
|
4470 |
}
|
|
4471 |
}
|
|
4472 |
}
|
|
4473 |
||
4474 |
done: |
|
4475 |
buf->len = 0; |
|
4476 |
opt->key_ctx_bi = NULL; |
|
4477 |
opt->packet_id = NULL; |
|
4478 |
opt->pid_persist = NULL; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4479 |
opt->flags &= multi->opt.crypto_flags_and; |
4480 |
gc_free (&gc); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4481 |
return ret; |
4482 |
||
4483 |
error: |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4484 |
++multi->n_soft_errors; |
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
4485 |
error_lite: |
4486 |
ERR_clear_error (); |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4487 |
goto done; |
4488 |
}
|
|
4489 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4490 |
/*
|
4491 |
* This function is similar to tls_pre_decrypt, except it is called
|
|
4492 |
* when we are in server mode and receive an initial incoming
|
|
4493 |
* packet. Note that we don't modify
|
|
4494 |
* any state in our parameter objects. The purpose is solely to
|
|
4495 |
* determine whether we should generate a client instance
|
|
4496 |
* object, in which case true is returned.
|
|
4497 |
*
|
|
4498 |
* This function is essentially the first-line HMAC firewall
|
|
4499 |
* on the UDP port listener in --mode server mode.
|
|
4500 |
*/
|
|
4501 |
bool
|
|
4502 |
tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4503 |
const struct link_socket_actual *from, |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4504 |
const struct buffer *buf) |
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4505 |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4506 |
{
|
4507 |
struct gc_arena gc = gc_new (); |
|
4508 |
bool ret = false; |
|
4509 |
||
4510 |
if (buf->len > 0) |
|
4511 |
{
|
|
4512 |
int op; |
|
4513 |
int key_id; |
|
4514 |
||
4515 |
/* get opcode and key ID */
|
|
4516 |
{
|
|
4517 |
uint8_t c = *BPTR (buf); |
|
4518 |
op = c >> P_OPCODE_SHIFT; |
|
4519 |
key_id = c & P_KEY_ID_MASK; |
|
4520 |
}
|
|
4521 |
||
4522 |
/* this packet is from an as-yet untrusted source, so
|
|
4523 |
scrutinize carefully */
|
|
4524 |
||
4525 |
if (op != P_CONTROL_HARD_RESET_CLIENT_V2) |
|
4526 |
{
|
|
4527 |
/*
|
|
4528 |
* This can occur due to bogus data or DoS packets.
|
|
4529 |
*/
|
|
4530 |
dmsg (D_TLS_STATE_ERRORS, |
|
4531 |
"TLS State Error: No TLS state for client %s, opcode=%d", |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4532 |
print_link_socket_actual (from, &gc), |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4533 |
op); |
4534 |
goto error; |
|
4535 |
}
|
|
4536 |
||
4537 |
if (key_id != 0) |
|
4538 |
{
|
|
4539 |
dmsg (D_TLS_STATE_ERRORS, |
|
4540 |
"TLS State Error: Unknown key ID (%d) received from %s -- 0 was expected", |
|
4541 |
key_id, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4542 |
print_link_socket_actual (from, &gc)); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4543 |
goto error; |
4544 |
}
|
|
4545 |
||
4546 |
if (buf->len > EXPANDED_SIZE_DYNAMIC (&tas->frame)) |
|
4547 |
{
|
|
4548 |
dmsg (D_TLS_STATE_ERRORS, |
|
4549 |
"TLS State Error: Large packet (size %d) received from %s -- a packet no larger than %d bytes was expected", |
|
4550 |
buf->len, |
|
1.1.7
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc4 |
4551 |
print_link_socket_actual (from, &gc), |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4552 |
EXPANDED_SIZE_DYNAMIC (&tas->frame)); |
4553 |
goto error; |
|
4554 |
}
|
|
4555 |
||
4556 |
{
|
|
4557 |
struct buffer newbuf = clone_buf (buf); |
|
4558 |
struct crypto_options co = tas->tls_auth_options; |
|
4559 |
bool status; |
|
4560 |
||
4561 |
/*
|
|
4562 |
* We are in read-only mode at this point with respect to TLS
|
|
4563 |
* control channel state. After we build a new client instance
|
|
4564 |
* object, we will process this session-initiating packet for real.
|
|
4565 |
*/
|
|
4566 |
co.flags |= CO_IGNORE_PACKET_ID; |
|
4567 |
||
4568 |
/* HMAC test, if --tls-auth was specified */
|
|
4569 |
status = read_control_auth (&newbuf, &co, from); |
|
4570 |
free_buf (&newbuf); |
|
4571 |
if (!status) |
|
4572 |
goto error; |
|
4573 |
||
4574 |
/*
|
|
4575 |
* At this point, if --tls-auth is being used, we know that
|
|
4576 |
* the packet has passed the HMAC test, but we don't know if
|
|
4577 |
* it is a replay yet. We will attempt to defeat replays
|
|
4578 |
* by not advancing to the S_START state until we
|
|
4579 |
* receive an ACK from our first reply to the client
|
|
4580 |
* that includes an HMAC of our randomly generated 64 bit
|
|
4581 |
* session ID.
|
|
4582 |
*
|
|
4583 |
* On the other hand if --tls-auth is not being used, we
|
|
4584 |
* will proceed to begin the TLS authentication
|
|
4585 |
* handshake with only cursory integrity checks having
|
|
4586 |
* been performed, since we will be leaving the task
|
|
4587 |
* of authentication solely up to TLS.
|
|
4588 |
*/
|
|
4589 |
||
4590 |
ret = true; |
|
4591 |
}
|
|
4592 |
}
|
|
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
4593 |
gc_free (&gc); |
4594 |
return ret; |
|
4595 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4596 |
error: |
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
4597 |
ERR_clear_error (); |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4598 |
gc_free (&gc); |
4599 |
return ret; |
|
4600 |
}
|
|
4601 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4602 |
/* Choose the key with which to encrypt a data packet */
|
4603 |
void
|
|
4604 |
tls_pre_encrypt (struct tls_multi *multi, |
|
4605 |
struct buffer *buf, struct crypto_options *opt) |
|
4606 |
{
|
|
4607 |
multi->save_ks = NULL; |
|
4608 |
if (buf->len > 0) |
|
4609 |
{
|
|
4610 |
int i; |
|
4611 |
for (i = 0; i < KEY_SCAN_SIZE; ++i) |
|
4612 |
{
|
|
4613 |
struct key_state *ks = multi->key_scan[i]; |
|
1.1.9
by Alberto Gonzalez Iniesta
Import upstream version 2.1~rc8 |
4614 |
if (ks->state >= S_ACTIVE |
4615 |
&& ks->authenticated |
|
4616 |
#ifdef ENABLE_DEF_AUTH
|
|
4617 |
&& !ks->auth_deferred |
|
4618 |
#endif
|
|
4619 |
&& (!ks->key_id || now >= ks->auth_deferred_expire)) |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4620 |
{
|
4621 |
opt->key_ctx_bi = &ks->key; |
|
4622 |
opt->packet_id = multi->opt.replay ? &ks->packet_id : NULL; |
|
4623 |
opt->pid_persist = NULL; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4624 |
opt->flags &= multi->opt.crypto_flags_and; |
4625 |
opt->flags |= multi->opt.crypto_flags_or; |
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4626 |
multi->save_ks = ks; |
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4627 |
dmsg (D_TLS_DEBUG, "TLS: tls_pre_encrypt: key_id=%d", ks->key_id); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4628 |
return; |
4629 |
}
|
|
4630 |
}
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4631 |
|
4632 |
{
|
|
4633 |
struct gc_arena gc = gc_new (); |
|
4634 |
dmsg (D_TLS_NO_SEND_KEY, "TLS Warning: no data channel send key available: %s", |
|
4635 |
print_key_id (multi, &gc)); |
|
4636 |
gc_free (&gc); |
|
4637 |
}
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4638 |
}
|
4639 |
||
4640 |
buf->len = 0; |
|
4641 |
opt->key_ctx_bi = NULL; |
|
4642 |
opt->packet_id = NULL; |
|
4643 |
opt->pid_persist = NULL; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4644 |
opt->flags &= multi->opt.crypto_flags_and; |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4645 |
}
|
4646 |
||
4647 |
/* Prepend the appropriate opcode to encrypted buffer prior to TCP/UDP send */
|
|
4648 |
void
|
|
4649 |
tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) |
|
4650 |
{
|
|
4651 |
struct key_state *ks; |
|
4652 |
uint8_t *op; |
|
4653 |
||
4654 |
ks = multi->save_ks; |
|
4655 |
multi->save_ks = NULL; |
|
4656 |
if (buf->len > 0) |
|
4657 |
{
|
|
4658 |
ASSERT (ks); |
|
4659 |
ASSERT (op = buf_prepend (buf, 1)); |
|
4660 |
*op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id; |
|
4661 |
++ks->n_packets; |
|
4662 |
ks->n_bytes += buf->len; |
|
4663 |
}
|
|
4664 |
}
|
|
4665 |
||
4666 |
/*
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4667 |
* Send a payload over the TLS control channel.
|
4668 |
* Called externally.
|
|
4669 |
*/
|
|
4670 |
||
4671 |
bool
|
|
4672 |
tls_send_payload (struct tls_multi *multi, |
|
4673 |
const uint8_t *data, |
|
4674 |
int size) |
|
4675 |
{
|
|
4676 |
struct tls_session *session; |
|
4677 |
struct key_state *ks; |
|
4678 |
bool ret = false; |
|
4679 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
4680 |
ERR_clear_error (); |
4681 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4682 |
ASSERT (multi); |
4683 |
||
4684 |
session = &multi->session[TM_ACTIVE]; |
|
4685 |
ks = &session->key[KS_PRIMARY]; |
|
4686 |
||
4687 |
if (ks->state >= S_ACTIVE) |
|
4688 |
{
|
|
4689 |
if (key_state_write_plaintext_const (multi, ks, data, size) == 1) |
|
4690 |
ret = true; |
|
4691 |
}
|
|
4692 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
4693 |
ERR_clear_error (); |
4694 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4695 |
return ret; |
4696 |
}
|
|
4697 |
||
4698 |
bool
|
|
4699 |
tls_rec_payload (struct tls_multi *multi, |
|
4700 |
struct buffer *buf) |
|
4701 |
{
|
|
4702 |
struct tls_session *session; |
|
4703 |
struct key_state *ks; |
|
4704 |
bool ret = false; |
|
4705 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
4706 |
ERR_clear_error (); |
4707 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4708 |
ASSERT (multi); |
4709 |
||
4710 |
session = &multi->session[TM_ACTIVE]; |
|
4711 |
ks = &session->key[KS_PRIMARY]; |
|
4712 |
||
4713 |
if (ks->state >= S_ACTIVE && BLEN (&ks->plaintext_read_buf)) |
|
4714 |
{
|
|
4715 |
if (buf_copy (buf, &ks->plaintext_read_buf)) |
|
4716 |
ret = true; |
|
4717 |
ks->plaintext_read_buf.len = 0; |
|
4718 |
}
|
|
4719 |
||
1.1.2
by Alberto Gonzalez Iniesta
Import upstream version 2.0.2 |
4720 |
ERR_clear_error (); |
4721 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4722 |
return ret; |
4723 |
}
|
|
4724 |
||
4725 |
/*
|
|
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4726 |
* Dump a human-readable rendition of an openvpn packet
|
4727 |
* into a garbage collectable string which is returned.
|
|
4728 |
*/
|
|
4729 |
const char * |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4730 |
protocol_dump (struct buffer *buffer, unsigned int flags, struct gc_arena *gc) |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4731 |
{
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4732 |
struct buffer out = alloc_buf_gc (256, gc); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4733 |
struct buffer buf = *buffer; |
4734 |
||
4735 |
uint8_t c; |
|
4736 |
int op; |
|
4737 |
int key_id; |
|
4738 |
||
4739 |
int tls_auth_hmac_size = (flags & PD_TLS_AUTH_HMAC_SIZE_MASK); |
|
4740 |
||
4741 |
if (buf.len <= 0) |
|
4742 |
{
|
|
4743 |
buf_printf (&out, "DATA UNDEF len=%d", buf.len); |
|
4744 |
goto done; |
|
4745 |
}
|
|
4746 |
||
4747 |
if (!(flags & PD_TLS)) |
|
4748 |
goto print_data; |
|
4749 |
||
4750 |
/*
|
|
4751 |
* Initial byte (opcode)
|
|
4752 |
*/
|
|
4753 |
if (!buf_read (&buf, &c, sizeof (c))) |
|
4754 |
goto done; |
|
4755 |
op = (c >> P_OPCODE_SHIFT); |
|
4756 |
key_id = c & P_KEY_ID_MASK; |
|
4757 |
buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id); |
|
4758 |
||
4759 |
if (op == P_DATA_V1) |
|
4760 |
goto print_data; |
|
4761 |
||
4762 |
/*
|
|
4763 |
* Session ID
|
|
4764 |
*/
|
|
4765 |
{
|
|
4766 |
struct session_id sid; |
|
4767 |
||
4768 |
if (!session_id_read (&sid, &buf)) |
|
4769 |
goto done; |
|
4770 |
if (flags & PD_VERBOSE) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4771 |
buf_printf (&out, " sid=%s", session_id_print (&sid, gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4772 |
}
|
4773 |
||
4774 |
/*
|
|
4775 |
* tls-auth hmac + packet_id
|
|
4776 |
*/
|
|
4777 |
if (tls_auth_hmac_size) |
|
4778 |
{
|
|
4779 |
struct packet_id_net pin; |
|
4780 |
uint8_t tls_auth_hmac[MAX_HMAC_KEY_LENGTH]; |
|
4781 |
||
4782 |
ASSERT (tls_auth_hmac_size <= MAX_HMAC_KEY_LENGTH); |
|
4783 |
||
4784 |
if (!buf_read (&buf, tls_auth_hmac, tls_auth_hmac_size)) |
|
4785 |
goto done; |
|
4786 |
if (flags & PD_VERBOSE) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4787 |
buf_printf (&out, " tls_hmac=%s", format_hex (tls_auth_hmac, tls_auth_hmac_size, 0, gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4788 |
|
4789 |
if (!packet_id_read (&pin, &buf, true)) |
|
4790 |
goto done; |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4791 |
buf_printf(&out, " pid=%s", packet_id_net_print (&pin, (flags & PD_VERBOSE), gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4792 |
}
|
4793 |
||
4794 |
/*
|
|
4795 |
* ACK list
|
|
4796 |
*/
|
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4797 |
buf_printf (&out, " %s", reliable_ack_print(&buf, (flags & PD_VERBOSE), gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4798 |
|
4799 |
if (op == P_ACK_V1) |
|
4800 |
goto done; |
|
4801 |
||
4802 |
/*
|
|
4803 |
* Packet ID
|
|
4804 |
*/
|
|
4805 |
{
|
|
4806 |
packet_id_type l; |
|
4807 |
if (!buf_read (&buf, &l, sizeof (l))) |
|
4808 |
goto done; |
|
4809 |
l = ntohpid (l); |
|
4810 |
buf_printf (&out, " pid=" packet_id_format, (packet_id_print_type)l); |
|
4811 |
}
|
|
4812 |
||
4813 |
print_data: |
|
4814 |
if (flags & PD_SHOW_DATA) |
|
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4815 |
buf_printf (&out, " DATA %s", format_hex (BPTR (&buf), BLEN (&buf), 80, gc)); |
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4816 |
else
|
4817 |
buf_printf (&out, " DATA len=%d", buf.len); |
|
4818 |
||
4819 |
done: |
|
4820 |
return BSTR (&out); |
|
4821 |
}
|
|
4822 |
||
1.1.1
by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6 |
4823 |
#ifdef EXTRACT_X509_FIELD_TEST
|
4824 |
||
4825 |
void
|
|
4826 |
extract_x509_field_test (void) |
|
4827 |
{
|
|
4828 |
char line[8]; |
|
4829 |
char field[4]; |
|
4830 |
static const char field_name[] = "CN"; |
|
4831 |
||
4832 |
while (fgets (line, sizeof (line), stdin)) |
|
4833 |
{
|
|
4834 |
chomp (line); |
|
4835 |
extract_x509_field (line, field_name, field, sizeof (field)); |
|
4836 |
printf ("CN: '%s'\n", field); |
|
4837 |
}
|
|
4838 |
}
|
|
4839 |
||
4840 |
#endif
|
|
4841 |
||
1
by Alberto Gonzalez Iniesta
Import upstream version 1.6.0 |
4842 |
#else
|
4843 |
static void dummy(void) {} |
|
4844 |
#endif /* USE_CRYPTO && USE_SSL*/ |