diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-03-10 21:32:05 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-03-10 21:32:05 +0100 |
commit | eac1312f563a3db362e189c8b2c915d666110dca (patch) | |
tree | 7097bc7fc3a91a1cfa497efbd8c40e611943e87e /src/namestore/plugin_gtk_namestore_tlsa.c | |
parent | d439a97be0eaf8bc005f2ce60d744e62d3920a93 (diff) | |
download | gnunet-gtk-eac1312f563a3db362e189c8b2c915d666110dca.tar.gz gnunet-gtk-eac1312f563a3db362e189c8b2c915d666110dca.zip |
be precise about which cert from the chain to use for TLSA record
Diffstat (limited to 'src/namestore/plugin_gtk_namestore_tlsa.c')
-rw-r--r-- | src/namestore/plugin_gtk_namestore_tlsa.c | 157 |
1 files changed, 113 insertions, 44 deletions
diff --git a/src/namestore/plugin_gtk_namestore_tlsa.c b/src/namestore/plugin_gtk_namestore_tlsa.c index 2a8ba21a..1fc970e4 100644 --- a/src/namestore/plugin_gtk_namestore_tlsa.c +++ b/src/namestore/plugin_gtk_namestore_tlsa.c | |||
@@ -567,20 +567,55 @@ tlsa_validate (void *cls, | |||
567 | 567 | ||
568 | 568 | ||
569 | /** | 569 | /** |
570 | * Context for TLS certificate import from network. | ||
571 | */ | ||
572 | struct ImportContext | ||
573 | { | ||
574 | |||
575 | /** | ||
576 | * Network handle for the session. | ||
577 | */ | ||
578 | struct GNUNET_NETWORK_Handle *sock; | ||
579 | |||
580 | /** | ||
581 | * DNS resolution request to resolve the domain name. | ||
582 | */ | ||
583 | struct GNUNET_RESOLVER_RequestHandle *rh; | ||
584 | |||
585 | /** | ||
586 | * Builder for accessing widgets. | ||
587 | */ | ||
588 | GtkBuilder *builder; | ||
589 | |||
590 | /** | ||
591 | * Domain name of the site we use to get the TLS cert record from. | ||
592 | */ | ||
593 | char *name; | ||
594 | |||
595 | /** | ||
596 | * We succeeded with our TLS handshake, ignore further DNS replies. | ||
597 | */ | ||
598 | int done; | ||
599 | }; | ||
600 | |||
601 | |||
602 | /** | ||
570 | * We have successfully established a TLS session to | 603 | * We have successfully established a TLS session to |
571 | * import a certificate from the server. Import the | 604 | * import a certificate from the server. Import the |
572 | * X509 certificate into the GUI. | 605 | * X509 certificate into the GUI. |
573 | * | 606 | * |
574 | * @param session TLS session to import from | 607 | * @param session TLS session to import from |
575 | * @param builder GTK builder to update GUI | 608 | * @param ic the import context |
576 | */ | 609 | */ |
577 | static void | 610 | static void |
578 | import_x509_certificate (gnutls_session_t session, | 611 | import_x509_certificate (gnutls_session_t session, |
579 | GtkBuilder *builder) | 612 | struct ImportContext *ic) |
580 | { | 613 | { |
614 | GtkBuilder *builder = ic->builder; | ||
581 | const gnutls_datum_t *cert_list; | 615 | const gnutls_datum_t *cert_list; |
582 | unsigned int cert_list_size = 0; | 616 | unsigned int cert_list_size = 0; |
583 | gnutls_x509_crt_t cert; | 617 | gnutls_x509_crt_t cert; |
618 | unsigned int usage; | ||
584 | unsigned int matching_type; | 619 | unsigned int matching_type; |
585 | unsigned int selector; | 620 | unsigned int selector; |
586 | gnutls_pubkey_t pk; | 621 | gnutls_pubkey_t pk; |
@@ -592,6 +627,7 @@ import_x509_certificate (gnutls_session_t session, | |||
592 | uint8_t sha512[512/8]; | 627 | uint8_t sha512[512/8]; |
593 | size_t ssize; | 628 | size_t ssize; |
594 | GtkTextBuffer *tb; | 629 | GtkTextBuffer *tb; |
630 | unsigned int i; | ||
595 | 631 | ||
596 | cert_list = gnutls_certificate_get_peers (session, | 632 | cert_list = gnutls_certificate_get_peers (session, |
597 | &cert_list_size); | 633 | &cert_list_size); |
@@ -602,17 +638,82 @@ import_x509_certificate (gnutls_session_t session, | |||
602 | GNUNET_break (0); | 638 | GNUNET_break (0); |
603 | return; | 639 | return; |
604 | } | 640 | } |
605 | /* we only import the first certificate. */ | 641 | |
606 | gnutls_x509_crt_init (&cert); | 642 | usage = get_selected_radio_value (builder, |
607 | if (GNUTLS_E_SUCCESS != | 643 | usage_buttons); |
608 | gnutls_x509_crt_import (cert, | 644 | /* Find out which certificate we care about based on usage */ |
609 | &cert_list[0], | 645 | for (i=0;i<cert_list_size;i++) |
610 | GNUTLS_X509_FMT_DER)) | ||
611 | { | 646 | { |
612 | GNUNET_break (0); | 647 | char san[256]; |
648 | size_t san_size = sizeof (san); | ||
649 | unsigned int critical; | ||
650 | int matches_dn; | ||
651 | gnutls_x509_dn_t dn; | ||
652 | gnutls_datum_t str; | ||
653 | |||
654 | gnutls_x509_crt_init (&cert); | ||
655 | if (GNUTLS_E_SUCCESS != | ||
656 | gnutls_x509_crt_import (cert, | ||
657 | &cert_list[i], | ||
658 | GNUTLS_X509_FMT_DER)) | ||
659 | { | ||
660 | GNUNET_break (0); | ||
661 | gnutls_x509_crt_deinit (cert); | ||
662 | return; | ||
663 | } | ||
664 | if (1 == usage) | ||
665 | break; /* RFC 6394: first certificate (i==0) is to be pinned */ | ||
666 | matches_dn = GNUNET_NO; | ||
667 | if ( (0 == gnutls_x509_crt_get_subject (cert, | ||
668 | &dn)) && | ||
669 | (0 == gnutls_x509_dn_get_str (dn, | ||
670 | &str)) ) | ||
671 | { | ||
672 | const char *cn; | ||
673 | |||
674 | cn = memmem (str.data, | ||
675 | str.size, | ||
676 | ",CN=", | ||
677 | 4); | ||
678 | if ( (NULL != cn) && | ||
679 | ( ('\0' == cn[4 + strlen (ic->name)]) || | ||
680 | (',' == cn[4 + strlen (ic->name)]) ) && | ||
681 | (0 == strncasecmp (cn + 4, | ||
682 | ic->name, | ||
683 | strlen (ic->name))) ) | ||
684 | matches_dn = GNUNET_YES; | ||
685 | } | ||
686 | for (unsigned int seq=0; | ||
687 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE != gnutls_x509_crt_get_subject_alt_name (cert, | ||
688 | seq, | ||
689 | san, | ||
690 | &san_size, | ||
691 | &critical); | ||
692 | seq++) | ||
693 | { | ||
694 | if (0 == strcasecmp (san, | ||
695 | ic->name)) | ||
696 | { | ||
697 | matches_dn = GNUNET_YES; | ||
698 | break; | ||
699 | } | ||
700 | } | ||
701 | /* usage = 3: we want to match DN, otherwise we do NOT want to | ||
702 | match DN */ | ||
703 | if ( (GNUNET_NO == matches_dn) ^ /* XOR */ | ||
704 | (3 == usage) /* Domain issued certificate */ ) | ||
705 | break; | ||
613 | gnutls_x509_crt_deinit (cert); | 706 | gnutls_x509_crt_deinit (cert); |
707 | } | ||
708 | if (i == cert_list_size) | ||
709 | { | ||
710 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
711 | "None of the %u certificates matches the usage %u\n", | ||
712 | cert_list_size, | ||
713 | usage); | ||
614 | return; | 714 | return; |
615 | } | 715 | } |
716 | |||
616 | selector = get_selected_radio_value (builder, | 717 | selector = get_selected_radio_value (builder, |
617 | selector_buttons); | 718 | selector_buttons); |
618 | switch (selector) | 719 | switch (selector) |
@@ -720,39 +821,6 @@ import_x509_certificate (gnutls_session_t session, | |||
720 | 821 | ||
721 | 822 | ||
722 | /** | 823 | /** |
723 | * Context for TLS certificate import from network. | ||
724 | */ | ||
725 | struct ImportContext | ||
726 | { | ||
727 | |||
728 | /** | ||
729 | * Network handle for the session. | ||
730 | */ | ||
731 | struct GNUNET_NETWORK_Handle *sock; | ||
732 | |||
733 | /** | ||
734 | * DNS resolution request to resolve the domain name. | ||
735 | */ | ||
736 | struct GNUNET_RESOLVER_RequestHandle *rh; | ||
737 | |||
738 | /** | ||
739 | * Builder for accessing widgets. | ||
740 | */ | ||
741 | GtkBuilder *builder; | ||
742 | |||
743 | /** | ||
744 | * Domain name of the site we use to get the TLS cert record from. | ||
745 | */ | ||
746 | char *name; | ||
747 | |||
748 | /** | ||
749 | * We succeeded with our TLS handshake, ignore further DNS replies. | ||
750 | */ | ||
751 | int done; | ||
752 | }; | ||
753 | |||
754 | |||
755 | /** | ||
756 | * We got an address from DNS, start TLS handshake. | 824 | * We got an address from DNS, start TLS handshake. |
757 | * | 825 | * |
758 | * @param cls our `struct ImportContext` | 826 | * @param cls our `struct ImportContext` |
@@ -837,7 +905,8 @@ import_address_cb (void *cls, | |||
837 | 905 | ||
838 | /* initialize TLS session */ | 906 | /* initialize TLS session */ |
839 | gnutls_init (&session, GNUTLS_CLIENT); | 907 | gnutls_init (&session, GNUTLS_CLIENT); |
840 | gnutls_session_set_ptr (session, ic); | 908 | gnutls_session_set_ptr (session, |
909 | ic); | ||
841 | gnutls_server_name_set (session, | 910 | gnutls_server_name_set (session, |
842 | GNUTLS_NAME_DNS, | 911 | GNUTLS_NAME_DNS, |
843 | ic->name, | 912 | ic->name, |
@@ -886,7 +955,7 @@ import_address_cb (void *cls, | |||
886 | break; | 955 | break; |
887 | case GNUTLS_CRT_X509: | 956 | case GNUTLS_CRT_X509: |
888 | import_x509_certificate (session, | 957 | import_x509_certificate (session, |
889 | ic->builder); | 958 | ic); |
890 | break; | 959 | break; |
891 | case GNUTLS_CRT_OPENPGP: | 960 | case GNUTLS_CRT_OPENPGP: |
892 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 961 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |