git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5105 e7ae566f-a301-0410-adde-c780ea21d3b5
| ... | ... |
@@ -1458,8 +1458,9 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi |
| 1458 | 1458 |
|
| 1459 | 1459 |
ASSERT (mi->context.c1.tuntap); |
| 1460 | 1460 |
|
| 1461 |
- /* lock down the common name so it can't change during future TLS renegotiations */ |
|
| 1461 |
+ /* lock down the common name and cert hashes so they can't change during future TLS renegotiations */ |
|
| 1462 | 1462 |
tls_lock_common_name (mi->context.c2.tls_multi); |
| 1463 |
+ tls_lock_cert_hash_set (mi->context.c2.tls_multi); |
|
| 1463 | 1464 |
|
| 1464 | 1465 |
/* generate a msg() prefix for this client instance */ |
| 1465 | 1466 |
generate_prefix (mi); |
| ... | ... |
@@ -340,6 +340,104 @@ tmp_rsa_cb (SSL * s, int is_export, int keylength) |
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 | 342 |
/* |
| 343 |
+ * Cert hash functions |
|
| 344 |
+ */ |
|
| 345 |
+static void |
|
| 346 |
+cert_hash_remember (struct tls_session *session, const int error_depth, const unsigned char *sha1_hash) |
|
| 347 |
+{
|
|
| 348 |
+ if (error_depth >= 0 && error_depth < MAX_CERT_DEPTH) |
|
| 349 |
+ {
|
|
| 350 |
+ if (!session->cert_hash_set) |
|
| 351 |
+ ALLOC_OBJ_CLEAR (session->cert_hash_set, struct cert_hash_set); |
|
| 352 |
+ if (!session->cert_hash_set->ch[error_depth]) |
|
| 353 |
+ ALLOC_OBJ (session->cert_hash_set->ch[error_depth], struct cert_hash); |
|
| 354 |
+ {
|
|
| 355 |
+ struct cert_hash *ch = session->cert_hash_set->ch[error_depth]; |
|
| 356 |
+ memcpy (ch->sha1_hash, sha1_hash, SHA_DIGEST_LENGTH); |
|
| 357 |
+ } |
|
| 358 |
+ } |
|
| 359 |
+} |
|
| 360 |
+ |
|
| 361 |
+#if 0 |
|
| 362 |
+static void |
|
| 363 |
+cert_hash_print (const struct cert_hash_set *chs, int msglevel) |
|
| 364 |
+{
|
|
| 365 |
+ struct gc_arena gc = gc_new (); |
|
| 366 |
+ msg (msglevel, "CERT_HASH"); |
|
| 367 |
+ if (chs) |
|
| 368 |
+ {
|
|
| 369 |
+ int i; |
|
| 370 |
+ for (i = 0; i < MAX_CERT_DEPTH; ++i) |
|
| 371 |
+ {
|
|
| 372 |
+ const struct cert_hash *ch = chs->ch[i]; |
|
| 373 |
+ if (ch) |
|
| 374 |
+ msg (msglevel, "%d:%s", i, format_hex(ch->sha1_hash, SHA_DIGEST_LENGTH, 0, &gc)); |
|
| 375 |
+ } |
|
| 376 |
+ } |
|
| 377 |
+ gc_free (&gc); |
|
| 378 |
+} |
|
| 379 |
+#endif |
|
| 380 |
+ |
|
| 381 |
+static void |
|
| 382 |
+cert_hash_free (struct cert_hash_set *chs) |
|
| 383 |
+{
|
|
| 384 |
+ if (chs) |
|
| 385 |
+ {
|
|
| 386 |
+ int i; |
|
| 387 |
+ for (i = 0; i < MAX_CERT_DEPTH; ++i) |
|
| 388 |
+ free (chs->ch[i]); |
|
| 389 |
+ free (chs); |
|
| 390 |
+ } |
|
| 391 |
+} |
|
| 392 |
+ |
|
| 393 |
+static bool |
|
| 394 |
+cert_hash_compare (const struct cert_hash_set *chs1, const struct cert_hash_set *chs2) |
|
| 395 |
+{
|
|
| 396 |
+ if (chs1 && chs2) |
|
| 397 |
+ {
|
|
| 398 |
+ int i; |
|
| 399 |
+ for (i = 0; i < MAX_CERT_DEPTH; ++i) |
|
| 400 |
+ {
|
|
| 401 |
+ const struct cert_hash *ch1 = chs1->ch[i]; |
|
| 402 |
+ const struct cert_hash *ch2 = chs2->ch[i]; |
|
| 403 |
+ |
|
| 404 |
+ if (!ch1 && !ch2) |
|
| 405 |
+ continue; |
|
| 406 |
+ else if (ch1 && ch2 && !memcmp (ch1->sha1_hash, ch2->sha1_hash, SHA_DIGEST_LENGTH)) |
|
| 407 |
+ continue; |
|
| 408 |
+ else |
|
| 409 |
+ return false; |
|
| 410 |
+ } |
|
| 411 |
+ return true; |
|
| 412 |
+ } |
|
| 413 |
+ else if (!chs1 && !chs2) |
|
| 414 |
+ return true; |
|
| 415 |
+ else |
|
| 416 |
+ return false; |
|
| 417 |
+} |
|
| 418 |
+ |
|
| 419 |
+static struct cert_hash_set * |
|
| 420 |
+cert_hash_copy (const struct cert_hash_set *chs) |
|
| 421 |
+{
|
|
| 422 |
+ struct cert_hash_set *dest = NULL; |
|
| 423 |
+ if (chs) |
|
| 424 |
+ {
|
|
| 425 |
+ int i; |
|
| 426 |
+ ALLOC_OBJ_CLEAR (dest, struct cert_hash_set); |
|
| 427 |
+ for (i = 0; i < MAX_CERT_DEPTH; ++i) |
|
| 428 |
+ {
|
|
| 429 |
+ const struct cert_hash *ch = chs->ch[i]; |
|
| 430 |
+ if (ch) |
|
| 431 |
+ {
|
|
| 432 |
+ ALLOC_OBJ (dest->ch[i], struct cert_hash); |
|
| 433 |
+ memcpy (dest->ch[i]->sha1_hash, ch->sha1_hash, SHA_DIGEST_LENGTH); |
|
| 434 |
+ } |
|
| 435 |
+ } |
|
| 436 |
+ } |
|
| 437 |
+ return dest; |
|
| 438 |
+} |
|
| 439 |
+ |
|
| 440 |
+/* |
|
| 343 | 441 |
* Extract a field from an X509 subject name. |
| 344 | 442 |
* |
| 345 | 443 |
* Example: |
| ... | ... |
@@ -603,7 +701,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
| 603 | 603 |
SSL *ssl; |
| 604 | 604 |
struct tls_session *session; |
| 605 | 605 |
const struct tls_options *opt; |
| 606 |
- const int max_depth = 8; |
|
| 606 |
+ const int max_depth = MAX_CERT_DEPTH; |
|
| 607 | 607 |
struct argv argv = argv_new (); |
| 608 | 608 |
|
| 609 | 609 |
/* get the tls_session pointer */ |
| ... | ... |
@@ -645,9 +743,16 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
| 645 | 645 |
|
| 646 | 646 |
string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags); |
| 647 | 647 |
|
| 648 |
+ cert_hash_remember (session, ctx->error_depth, ctx->current_cert->sha1_hash); |
|
| 649 |
+ |
|
| 648 | 650 |
#if 0 /* print some debugging info */ |
| 649 |
- msg (D_LOW, "LOCAL OPT: %s", opt->local_options); |
|
| 650 |
- msg (D_LOW, "X509: %s", subject); |
|
| 651 |
+ {
|
|
| 652 |
+ struct gc_arena gc = gc_new (); |
|
| 653 |
+ msg (M_INFO, "LOCAL OPT[%d]: %s", ctx->error_depth, opt->local_options); |
|
| 654 |
+ msg (M_INFO, "X509[%d]: %s", ctx->error_depth, subject); |
|
| 655 |
+ msg (M_INFO, "SHA1[%d]: %s", ctx->error_depth, format_hex(ctx->current_cert->sha1_hash, SHA_DIGEST_LENGTH, 0, &gc)); |
|
| 656 |
+ gc_free (&gc); |
|
| 657 |
+ } |
|
| 651 | 658 |
#endif |
| 652 | 659 |
|
| 653 | 660 |
/* did peer present cert which was signed our root cert? */ |
| ... | ... |
@@ -898,6 +1003,14 @@ tls_lock_common_name (struct tls_multi *multi) |
| 898 | 898 |
multi->locked_cn = string_alloc (cn, NULL); |
| 899 | 899 |
} |
| 900 | 900 |
|
| 901 |
+void |
|
| 902 |
+tls_lock_cert_hash_set (struct tls_multi *multi) |
|
| 903 |
+{
|
|
| 904 |
+ const struct cert_hash_set *chs = multi->session[TM_ACTIVE].cert_hash_set; |
|
| 905 |
+ if (chs && !multi->locked_cert_hash_set) |
|
| 906 |
+ multi->locked_cert_hash_set = cert_hash_copy (chs); |
|
| 907 |
+} |
|
| 908 |
+ |
|
| 901 | 909 |
static bool |
| 902 | 910 |
tls_lock_username (struct tls_multi *multi, const char *username) |
| 903 | 911 |
{
|
| ... | ... |
@@ -2251,6 +2364,8 @@ tls_session_free (struct tls_session *session, bool clear) |
| 2251 | 2251 |
if (session->common_name) |
| 2252 | 2252 |
free (session->common_name); |
| 2253 | 2253 |
|
| 2254 |
+ cert_hash_free (session->cert_hash_set); |
|
| 2255 |
+ |
|
| 2254 | 2256 |
if (clear) |
| 2255 | 2257 |
CLEAR (*session); |
| 2256 | 2258 |
} |
| ... | ... |
@@ -2444,6 +2559,8 @@ tls_multi_free (struct tls_multi *multi, bool clear) |
| 2444 | 2444 |
if (multi->locked_username) |
| 2445 | 2445 |
free (multi->locked_username); |
| 2446 | 2446 |
|
| 2447 |
+ cert_hash_free (multi->locked_cert_hash_set); |
|
| 2448 |
+ |
|
| 2447 | 2449 |
for (i = 0; i < TM_SIZE; ++i) |
| 2448 | 2450 |
tls_session_free (&multi->session[i], false); |
| 2449 | 2451 |
|
| ... | ... |
@@ -3492,6 +3609,20 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
| 3492 | 3492 |
} |
| 3493 | 3493 |
} |
| 3494 | 3494 |
|
| 3495 |
+ /* Don't allow the cert hashes to change once they have been locked */ |
|
| 3496 |
+ if (ks->authenticated && multi->locked_cert_hash_set) |
|
| 3497 |
+ {
|
|
| 3498 |
+ const struct cert_hash_set *chs = session->cert_hash_set; |
|
| 3499 |
+ if (chs && !cert_hash_compare (chs, multi->locked_cert_hash_set)) |
|
| 3500 |
+ {
|
|
| 3501 |
+ msg (D_TLS_ERRORS, "TLS Auth Error: TLS object CN=%s client-provided SSL certs unexpectedly changed during mid-session reauth", |
|
| 3502 |
+ session->common_name); |
|
| 3503 |
+ |
|
| 3504 |
+ /* disable the tunnel */ |
|
| 3505 |
+ tls_deauthenticate (multi); |
|
| 3506 |
+ } |
|
| 3507 |
+ } |
|
| 3508 |
+ |
|
| 3495 | 3509 |
/* verify --client-config-dir based authentication */ |
| 3496 | 3510 |
if (ks->authenticated && session->opt->client_config_dir_exclusive) |
| 3497 | 3511 |
{
|
| ... | ... |
@@ -303,6 +303,21 @@ |
| 303 | 303 |
/* #define MEASURE_TLS_HANDSHAKE_STATS */ |
| 304 | 304 |
|
| 305 | 305 |
/* |
| 306 |
+ * Keep track of certificate hashes at various depths |
|
| 307 |
+ */ |
|
| 308 |
+ |
|
| 309 |
+/* Maximum certificate depth we will allow */ |
|
| 310 |
+#define MAX_CERT_DEPTH 8 |
|
| 311 |
+ |
|
| 312 |
+struct cert_hash {
|
|
| 313 |
+ unsigned char sha1_hash[SHA_DIGEST_LENGTH]; |
|
| 314 |
+}; |
|
| 315 |
+ |
|
| 316 |
+struct cert_hash_set {
|
|
| 317 |
+ struct cert_hash *ch[MAX_CERT_DEPTH]; |
|
| 318 |
+}; |
|
| 319 |
+ |
|
| 320 |
+/* |
|
| 306 | 321 |
* Key material, used as source for PRF-based |
| 307 | 322 |
* key expansion. |
| 308 | 323 |
*/ |
| ... | ... |
@@ -518,6 +533,8 @@ struct tls_session |
| 518 | 518 |
|
| 519 | 519 |
char *common_name; |
| 520 | 520 |
|
| 521 |
+ struct cert_hash_set *cert_hash_set; |
|
| 522 |
+ |
|
| 521 | 523 |
#ifdef ENABLE_PF |
| 522 | 524 |
uint32_t common_name_hashval; |
| 523 | 525 |
#endif |
| ... | ... |
@@ -589,10 +606,11 @@ struct tls_multi |
| 589 | 589 |
int n_soft_errors; /* errors due to unrecognized or failed-to-authenticate incoming packets */ |
| 590 | 590 |
|
| 591 | 591 |
/* |
| 592 |
- * Our locked common name and username (cannot change during the life of this tls_multi object) |
|
| 592 |
+ * Our locked common name, username, and cert hashes (cannot change during the life of this tls_multi object) |
|
| 593 | 593 |
*/ |
| 594 | 594 |
char *locked_cn; |
| 595 | 595 |
char *locked_username; |
| 596 |
+ struct cert_hash_set *locked_cert_hash_set; |
|
| 596 | 597 |
|
| 597 | 598 |
#ifdef ENABLE_DEF_AUTH |
| 598 | 599 |
/* |
| ... | ... |
@@ -692,6 +710,7 @@ bool tls_rec_payload (struct tls_multi *multi, |
| 692 | 692 |
const char *tls_common_name (const struct tls_multi* multi, const bool null); |
| 693 | 693 |
void tls_set_common_name (struct tls_multi *multi, const char *common_name); |
| 694 | 694 |
void tls_lock_common_name (struct tls_multi *multi); |
| 695 |
+void tls_lock_cert_hash_set (struct tls_multi *multi); |
|
| 695 | 696 |
|
| 696 | 697 |
#define TLS_AUTHENTICATION_SUCCEEDED 0 |
| 697 | 698 |
#define TLS_AUTHENTICATION_FAILED 1 |