diff options
| author | Lars Magne Ingebrigtsen | 2014-11-23 14:52:04 +0100 |
|---|---|---|
| committer | Lars Magne Ingebrigtsen | 2014-11-23 14:52:04 +0100 |
| commit | a85950469e6fc045de6157f9ad739e28f30ecd8d (patch) | |
| tree | 99d4c9b37dd5b23db0112eaafe27f0f8ea1c89e1 /src | |
| parent | 0b1d7cd596b9784584812d1bde8aa2d376891cdb (diff) | |
| download | emacs-a85950469e6fc045de6157f9ad739e28f30ecd8d.tar.gz emacs-a85950469e6fc045de6157f9ad739e28f30ecd8d.zip | |
Add functions to gnutls.c for exporting certificate details
* gnutls.c (gnutls_hex_string, gnutls_certificate_details)
(Fgnutls_peer_status): New functions to export TLS certificate
details to Emacs Lisp.
* process.h: Added more fields to Lisp_Process to track
certificate details.
* gnutls.c (Fgnutls_boot): Save certificate for later inspection.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/gnutls.c | 351 | ||||
| -rw-r--r-- | src/process.h | 3 |
3 files changed, 364 insertions, 1 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b75b2f7f659..10ef4fab1c0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2014-11-23 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 2 | |||
| 3 | * gnutls.c (Fgnutls_boot): Save certificate for later inspection. | ||
| 4 | |||
| 5 | * process.h: Added more fields to Lisp_Process to track | ||
| 6 | certificate details. | ||
| 7 | |||
| 8 | * gnutls.c (gnutls_hex_string, gnutls_certificate_details) | ||
| 9 | (Fgnutls_peer_status): New functions to export TLS certificate | ||
| 10 | details to Emacs Lisp. | ||
| 11 | |||
| 1 | 2014-11-23 Jan Djärv <jan.h.d@swipnet.se> | 12 | 2014-11-23 Jan Djärv <jan.h.d@swipnet.se> |
| 2 | 13 | ||
| 3 | * gtkutil.c (gtk_adjustment_configure): Define for Gtk+ < 2.14. | 14 | * gtkutil.c (gtk_adjustment_configure): Define for Gtk+ < 2.14. |
diff --git a/src/gnutls.c b/src/gnutls.c index 5d48f78a6d4..37d797a4b43 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -18,6 +18,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 18 | 18 | ||
| 19 | #include <config.h> | 19 | #include <config.h> |
| 20 | #include <errno.h> | 20 | #include <errno.h> |
| 21 | #include <stdio.h> | ||
| 21 | 22 | ||
| 22 | #include "lisp.h" | 23 | #include "lisp.h" |
| 23 | #include "process.h" | 24 | #include "process.h" |
| @@ -61,6 +62,11 @@ static void gnutls_log_function2 (int, const char *, const char *); | |||
| 61 | static void gnutls_audit_log_function (gnutls_session_t, const char *); | 62 | static void gnutls_audit_log_function (gnutls_session_t, const char *); |
| 62 | #endif | 63 | #endif |
| 63 | 64 | ||
| 65 | static enum | ||
| 66 | { | ||
| 67 | CERTIFICATE_NOT_MATCHING = 2, | ||
| 68 | } extra_peer_verification_t; | ||
| 69 | |||
| 64 | 70 | ||
| 65 | #ifdef WINDOWSNT | 71 | #ifdef WINDOWSNT |
| 66 | 72 | ||
| @@ -146,6 +152,40 @@ DEF_GNUTLS_FN (int, gnutls_x509_crt_import, | |||
| 146 | (gnutls_x509_crt_t, const gnutls_datum_t *, | 152 | (gnutls_x509_crt_t, const gnutls_datum_t *, |
| 147 | gnutls_x509_crt_fmt_t)); | 153 | gnutls_x509_crt_fmt_t)); |
| 148 | DEF_GNUTLS_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *)); | 154 | DEF_GNUTLS_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *)); |
| 155 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_fingerprint, | ||
| 156 | (gnutls_digest_algorithm_t, | ||
| 157 | const gnutls_datum_t*, void *, size_t *)); | ||
| 158 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_version, | ||
| 159 | (gnutls_x509_crt_t)); | ||
| 160 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_serial, | ||
| 161 | (gnutls_x509_crt_t, void *, size_t *)); | ||
| 162 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_issuer_dn, | ||
| 163 | (gnutls_x509_crt_t, char *, size_t *)); | ||
| 164 | DEF_GNUTLS_FN (time_t, gnutls_x509_crt_get_activation_time, | ||
| 165 | (gnutls_x509_crt_t)); | ||
| 166 | DEF_GNUTLS_FN (time_t, gnutls_x509_crt_get_expiration_time, | ||
| 167 | (gnutls_x509_crt_t)); | ||
| 168 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_dn, | ||
| 169 | (gnutls_x509_crt_t, char *, size_t *)); | ||
| 170 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_pk_algorithm, | ||
| 171 | (gnutls_x509_crt_t, unsigned int *)); | ||
| 172 | DEF_GNUTLS_FN (int, gnutls_pk_algorithm_get_name, (gnutls_pk_algorithm_t)); | ||
| 173 | DEF_GNUTLS_FN (int, gnutls_pk_bits_to_sec_param, | ||
| 174 | (gnutls_pk_algorithm_t, unsigned int)); | ||
| 175 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_issuer_unique_id, | ||
| 176 | (gnutls_x509_crt_t, char *, size_t *)); | ||
| 177 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_subject_unique_id, | ||
| 178 | (gnutls_x509_crt_t, char *, size_t *)); | ||
| 179 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_signature_algorithm, | ||
| 180 | (gnutls_x509_crt_t)); | ||
| 181 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_signature, | ||
| 182 | (gnutls_x509_crt_t, char *, size_t *)); | ||
| 183 | DEF_GNUTLS_FN (int, gnutls_x509_crt_get_key_id, | ||
| 184 | (gnutls_x509_crt_t, unsigned int, | ||
| 185 | unsigned char *, size_t *_size)); | ||
| 186 | DEF_GNUTLS_FN (const char*, gnutls_sec_param_get_name, (gnutls_sec_param_t)); | ||
| 187 | DEF_GNUTLS_FN (const char*, gnutls_sign_algorithm_get_name, | ||
| 188 | (gnutls_sign_algorithm_t)); | ||
| 149 | 189 | ||
| 150 | static bool | 190 | static bool |
| 151 | init_gnutls_functions (void) | 191 | init_gnutls_functions (void) |
| @@ -205,6 +245,23 @@ init_gnutls_functions (void) | |||
| 205 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_deinit); | 245 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_deinit); |
| 206 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_import); | 246 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_import); |
| 207 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_init); | 247 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_init); |
| 248 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_fingerprint); | ||
| 249 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_version); | ||
| 250 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_serial); | ||
| 251 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_issuer_dn); | ||
| 252 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_activation_time); | ||
| 253 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_expiration_time); | ||
| 254 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_dn); | ||
| 255 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_pk_algorithm); | ||
| 256 | LOAD_GNUTLS_FN (library, gnutls_pk_algorithm_get_name); | ||
| 257 | LOAD_GNUTLS_FN (library, gnutls_pk_bits_to_sec_param); | ||
| 258 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_issuer_unique_id); | ||
| 259 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_subject_unique_id); | ||
| 260 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_signature_algorithm); | ||
| 261 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_signature); | ||
| 262 | LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_key_id); | ||
| 263 | LOAD_GNUTLS_FN (library, gnutls_sec_param_get_name); | ||
| 264 | LOAD_GNUTLS_FN (library, gnutls_sign_algorithm_get_name); | ||
| 208 | 265 | ||
| 209 | max_log_level = global_gnutls_log_level; | 266 | max_log_level = global_gnutls_log_level; |
| 210 | 267 | ||
| @@ -260,6 +317,23 @@ init_gnutls_functions (void) | |||
| 260 | #define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit | 317 | #define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit |
| 261 | #define fn_gnutls_x509_crt_import gnutls_x509_crt_import | 318 | #define fn_gnutls_x509_crt_import gnutls_x509_crt_import |
| 262 | #define fn_gnutls_x509_crt_init gnutls_x509_crt_init | 319 | #define fn_gnutls_x509_crt_init gnutls_x509_crt_init |
| 320 | #define fn_gnutls_x509_crt_get_fingerprint gnutls_x509_crt_get_fingerprint | ||
| 321 | #define fn_gnutls_x509_crt_get_version gnutls_x509_crt_get_version | ||
| 322 | #define fn_gnutls_x509_crt_get_serial gnutls_x509_crt_get_serial | ||
| 323 | #define fn_gnutls_x509_crt_get_issuer_dn gnutls_x509_crt_get_issuer_dn | ||
| 324 | #define fn_gnutls_x509_crt_get_activation_time gnutls_x509_crt_get_activation_time | ||
| 325 | #define fn_gnutls_x509_crt_get_expiration_time gnutls_x509_crt_get_expiration_time | ||
| 326 | #define fn_gnutls_x509_crt_get_dn gnutls_x509_crt_get_dn | ||
| 327 | #define fn_gnutls_x509_crt_get_pk_algorithm gnutls_x509_crt_get_pk_algorithm | ||
| 328 | #define fn_gnutls_pk_algorithm_get_name gnutls_pk_algorithm_get_name | ||
| 329 | #define fn_gnutls_pk_bits_to_sec_param gnutls_pk_bits_to_sec_param | ||
| 330 | #define fn_gnutls_x509_crt_get_issuer_unique_id gnutls_x509_crt_get_issuer_unique_id | ||
| 331 | #define fn_gnutls_x509_crt_get_subject_unique_id gnutls_x509_crt_get_subject_unique_id | ||
| 332 | #define fn_gnutls_x509_crt_get_signature_algorithm gnutls_x509_crt_get_signature_algorithm | ||
| 333 | #define fn_gnutls_x509_crt_get_signature gnutls_x509_crt_get_signature | ||
| 334 | #define fn_gnutls_x509_crt_get_key_id gnutls_x509_crt_get_key_id | ||
| 335 | #define fn_gnutls_sec_param_get_name gnutls_sec_param_get_name | ||
| 336 | #define fn_gnutls_sign_algorithm_get_name gnutls_sign_algorithm_get_name | ||
| 263 | 337 | ||
| 264 | #endif /* !WINDOWSNT */ | 338 | #endif /* !WINDOWSNT */ |
| 265 | 339 | ||
| @@ -693,6 +767,273 @@ DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0, | |||
| 693 | #endif | 767 | #endif |
| 694 | } | 768 | } |
| 695 | 769 | ||
| 770 | Lisp_Object | ||
| 771 | gnutls_hex_string (char *buf, size_t buf_size, char *prefix) { | ||
| 772 | size_t prefix_length = strlen (prefix); | ||
| 773 | char *string = malloc (buf_size * 3 + prefix_length); | ||
| 774 | Lisp_Object ret; | ||
| 775 | |||
| 776 | strcpy (string, prefix); | ||
| 777 | |||
| 778 | for (int i = 0; i < buf_size; i++) | ||
| 779 | sprintf (string + i * 3 + prefix_length, | ||
| 780 | i == buf_size - 1? "%02x": "%02x:", | ||
| 781 | ((unsigned char*)buf)[i]); | ||
| 782 | |||
| 783 | ret = build_string (string); | ||
| 784 | free (string); | ||
| 785 | return ret; | ||
| 786 | } | ||
| 787 | |||
| 788 | Lisp_Object | ||
| 789 | gnutls_certificate_details (gnutls_x509_crt_t cert) | ||
| 790 | { | ||
| 791 | Lisp_Object res = Qnil; | ||
| 792 | int err; | ||
| 793 | |||
| 794 | /* Version. */ | ||
| 795 | { | ||
| 796 | int version = fn_gnutls_x509_crt_get_version (cert); | ||
| 797 | if (version >= GNUTLS_E_SUCCESS) | ||
| 798 | res = nconc2 (res, list2 (intern (":version"), | ||
| 799 | make_number (version))); | ||
| 800 | } | ||
| 801 | |||
| 802 | /* Serial. */ | ||
| 803 | { | ||
| 804 | size_t serial_size = 0; | ||
| 805 | |||
| 806 | err = fn_gnutls_x509_crt_get_serial (cert, NULL, &serial_size); | ||
| 807 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 808 | char *serial = malloc (serial_size); | ||
| 809 | err = fn_gnutls_x509_crt_get_serial (cert, serial, &serial_size); | ||
| 810 | if (err >= GNUTLS_E_SUCCESS) { | ||
| 811 | res = nconc2 (res, list2 (intern (":serial-number"), | ||
| 812 | gnutls_hex_string (serial, serial_size, ""))); | ||
| 813 | } | ||
| 814 | free (serial); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | |||
| 818 | /* Issuer. */ | ||
| 819 | { | ||
| 820 | size_t dn_size = 0; | ||
| 821 | |||
| 822 | err = fn_gnutls_x509_crt_get_issuer_dn (cert, NULL, &dn_size); | ||
| 823 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 824 | char *dn = malloc (dn_size); | ||
| 825 | err = fn_gnutls_x509_crt_get_issuer_dn (cert, dn, &dn_size); | ||
| 826 | if (err >= GNUTLS_E_SUCCESS) | ||
| 827 | res = nconc2 (res, list2 (intern (":issuer"), | ||
| 828 | make_string (dn, dn_size))); | ||
| 829 | free (dn); | ||
| 830 | } | ||
| 831 | } | ||
| 832 | |||
| 833 | /* Validity. */ | ||
| 834 | { | ||
| 835 | char buf[11]; | ||
| 836 | size_t buf_size = sizeof (buf); | ||
| 837 | struct tm t; | ||
| 838 | time_t tim = fn_gnutls_x509_crt_get_activation_time (cert); | ||
| 839 | |||
| 840 | if (gmtime_r (&tim, &t) != NULL && | ||
| 841 | strftime (buf, buf_size, "%Y-%m-%d", &t) != 0) | ||
| 842 | res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf))); | ||
| 843 | |||
| 844 | tim = fn_gnutls_x509_crt_get_expiration_time (cert); | ||
| 845 | if (gmtime_r (&tim, &t) != NULL && | ||
| 846 | strftime (buf, buf_size, "%Y-%m-%d", &t) != 0) | ||
| 847 | res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf))); | ||
| 848 | } | ||
| 849 | |||
| 850 | /* Subject. */ | ||
| 851 | { | ||
| 852 | size_t dn_size = 0; | ||
| 853 | |||
| 854 | err = fn_gnutls_x509_crt_get_dn (cert, NULL, &dn_size); | ||
| 855 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 856 | char *dn = malloc (dn_size); | ||
| 857 | err = fn_gnutls_x509_crt_get_dn (cert, dn, &dn_size); | ||
| 858 | if (err >= GNUTLS_E_SUCCESS) | ||
| 859 | res = nconc2 (res, list2 (intern (":subject"), | ||
| 860 | make_string (dn, dn_size))); | ||
| 861 | free (dn); | ||
| 862 | } | ||
| 863 | } | ||
| 864 | |||
| 865 | /* SubjectPublicKeyInfo. */ | ||
| 866 | { | ||
| 867 | unsigned int bits; | ||
| 868 | |||
| 869 | err = fn_gnutls_x509_crt_get_pk_algorithm (cert, &bits); | ||
| 870 | if (err >= GNUTLS_E_SUCCESS) { | ||
| 871 | const char *name = fn_gnutls_pk_algorithm_get_name (err); | ||
| 872 | if (name) | ||
| 873 | res = nconc2 (res, list2 (intern (":public-key-algorithm"), | ||
| 874 | build_string (name))); | ||
| 875 | |||
| 876 | name = fn_gnutls_sec_param_get_name (fn_gnutls_pk_bits_to_sec_param | ||
| 877 | (err, bits)); | ||
| 878 | res = nconc2 (res, list2 (intern (":certificate-security-level"), | ||
| 879 | build_string (name))); | ||
| 880 | } | ||
| 881 | } | ||
| 882 | |||
| 883 | /* Unique IDs. */ | ||
| 884 | { | ||
| 885 | size_t buf_size = 0; | ||
| 886 | |||
| 887 | err = fn_gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size); | ||
| 888 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 889 | char *buf = malloc (buf_size); | ||
| 890 | err = fn_gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size); | ||
| 891 | if (err >= GNUTLS_E_SUCCESS) | ||
| 892 | res = nconc2 (res, list2 (intern (":issuer-unique-id"), | ||
| 893 | make_string (buf, buf_size))); | ||
| 894 | free (buf); | ||
| 895 | } | ||
| 896 | |||
| 897 | buf_size = 0; | ||
| 898 | err = fn_gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size); | ||
| 899 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 900 | char *buf = malloc (buf_size); | ||
| 901 | err = fn_gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size); | ||
| 902 | if (err >= GNUTLS_E_SUCCESS) | ||
| 903 | res = nconc2 (res, list2 (intern (":subject-unique-id"), | ||
| 904 | make_string (buf, buf_size))); | ||
| 905 | free (buf); | ||
| 906 | } | ||
| 907 | } | ||
| 908 | |||
| 909 | /* Signature. */ | ||
| 910 | { | ||
| 911 | size_t buf_size = 0; | ||
| 912 | |||
| 913 | err = fn_gnutls_x509_crt_get_signature_algorithm (cert); | ||
| 914 | if (err >= GNUTLS_E_SUCCESS) { | ||
| 915 | const char *name = fn_gnutls_sign_algorithm_get_name (err); | ||
| 916 | if (name) | ||
| 917 | res = nconc2 (res, list2 (intern (":signature-algorithm"), | ||
| 918 | build_string (name))); | ||
| 919 | |||
| 920 | err = fn_gnutls_x509_crt_get_signature (cert, NULL, &buf_size); | ||
| 921 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 922 | char *buf = malloc (buf_size); | ||
| 923 | err = fn_gnutls_x509_crt_get_signature (cert, buf, &buf_size); | ||
| 924 | if (err >= GNUTLS_E_SUCCESS) { | ||
| 925 | res = nconc2 (res, list2 (intern (":signature"), | ||
| 926 | gnutls_hex_string (buf, buf_size, ""))); | ||
| 927 | } | ||
| 928 | free (buf); | ||
| 929 | } | ||
| 930 | } | ||
| 931 | } | ||
| 932 | |||
| 933 | /* Public key ID. */ | ||
| 934 | { | ||
| 935 | size_t buf_size = 0; | ||
| 936 | |||
| 937 | err = fn_gnutls_x509_crt_get_key_id (cert, 0, NULL, &buf_size); | ||
| 938 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 939 | unsigned char *buf = malloc (buf_size); | ||
| 940 | err = fn_gnutls_x509_crt_get_key_id (cert, 0, buf, &buf_size); | ||
| 941 | if (err >= GNUTLS_E_SUCCESS) | ||
| 942 | res = nconc2 (res, list2 (intern (":public-key-id"), | ||
| 943 | gnutls_hex_string ((char *)buf, | ||
| 944 | buf_size, "sha1:"))); | ||
| 945 | free (buf); | ||
| 946 | } | ||
| 947 | } | ||
| 948 | |||
| 949 | /* Certificate fingerprint. */ | ||
| 950 | { | ||
| 951 | size_t buf_size = 0; | ||
| 952 | |||
| 953 | err = fn_gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, | ||
| 954 | NULL, &buf_size); | ||
| 955 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) { | ||
| 956 | unsigned char *buf = malloc (buf_size); | ||
| 957 | err = fn_gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, | ||
| 958 | buf, &buf_size); | ||
| 959 | if (err >= GNUTLS_E_SUCCESS) | ||
| 960 | res = nconc2 (res, list2 (intern (":certificate-id"), | ||
| 961 | gnutls_hex_string ((char *)buf, | ||
| 962 | buf_size, "sha1:"))); | ||
| 963 | free (buf); | ||
| 964 | } | ||
| 965 | } | ||
| 966 | |||
| 967 | return res; | ||
| 968 | } | ||
| 969 | |||
| 970 | DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0, | ||
| 971 | doc: /* Return the status of the gnutls PROC peer certificate. | ||
| 972 | The return value is a property list. */) | ||
| 973 | (Lisp_Object proc) | ||
| 974 | { | ||
| 975 | Lisp_Object warnings = Qnil, result = Qnil; | ||
| 976 | unsigned int verification; | ||
| 977 | |||
| 978 | CHECK_PROCESS (proc); | ||
| 979 | |||
| 980 | if (XPROCESS (proc)->gnutls_p == 0) | ||
| 981 | return Qnil; | ||
| 982 | |||
| 983 | /* Then collect any warnings already computed by the handshake. */ | ||
| 984 | verification = XPROCESS (proc)->gnutls_peer_verification; | ||
| 985 | |||
| 986 | if (verification & GNUTLS_CERT_INVALID) | ||
| 987 | warnings = Fcons (list2 (intern (":invalid"), | ||
| 988 | build_string("certificate could not be verified")), | ||
| 989 | warnings); | ||
| 990 | |||
| 991 | if (verification & GNUTLS_CERT_REVOKED) | ||
| 992 | warnings = Fcons (list2 (intern (":revoked"), | ||
| 993 | build_string("certificate was revoked (CRL)")), | ||
| 994 | warnings); | ||
| 995 | |||
| 996 | if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND) | ||
| 997 | warnings = Fcons (list2 (intern (":self-signed"), | ||
| 998 | build_string("certificate signer was not found (self-signed)")), | ||
| 999 | warnings); | ||
| 1000 | |||
| 1001 | if (verification & GNUTLS_CERT_SIGNER_NOT_CA) | ||
| 1002 | warnings = Fcons (list2 (intern (":not-ca"), | ||
| 1003 | build_string("certificate signer is not a CA")), | ||
| 1004 | warnings); | ||
| 1005 | |||
| 1006 | if (verification & GNUTLS_CERT_INSECURE_ALGORITHM) | ||
| 1007 | warnings = Fcons (list2 (intern (":insecure"), | ||
| 1008 | build_string("certificate was signed with an insecure algorithm")), | ||
| 1009 | warnings); | ||
| 1010 | |||
| 1011 | if (verification & GNUTLS_CERT_NOT_ACTIVATED) | ||
| 1012 | warnings = Fcons (list2 (intern (":not-activated"), | ||
| 1013 | build_string("certificate is not yet activated")), | ||
| 1014 | warnings); | ||
| 1015 | |||
| 1016 | if (verification & GNUTLS_CERT_EXPIRED) | ||
| 1017 | warnings = Fcons (list2 (intern (":expired"), | ||
| 1018 | build_string("certificate has expired")), | ||
| 1019 | warnings); | ||
| 1020 | |||
| 1021 | if (XPROCESS (proc)->gnutls_extra_peer_verification & | ||
| 1022 | CERTIFICATE_NOT_MATCHING) | ||
| 1023 | warnings = Fcons (list2 (intern (":no-host-match"), | ||
| 1024 | build_string("certificate host does not match hostname")), | ||
| 1025 | warnings); | ||
| 1026 | |||
| 1027 | if (!NILP (warnings)) | ||
| 1028 | result = list2 (intern (":warnings"), warnings); | ||
| 1029 | |||
| 1030 | result = nconc2 (result, list2 | ||
| 1031 | (intern (":certificate"), | ||
| 1032 | gnutls_certificate_details(XPROCESS (proc)->gnutls_certificate))); | ||
| 1033 | |||
| 1034 | return result; | ||
| 1035 | } | ||
| 1036 | |||
| 696 | 1037 | ||
| 697 | /* Initializes global GnuTLS state to defaults. | 1038 | /* Initializes global GnuTLS state to defaults. |
| 698 | Call `gnutls-global-deinit' when GnuTLS usage is no longer needed. | 1039 | Call `gnutls-global-deinit' when GnuTLS usage is no longer needed. |
| @@ -1048,6 +1389,8 @@ one trustfile (usually a CA bundle). */) | |||
| 1048 | if (ret < GNUTLS_E_SUCCESS) | 1389 | if (ret < GNUTLS_E_SUCCESS) |
| 1049 | return gnutls_make_error (ret); | 1390 | return gnutls_make_error (ret); |
| 1050 | 1391 | ||
| 1392 | XPROCESS (proc)->gnutls_peer_verification = peer_verification; | ||
| 1393 | |||
| 1051 | if (XINT (loglevel) > 0 && peer_verification & GNUTLS_CERT_INVALID) | 1394 | if (XINT (loglevel) > 0 && peer_verification & GNUTLS_CERT_INVALID) |
| 1052 | message ("%s certificate could not be verified.", c_hostname); | 1395 | message ("%s certificate could not be verified.", c_hostname); |
| 1053 | 1396 | ||
| @@ -1126,8 +1469,12 @@ one trustfile (usually a CA bundle). */) | |||
| 1126 | return gnutls_make_error (ret); | 1469 | return gnutls_make_error (ret); |
| 1127 | } | 1470 | } |
| 1128 | 1471 | ||
| 1472 | XPROCESS (proc)->gnutls_certificate = gnutls_verify_cert; | ||
| 1473 | |||
| 1129 | if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname)) | 1474 | if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname)) |
| 1130 | { | 1475 | { |
| 1476 | XPROCESS (proc)->gnutls_extra_peer_verification |= | ||
| 1477 | CERTIFICATE_NOT_MATCHING; | ||
| 1131 | if (verify_error_all | 1478 | if (verify_error_all |
| 1132 | || !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error))) | 1479 | || !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error))) |
| 1133 | { | 1480 | { |
| @@ -1141,7 +1488,6 @@ one trustfile (usually a CA bundle). */) | |||
| 1141 | c_hostname); | 1488 | c_hostname); |
| 1142 | } | 1489 | } |
| 1143 | } | 1490 | } |
| 1144 | fn_gnutls_x509_crt_deinit (gnutls_verify_cert); | ||
| 1145 | } | 1491 | } |
| 1146 | 1492 | ||
| 1147 | /* Set this flag only if the whole initialization succeeded. */ | 1493 | /* Set this flag only if the whole initialization succeeded. */ |
| @@ -1173,6 +1519,8 @@ This function may also return `gnutls-e-again', or | |||
| 1173 | 1519 | ||
| 1174 | state = XPROCESS (proc)->gnutls_state; | 1520 | state = XPROCESS (proc)->gnutls_state; |
| 1175 | 1521 | ||
| 1522 | fn_gnutls_x509_crt_deinit (XPROCESS (proc)->gnutls_certificate); | ||
| 1523 | |||
| 1176 | ret = fn_gnutls_bye (state, | 1524 | ret = fn_gnutls_bye (state, |
| 1177 | NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR); | 1525 | NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR); |
| 1178 | 1526 | ||
| @@ -1224,6 +1572,7 @@ syms_of_gnutls (void) | |||
| 1224 | defsubr (&Sgnutls_deinit); | 1572 | defsubr (&Sgnutls_deinit); |
| 1225 | defsubr (&Sgnutls_bye); | 1573 | defsubr (&Sgnutls_bye); |
| 1226 | defsubr (&Sgnutls_available_p); | 1574 | defsubr (&Sgnutls_available_p); |
| 1575 | defsubr (&Sgnutls_peer_status); | ||
| 1227 | 1576 | ||
| 1228 | DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level, | 1577 | DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level, |
| 1229 | doc: /* Logging level used by the GnuTLS functions. | 1578 | doc: /* Logging level used by the GnuTLS functions. |
diff --git a/src/process.h b/src/process.h index 273ad9267d6..56c0f6d6302 100644 --- a/src/process.h +++ b/src/process.h | |||
| @@ -162,6 +162,9 @@ struct Lisp_Process | |||
| 162 | gnutls_session_t gnutls_state; | 162 | gnutls_session_t gnutls_state; |
| 163 | gnutls_certificate_client_credentials gnutls_x509_cred; | 163 | gnutls_certificate_client_credentials gnutls_x509_cred; |
| 164 | gnutls_anon_client_credentials_t gnutls_anon_cred; | 164 | gnutls_anon_client_credentials_t gnutls_anon_cred; |
| 165 | gnutls_x509_crt_t gnutls_certificate; | ||
| 166 | unsigned int gnutls_peer_verification; | ||
| 167 | unsigned int gnutls_extra_peer_verification; | ||
| 165 | int gnutls_log_level; | 168 | int gnutls_log_level; |
| 166 | int gnutls_handshakes_tried; | 169 | int gnutls_handshakes_tried; |
| 167 | bool_bf gnutls_p : 1; | 170 | bool_bf gnutls_p : 1; |