diff options
| author | Chong Yidong | 2011-10-27 16:07:28 +0800 |
|---|---|---|
| committer | Chong Yidong | 2011-10-27 16:07:28 +0800 |
| commit | 435c1d6793ce358f4d2c77c9e9c1ad81fd754651 (patch) | |
| tree | c4a4bf709d74290d4c59f8b1a152190c8d89d9c6 /src | |
| parent | 416a2c45b3068568e47076ed089db25830117ea8 (diff) | |
| download | emacs-435c1d6793ce358f4d2c77c9e9c1ad81fd754651.tar.gz emacs-435c1d6793ce358f4d2c77c9e9c1ad81fd754651.zip | |
More gnutls memory fixes.
* src/gnutls.c (emacs_gnutls_deinit): Deinit the gnutls_state if it is
non-NULL, regardless of GNUTLS_INITSTAGE.
(Fgnutls_boot): Cleanups. Call emacs_gnutls_deinit if we signal
an error. Set process slots as soon as we allocate them.
* src/gnutls.h (GNUTLS_LOG, GNUTLS_LOG2): Fix macros.
* src/process.c (make_process): Set gnutls_state to NULL.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/gnutls.c | 240 | ||||
| -rw-r--r-- | src/gnutls.h | 4 | ||||
| -rw-r--r-- | src/process.c | 1 |
4 files changed, 110 insertions, 146 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 65995d0ac92..c3926f6024b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,16 @@ | |||
| 1 | 2011-10-27 Chong Yidong <cyd@gnu.org> | 1 | 2011-10-27 Chong Yidong <cyd@gnu.org> |
| 2 | 2 | ||
| 3 | * process.c (make_process): Set gnutls_state to NULL. | ||
| 4 | |||
| 5 | * gnutls.c (emacs_gnutls_deinit): Deinit the gnutls_state if it is | ||
| 6 | non-NULL, regardless of GNUTLS_INITSTAGE. | ||
| 7 | (Fgnutls_boot): Cleanups. Call emacs_gnutls_deinit if we signal | ||
| 8 | an error. Set process slots as soon as we allocate them. | ||
| 9 | |||
| 10 | * gnutls.h (GNUTLS_LOG, GNUTLS_LOG2): Fix macros. | ||
| 11 | |||
| 12 | 2011-10-27 Chong Yidong <cyd@gnu.org> | ||
| 13 | |||
| 3 | * gnutls.c (emacs_gnutls_deinit): New function. Deallocate | 14 | * gnutls.c (emacs_gnutls_deinit): New function. Deallocate |
| 4 | credentials structures as well as calling gnutls_deinit. | 15 | credentials structures as well as calling gnutls_deinit. |
| 5 | (Fgnutls_deinit, Fgnutls_boot): Use it. | 16 | (Fgnutls_deinit, Fgnutls_boot): Use it. |
diff --git a/src/gnutls.c b/src/gnutls.c index f836692198c..500f09432b1 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -490,10 +490,12 @@ emacs_gnutls_deinit (Lisp_Object proc) | |||
| 490 | XPROCESS (proc)->gnutls_anon_cred = NULL; | 490 | XPROCESS (proc)->gnutls_anon_cred = NULL; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT) | 493 | if (XPROCESS (proc)->gnutls_state) |
| 494 | { | 494 | { |
| 495 | fn_gnutls_deinit (XPROCESS (proc)->gnutls_state); | 495 | fn_gnutls_deinit (XPROCESS (proc)->gnutls_state); |
| 496 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1; | 496 | XPROCESS (proc)->gnutls_state = NULL; |
| 497 | if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT) | ||
| 498 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1; | ||
| 497 | } | 499 | } |
| 498 | 500 | ||
| 499 | XPROCESS (proc)->gnutls_p = 0; | 501 | XPROCESS (proc)->gnutls_p = 0; |
| @@ -647,7 +649,7 @@ emacs_gnutls_global_deinit (void) | |||
| 647 | 649 | ||
| 648 | DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, | 650 | DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, |
| 649 | doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST. | 651 | doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST. |
| 650 | Currently only client mode is supported. Returns a success/failure | 652 | Currently only client mode is supported. Return a success/failure |
| 651 | value you can check with `gnutls-errorp'. | 653 | value you can check with `gnutls-errorp'. |
| 652 | 654 | ||
| 653 | TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'. | 655 | TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'. |
| @@ -698,23 +700,13 @@ one trustfile (usually a CA bundle). */) | |||
| 698 | (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist) | 700 | (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist) |
| 699 | { | 701 | { |
| 700 | int ret = GNUTLS_E_SUCCESS; | 702 | int ret = GNUTLS_E_SUCCESS; |
| 701 | |||
| 702 | int max_log_level = 0; | 703 | int max_log_level = 0; |
| 703 | 704 | ||
| 704 | /* TODO: GNUTLS_X509_FMT_DER is also an option. */ | ||
| 705 | int file_format = GNUTLS_X509_FMT_PEM; | ||
| 706 | |||
| 707 | unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; | ||
| 708 | gnutls_x509_crt_t gnutls_verify_cert; | ||
| 709 | unsigned int gnutls_verify_cert_list_size; | ||
| 710 | const gnutls_datum_t *gnutls_verify_cert_list; | ||
| 711 | |||
| 712 | gnutls_session_t state; | 705 | gnutls_session_t state; |
| 713 | gnutls_certificate_credentials_t x509_cred; | 706 | gnutls_certificate_credentials_t x509_cred = NULL; |
| 714 | gnutls_anon_client_credentials_t anon_cred; | 707 | gnutls_anon_client_credentials_t anon_cred = NULL; |
| 715 | Lisp_Object global_init; | 708 | Lisp_Object global_init; |
| 716 | char const *priority_string_ptr = "NORMAL"; /* default priority string. */ | 709 | char const *priority_string_ptr = "NORMAL"; /* default priority string. */ |
| 717 | Lisp_Object tail; | ||
| 718 | unsigned int peer_verification; | 710 | unsigned int peer_verification; |
| 719 | char* c_hostname; | 711 | char* c_hostname; |
| 720 | 712 | ||
| @@ -726,7 +718,6 @@ one trustfile (usually a CA bundle). */) | |||
| 726 | /* Lisp_Object callbacks; */ | 718 | /* Lisp_Object callbacks; */ |
| 727 | Lisp_Object loglevel; | 719 | Lisp_Object loglevel; |
| 728 | Lisp_Object hostname; | 720 | Lisp_Object hostname; |
| 729 | Lisp_Object verify_flags; | ||
| 730 | /* Lisp_Object verify_error; */ | 721 | /* Lisp_Object verify_error; */ |
| 731 | Lisp_Object verify_hostname_error; | 722 | Lisp_Object verify_hostname_error; |
| 732 | Lisp_Object prime_bits; | 723 | Lisp_Object prime_bits; |
| @@ -741,21 +732,23 @@ one trustfile (usually a CA bundle). */) | |||
| 741 | return gnutls_make_error (GNUTLS_EMACS_ERROR_NOT_LOADED); | 732 | return gnutls_make_error (GNUTLS_EMACS_ERROR_NOT_LOADED); |
| 742 | } | 733 | } |
| 743 | 734 | ||
| 735 | if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon)) | ||
| 736 | { | ||
| 737 | error ("Invalid GnuTLS credential type"); | ||
| 738 | return gnutls_make_error (GNUTLS_EMACS_ERROR_INVALID_TYPE); | ||
| 739 | } | ||
| 740 | |||
| 744 | hostname = Fplist_get (proplist, QCgnutls_bootprop_hostname); | 741 | hostname = Fplist_get (proplist, QCgnutls_bootprop_hostname); |
| 745 | priority_string = Fplist_get (proplist, QCgnutls_bootprop_priority); | 742 | priority_string = Fplist_get (proplist, QCgnutls_bootprop_priority); |
| 746 | trustfiles = Fplist_get (proplist, QCgnutls_bootprop_trustfiles); | 743 | trustfiles = Fplist_get (proplist, QCgnutls_bootprop_trustfiles); |
| 747 | keylist = Fplist_get (proplist, QCgnutls_bootprop_keylist); | 744 | keylist = Fplist_get (proplist, QCgnutls_bootprop_keylist); |
| 748 | crlfiles = Fplist_get (proplist, QCgnutls_bootprop_crlfiles); | 745 | crlfiles = Fplist_get (proplist, QCgnutls_bootprop_crlfiles); |
| 749 | /* callbacks = Fplist_get (proplist, QCgnutls_bootprop_callbacks); */ | ||
| 750 | loglevel = Fplist_get (proplist, QCgnutls_bootprop_loglevel); | 746 | loglevel = Fplist_get (proplist, QCgnutls_bootprop_loglevel); |
| 751 | verify_flags = Fplist_get (proplist, QCgnutls_bootprop_verify_flags); | ||
| 752 | /* verify_error = Fplist_get (proplist, QCgnutls_bootprop_verify_error); */ | ||
| 753 | verify_hostname_error = Fplist_get (proplist, QCgnutls_bootprop_verify_hostname_error); | 747 | verify_hostname_error = Fplist_get (proplist, QCgnutls_bootprop_verify_hostname_error); |
| 754 | prime_bits = Fplist_get (proplist, QCgnutls_bootprop_min_prime_bits); | 748 | prime_bits = Fplist_get (proplist, QCgnutls_bootprop_min_prime_bits); |
| 755 | 749 | ||
| 756 | if (!STRINGP (hostname)) | 750 | if (!STRINGP (hostname)) |
| 757 | error ("gnutls-boot: invalid :hostname parameter"); | 751 | error ("gnutls-boot: invalid :hostname parameter"); |
| 758 | |||
| 759 | c_hostname = SSDATA (hostname); | 752 | c_hostname = SSDATA (hostname); |
| 760 | 753 | ||
| 761 | if (NUMBERP (loglevel)) | 754 | if (NUMBERP (loglevel)) |
| @@ -777,53 +770,50 @@ one trustfile (usually a CA bundle). */) | |||
| 777 | 770 | ||
| 778 | /* Mark PROC as a GnuTLS process. */ | 771 | /* Mark PROC as a GnuTLS process. */ |
| 779 | XPROCESS (proc)->gnutls_p = 1; | 772 | XPROCESS (proc)->gnutls_p = 1; |
| 773 | XPROCESS (proc)->gnutls_state = NULL; | ||
| 780 | XPROCESS (proc)->gnutls_x509_cred = NULL; | 774 | XPROCESS (proc)->gnutls_x509_cred = NULL; |
| 781 | XPROCESS (proc)->gnutls_anon_cred = NULL; | 775 | XPROCESS (proc)->gnutls_anon_cred = NULL; |
| 776 | XPROCESS (proc)->gnutls_cred_type = type; | ||
| 782 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY; | 777 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY; |
| 783 | 778 | ||
| 784 | GNUTLS_LOG (1, max_log_level, "allocating credentials"); | 779 | GNUTLS_LOG (1, max_log_level, "allocating credentials"); |
| 785 | if (EQ (type, Qgnutls_x509pki)) | 780 | if (EQ (type, Qgnutls_x509pki)) |
| 786 | { | 781 | { |
| 782 | Lisp_Object verify_flags; | ||
| 783 | unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; | ||
| 784 | |||
| 787 | GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); | 785 | GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); |
| 788 | x509_cred = XPROCESS (proc)->gnutls_x509_cred; | ||
| 789 | fn_gnutls_certificate_allocate_credentials (&x509_cred); | 786 | fn_gnutls_certificate_allocate_credentials (&x509_cred); |
| 787 | XPROCESS (proc)->gnutls_x509_cred = x509_cred; | ||
| 790 | 788 | ||
| 789 | verify_flags = Fplist_get (proplist, QCgnutls_bootprop_verify_flags); | ||
| 791 | if (NUMBERP (verify_flags)) | 790 | if (NUMBERP (verify_flags)) |
| 792 | { | 791 | { |
| 793 | gnutls_verify_flags = XINT (verify_flags); | 792 | gnutls_verify_flags = XINT (verify_flags); |
| 794 | GNUTLS_LOG (2, max_log_level, "setting verification flags"); | 793 | GNUTLS_LOG (2, max_log_level, "setting verification flags"); |
| 795 | } | 794 | } |
| 796 | else if (NILP (verify_flags)) | 795 | else if (NILP (verify_flags)) |
| 797 | { | 796 | GNUTLS_LOG (2, max_log_level, "using default verification flags"); |
| 798 | /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */ | ||
| 799 | GNUTLS_LOG (2, max_log_level, "using default verification flags"); | ||
| 800 | } | ||
| 801 | else | 797 | else |
| 802 | { | 798 | GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags"); |
| 803 | /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */ | 799 | |
| 804 | GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags"); | ||
| 805 | } | ||
| 806 | fn_gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags); | 800 | fn_gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags); |
| 807 | } | 801 | } |
| 808 | else if (EQ (type, Qgnutls_anon)) | 802 | else /* Qgnutls_anon: */ |
| 809 | { | 803 | { |
| 810 | GNUTLS_LOG (2, max_log_level, "allocating anon credentials"); | 804 | GNUTLS_LOG (2, max_log_level, "allocating anon credentials"); |
| 811 | anon_cred = XPROCESS (proc)->gnutls_anon_cred; | ||
| 812 | fn_gnutls_anon_allocate_client_credentials (&anon_cred); | 805 | fn_gnutls_anon_allocate_client_credentials (&anon_cred); |
| 813 | } | 806 | XPROCESS (proc)->gnutls_anon_cred = anon_cred; |
| 814 | else | ||
| 815 | { | ||
| 816 | error ("unknown credential type"); | ||
| 817 | ret = GNUTLS_EMACS_ERROR_INVALID_TYPE; | ||
| 818 | } | 807 | } |
| 819 | 808 | ||
| 820 | if (ret < GNUTLS_E_SUCCESS) | ||
| 821 | return gnutls_make_error (ret); | ||
| 822 | |||
| 823 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC; | 809 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC; |
| 824 | 810 | ||
| 825 | if (EQ (type, Qgnutls_x509pki)) | 811 | if (EQ (type, Qgnutls_x509pki)) |
| 826 | { | 812 | { |
| 813 | /* TODO: GNUTLS_X509_FMT_DER is also an option. */ | ||
| 814 | int file_format = GNUTLS_X509_FMT_PEM; | ||
| 815 | Lisp_Object tail; | ||
| 816 | |||
| 827 | for (tail = trustfiles; !NILP (tail); tail = Fcdr (tail)) | 817 | for (tail = trustfiles; !NILP (tail); tail = Fcdr (tail)) |
| 828 | { | 818 | { |
| 829 | Lisp_Object trustfile = Fcar (tail); | 819 | Lisp_Object trustfile = Fcar (tail); |
| @@ -841,8 +831,8 @@ one trustfile (usually a CA bundle). */) | |||
| 841 | } | 831 | } |
| 842 | else | 832 | else |
| 843 | { | 833 | { |
| 844 | error ("Sorry, GnuTLS can't use non-string trustfile %s", | 834 | emacs_gnutls_deinit (proc); |
| 845 | SDATA (trustfile)); | 835 | error ("Invalid trustfile"); |
| 846 | } | 836 | } |
| 847 | } | 837 | } |
| 848 | 838 | ||
| @@ -854,17 +844,15 @@ one trustfile (usually a CA bundle). */) | |||
| 854 | GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ", | 844 | GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ", |
| 855 | SSDATA (crlfile)); | 845 | SSDATA (crlfile)); |
| 856 | ret = fn_gnutls_certificate_set_x509_crl_file | 846 | ret = fn_gnutls_certificate_set_x509_crl_file |
| 857 | (x509_cred, | 847 | (x509_cred, SSDATA (crlfile), file_format); |
| 858 | SSDATA (crlfile), | ||
| 859 | file_format); | ||
| 860 | 848 | ||
| 861 | if (ret < GNUTLS_E_SUCCESS) | 849 | if (ret < GNUTLS_E_SUCCESS) |
| 862 | return gnutls_make_error (ret); | 850 | return gnutls_make_error (ret); |
| 863 | } | 851 | } |
| 864 | else | 852 | else |
| 865 | { | 853 | { |
| 866 | error ("Sorry, GnuTLS can't use non-string CRL file %s", | 854 | emacs_gnutls_deinit (proc); |
| 867 | SDATA (crlfile)); | 855 | error ("Invalid CRL file"); |
| 868 | } | 856 | } |
| 869 | } | 857 | } |
| 870 | 858 | ||
| @@ -879,45 +867,31 @@ one trustfile (usually a CA bundle). */) | |||
| 879 | GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ", | 867 | GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ", |
| 880 | SSDATA (certfile)); | 868 | SSDATA (certfile)); |
| 881 | ret = fn_gnutls_certificate_set_x509_key_file | 869 | ret = fn_gnutls_certificate_set_x509_key_file |
| 882 | (x509_cred, | 870 | (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format); |
| 883 | SSDATA (certfile), | ||
| 884 | SSDATA (keyfile), | ||
| 885 | file_format); | ||
| 886 | 871 | ||
| 887 | if (ret < GNUTLS_E_SUCCESS) | 872 | if (ret < GNUTLS_E_SUCCESS) |
| 888 | return gnutls_make_error (ret); | 873 | return gnutls_make_error (ret); |
| 889 | } | 874 | } |
| 890 | else | 875 | else |
| 891 | { | 876 | { |
| 892 | if (STRINGP (keyfile)) | 877 | emacs_gnutls_deinit (proc); |
| 893 | error ("Sorry, GnuTLS can't use non-string client cert file %s", | 878 | error (STRINGP (keyfile) ? "Invalid client cert file" |
| 894 | SDATA (certfile)); | 879 | : "Invalid client key file"); |
| 895 | else | ||
| 896 | error ("Sorry, GnuTLS can't use non-string client key file %s", | ||
| 897 | SDATA (keyfile)); | ||
| 898 | } | 880 | } |
| 899 | } | 881 | } |
| 900 | } | 882 | } |
| 901 | 883 | ||
| 902 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES; | 884 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES; |
| 903 | |||
| 904 | GNUTLS_LOG (1, max_log_level, "gnutls callbacks"); | 885 | GNUTLS_LOG (1, max_log_level, "gnutls callbacks"); |
| 905 | |||
| 906 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS; | 886 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS; |
| 907 | 887 | ||
| 908 | #ifdef HAVE_GNUTLS_CALLBACK_CERTIFICATE_VERIFY | 888 | /* Call gnutls_init here: */ |
| 909 | #else | ||
| 910 | #endif | ||
| 911 | 889 | ||
| 912 | GNUTLS_LOG (1, max_log_level, "gnutls_init"); | 890 | GNUTLS_LOG (1, max_log_level, "gnutls_init"); |
| 913 | |||
| 914 | ret = fn_gnutls_init (&state, GNUTLS_CLIENT); | 891 | ret = fn_gnutls_init (&state, GNUTLS_CLIENT); |
| 915 | 892 | XPROCESS (proc)->gnutls_state = state; | |
| 916 | if (ret < GNUTLS_E_SUCCESS) | 893 | if (ret < GNUTLS_E_SUCCESS) |
| 917 | return gnutls_make_error (ret); | 894 | return gnutls_make_error (ret); |
| 918 | |||
| 919 | XPROCESS (proc)->gnutls_state = state; | ||
| 920 | |||
| 921 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT; | 895 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT; |
| 922 | 896 | ||
| 923 | if (STRINGP (priority_string)) | 897 | if (STRINGP (priority_string)) |
| @@ -933,46 +907,25 @@ one trustfile (usually a CA bundle). */) | |||
| 933 | } | 907 | } |
| 934 | 908 | ||
| 935 | GNUTLS_LOG (1, max_log_level, "setting the priority string"); | 909 | GNUTLS_LOG (1, max_log_level, "setting the priority string"); |
| 936 | |||
| 937 | ret = fn_gnutls_priority_set_direct (state, | 910 | ret = fn_gnutls_priority_set_direct (state, |
| 938 | priority_string_ptr, | 911 | priority_string_ptr, |
| 939 | NULL); | 912 | NULL); |
| 940 | |||
| 941 | if (ret < GNUTLS_E_SUCCESS) | 913 | if (ret < GNUTLS_E_SUCCESS) |
| 942 | return gnutls_make_error (ret); | 914 | return gnutls_make_error (ret); |
| 943 | 915 | ||
| 944 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY; | 916 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY; |
| 945 | 917 | ||
| 946 | if (!EQ (prime_bits, Qnil)) | 918 | if (INTEGERP (prime_bits)) |
| 947 | { | 919 | fn_gnutls_dh_set_prime_bits (state, XUINT (prime_bits)); |
| 948 | fn_gnutls_dh_set_prime_bits (state, XUINT (prime_bits)); | ||
| 949 | } | ||
| 950 | |||
| 951 | if (EQ (type, Qgnutls_x509pki)) | ||
| 952 | { | ||
| 953 | ret = fn_gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred); | ||
| 954 | } | ||
| 955 | else if (EQ (type, Qgnutls_anon)) | ||
| 956 | { | ||
| 957 | ret = fn_gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred); | ||
| 958 | } | ||
| 959 | else | ||
| 960 | { | ||
| 961 | error ("unknown credential type"); | ||
| 962 | ret = GNUTLS_EMACS_ERROR_INVALID_TYPE; | ||
| 963 | } | ||
| 964 | 920 | ||
| 921 | ret = EQ (type, Qgnutls_x509pki) | ||
| 922 | ? fn_gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred) | ||
| 923 | : fn_gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred); | ||
| 965 | if (ret < GNUTLS_E_SUCCESS) | 924 | if (ret < GNUTLS_E_SUCCESS) |
| 966 | return gnutls_make_error (ret); | 925 | return gnutls_make_error (ret); |
| 967 | 926 | ||
| 968 | XPROCESS (proc)->gnutls_anon_cred = anon_cred; | ||
| 969 | XPROCESS (proc)->gnutls_x509_cred = x509_cred; | ||
| 970 | XPROCESS (proc)->gnutls_cred_type = type; | ||
| 971 | |||
| 972 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET; | 927 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET; |
| 973 | |||
| 974 | ret = emacs_gnutls_handshake (XPROCESS (proc)); | 928 | ret = emacs_gnutls_handshake (XPROCESS (proc)); |
| 975 | |||
| 976 | if (ret < GNUTLS_E_SUCCESS) | 929 | if (ret < GNUTLS_E_SUCCESS) |
| 977 | return gnutls_make_error (ret); | 930 | return gnutls_make_error (ret); |
| 978 | 931 | ||
| @@ -983,69 +936,71 @@ one trustfile (usually a CA bundle). */) | |||
| 983 | gnutls_x509_crt_check_hostname() against :hostname. */ | 936 | gnutls_x509_crt_check_hostname() against :hostname. */ |
| 984 | 937 | ||
| 985 | ret = fn_gnutls_certificate_verify_peers2 (state, &peer_verification); | 938 | ret = fn_gnutls_certificate_verify_peers2 (state, &peer_verification); |
| 986 | |||
| 987 | if (ret < GNUTLS_E_SUCCESS) | 939 | if (ret < GNUTLS_E_SUCCESS) |
| 988 | return gnutls_make_error (ret); | 940 | return gnutls_make_error (ret); |
| 989 | 941 | ||
| 990 | if (XINT (loglevel) > 0 && peer_verification & GNUTLS_CERT_INVALID) | 942 | if (XINT (loglevel) > 0 && peer_verification & GNUTLS_CERT_INVALID) |
| 991 | message ("%s certificate could not be verified.", | 943 | message ("%s certificate could not be verified.", c_hostname); |
| 992 | c_hostname); | 944 | |
| 993 | 945 | if (peer_verification & GNUTLS_CERT_REVOKED) | |
| 994 | if (peer_verification & GNUTLS_CERT_REVOKED) | 946 | GNUTLS_LOG2 (1, max_log_level, "certificate was revoked (CRL):", |
| 995 | GNUTLS_LOG2 (1, max_log_level, "certificate was revoked (CRL):", | 947 | c_hostname); |
| 996 | c_hostname); | 948 | |
| 997 | 949 | if (peer_verification & GNUTLS_CERT_SIGNER_NOT_FOUND) | |
| 998 | if (peer_verification & GNUTLS_CERT_SIGNER_NOT_FOUND) | 950 | GNUTLS_LOG2 (1, max_log_level, "certificate signer was not found:", |
| 999 | GNUTLS_LOG2 (1, max_log_level, "certificate signer was not found:", | 951 | c_hostname); |
| 1000 | c_hostname); | 952 | |
| 1001 | 953 | if (peer_verification & GNUTLS_CERT_SIGNER_NOT_CA) | |
| 1002 | if (peer_verification & GNUTLS_CERT_SIGNER_NOT_CA) | 954 | GNUTLS_LOG2 (1, max_log_level, "certificate signer is not a CA:", |
| 1003 | GNUTLS_LOG2 (1, max_log_level, "certificate signer is not a CA:", | 955 | c_hostname); |
| 1004 | c_hostname); | 956 | |
| 1005 | 957 | if (peer_verification & GNUTLS_CERT_INSECURE_ALGORITHM) | |
| 1006 | if (peer_verification & GNUTLS_CERT_INSECURE_ALGORITHM) | 958 | GNUTLS_LOG2 (1, max_log_level, |
| 1007 | GNUTLS_LOG2 (1, max_log_level, | 959 | "certificate was signed with an insecure algorithm:", |
| 1008 | "certificate was signed with an insecure algorithm:", | 960 | c_hostname); |
| 1009 | c_hostname); | 961 | |
| 1010 | 962 | if (peer_verification & GNUTLS_CERT_NOT_ACTIVATED) | |
| 1011 | if (peer_verification & GNUTLS_CERT_NOT_ACTIVATED) | 963 | GNUTLS_LOG2 (1, max_log_level, "certificate is not yet activated:", |
| 1012 | GNUTLS_LOG2 (1, max_log_level, "certificate is not yet activated:", | 964 | c_hostname); |
| 1013 | c_hostname); | 965 | |
| 1014 | 966 | if (peer_verification & GNUTLS_CERT_EXPIRED) | |
| 1015 | if (peer_verification & GNUTLS_CERT_EXPIRED) | 967 | GNUTLS_LOG2 (1, max_log_level, "certificate has expired:", |
| 1016 | GNUTLS_LOG2 (1, max_log_level, "certificate has expired:", | 968 | c_hostname); |
| 1017 | c_hostname); | 969 | |
| 1018 | 970 | if (peer_verification != 0) | |
| 1019 | if (peer_verification != 0) | 971 | { |
| 1020 | { | 972 | if (NILP (verify_hostname_error)) |
| 1021 | if (NILP (verify_hostname_error)) | 973 | GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:", |
| 1022 | { | 974 | c_hostname); |
| 1023 | GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:", | 975 | else |
| 1024 | c_hostname); | 976 | { |
| 1025 | } | 977 | emacs_gnutls_deinit (proc); |
| 1026 | else | 978 | error ("Certificate validation failed %s, verification code %d", |
| 1027 | { | 979 | c_hostname, peer_verification); |
| 1028 | error ("Certificate validation failed %s, verification code %d", | 980 | } |
| 1029 | c_hostname, peer_verification); | 981 | } |
| 1030 | } | ||
| 1031 | } | ||
| 1032 | 982 | ||
| 1033 | /* Up to here the process is the same for X.509 certificates and | 983 | /* Up to here the process is the same for X.509 certificates and |
| 1034 | OpenPGP keys. From now on X.509 certificates are assumed. This | 984 | OpenPGP keys. From now on X.509 certificates are assumed. This |
| 1035 | can be easily extended to work with openpgp keys as well. */ | 985 | can be easily extended to work with openpgp keys as well. */ |
| 1036 | if (fn_gnutls_certificate_type_get (state) == GNUTLS_CRT_X509) | 986 | if (fn_gnutls_certificate_type_get (state) == GNUTLS_CRT_X509) |
| 1037 | { | 987 | { |
| 1038 | ret = fn_gnutls_x509_crt_init (&gnutls_verify_cert); | 988 | gnutls_x509_crt_t gnutls_verify_cert; |
| 989 | const gnutls_datum_t *gnutls_verify_cert_list; | ||
| 990 | unsigned int gnutls_verify_cert_list_size; | ||
| 1039 | 991 | ||
| 992 | ret = fn_gnutls_x509_crt_init (&gnutls_verify_cert); | ||
| 1040 | if (ret < GNUTLS_E_SUCCESS) | 993 | if (ret < GNUTLS_E_SUCCESS) |
| 1041 | return gnutls_make_error (ret); | 994 | return gnutls_make_error (ret); |
| 1042 | 995 | ||
| 1043 | gnutls_verify_cert_list = | 996 | gnutls_verify_cert_list = |
| 1044 | fn_gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size); | 997 | fn_gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size); |
| 1045 | 998 | ||
| 1046 | if (NULL == gnutls_verify_cert_list) | 999 | if (gnutls_verify_cert_list == NULL) |
| 1047 | { | 1000 | { |
| 1048 | error ("No x509 certificate was found!\n"); | 1001 | fn_gnutls_x509_crt_deinit (gnutls_verify_cert); |
| 1002 | emacs_gnutls_deinit (proc); | ||
| 1003 | error ("No x509 certificate was found\n"); | ||
| 1049 | } | 1004 | } |
| 1050 | 1005 | ||
| 1051 | /* We only check the first certificate in the given chain. */ | 1006 | /* We only check the first certificate in the given chain. */ |
| @@ -1062,18 +1017,15 @@ one trustfile (usually a CA bundle). */) | |||
| 1062 | if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname)) | 1017 | if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname)) |
| 1063 | { | 1018 | { |
| 1064 | if (NILP (verify_hostname_error)) | 1019 | if (NILP (verify_hostname_error)) |
| 1065 | { | 1020 | GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:", |
| 1066 | GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:", | 1021 | c_hostname); |
| 1067 | c_hostname); | ||
| 1068 | } | ||
| 1069 | else | 1022 | else |
| 1070 | { | 1023 | { |
| 1071 | fn_gnutls_x509_crt_deinit (gnutls_verify_cert); | 1024 | fn_gnutls_x509_crt_deinit (gnutls_verify_cert); |
| 1072 | error ("The x509 certificate does not match \"%s\"", | 1025 | emacs_gnutls_deinit (proc); |
| 1073 | c_hostname); | 1026 | error ("The x509 certificate does not match \"%s\"", c_hostname); |
| 1074 | } | 1027 | } |
| 1075 | } | 1028 | } |
| 1076 | |||
| 1077 | fn_gnutls_x509_crt_deinit (gnutls_verify_cert); | 1029 | fn_gnutls_x509_crt_deinit (gnutls_verify_cert); |
| 1078 | } | 1030 | } |
| 1079 | 1031 | ||
diff --git a/src/gnutls.h b/src/gnutls.h index 5ec6fb76c01..076e9fdba9c 100644 --- a/src/gnutls.h +++ b/src/gnutls.h | |||
| @@ -49,9 +49,9 @@ typedef enum | |||
| 49 | 49 | ||
| 50 | #define GNUTLS_PROCESS_USABLE(proc) (GNUTLS_INITSTAGE(proc) >= GNUTLS_STAGE_READY) | 50 | #define GNUTLS_PROCESS_USABLE(proc) (GNUTLS_INITSTAGE(proc) >= GNUTLS_STAGE_READY) |
| 51 | 51 | ||
| 52 | #define GNUTLS_LOG(level, max, string) if (level <= max) { gnutls_log_function (level, "(Emacs) " string); } | 52 | #define GNUTLS_LOG(level, max, string) do { if (level <= max) { gnutls_log_function (level, "(Emacs) " string); } } while (0) |
| 53 | 53 | ||
| 54 | #define GNUTLS_LOG2(level, max, string, extra) if (level <= max) { gnutls_log_function2 (level, "(Emacs) " string, extra); } | 54 | #define GNUTLS_LOG2(level, max, string, extra) do { if (level <= max) { gnutls_log_function2 (level, "(Emacs) " string, extra); } } while (0) |
| 55 | 55 | ||
| 56 | extern EMACS_INT | 56 | extern EMACS_INT |
| 57 | emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, EMACS_INT nbyte); | 57 | emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, EMACS_INT nbyte); |
diff --git a/src/process.c b/src/process.c index 3daa55b259e..dc37ec5f961 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -642,6 +642,7 @@ make_process (Lisp_Object name) | |||
| 642 | p->gnutls_initstage = GNUTLS_STAGE_EMPTY; | 642 | p->gnutls_initstage = GNUTLS_STAGE_EMPTY; |
| 643 | p->gnutls_log_level = 0; | 643 | p->gnutls_log_level = 0; |
| 644 | p->gnutls_p = 0; | 644 | p->gnutls_p = 0; |
| 645 | p->gnutls_state = NULL; | ||
| 645 | p->gnutls_x509_cred = NULL; | 646 | p->gnutls_x509_cred = NULL; |
| 646 | p->gnutls_anon_cred = NULL; | 647 | p->gnutls_anon_cred = NULL; |
| 647 | #endif | 648 | #endif |