1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2014 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
29 #include <gnutls/gnutls.h>
36 static bool emacs_gnutls_handle_error (gnutls_session_t
, int);
38 static Lisp_Object Qgnutls_dll
;
39 static Lisp_Object Qgnutls_code
;
40 static Lisp_Object Qgnutls_anon
, Qgnutls_x509pki
;
41 static Lisp_Object Qgnutls_e_interrupted
, Qgnutls_e_again
,
42 Qgnutls_e_invalid_session
, Qgnutls_e_not_ready_for_handshake
;
43 static bool gnutls_global_initialized
;
45 /* The following are for the property list of `gnutls-boot'. */
46 static Lisp_Object QCgnutls_bootprop_priority
;
47 static Lisp_Object QCgnutls_bootprop_trustfiles
;
48 static Lisp_Object QCgnutls_bootprop_keylist
;
49 static Lisp_Object QCgnutls_bootprop_crlfiles
;
50 static Lisp_Object QCgnutls_bootprop_callbacks
;
51 static Lisp_Object QCgnutls_bootprop_loglevel
;
52 static Lisp_Object QCgnutls_bootprop_hostname
;
53 static Lisp_Object QCgnutls_bootprop_min_prime_bits
;
54 static Lisp_Object QCgnutls_bootprop_verify_flags
;
55 static Lisp_Object QCgnutls_bootprop_verify_error
;
57 /* Callback keys for `gnutls-boot'. Unused currently. */
58 static Lisp_Object QCgnutls_bootprop_callbacks_verify
;
60 static void gnutls_log_function (int, const char *);
61 static void gnutls_log_function2 (int, const char *, const char *);
63 static void gnutls_audit_log_function (gnutls_session_t
, const char *);
66 enum extra_peer_verification
68 CERTIFICATE_NOT_MATCHING
= 2
74 /* Macro for defining functions that will be loaded from the GnuTLS DLL. */
75 #define DEF_GNUTLS_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
77 /* Macro for loading GnuTLS functions from the library. */
78 #define LOAD_GNUTLS_FN(lib,func) { \
79 fn_##func = (void *) GetProcAddress (lib, #func); \
80 if (!fn_##func) return 0; \
83 DEF_GNUTLS_FN (gnutls_alert_description_t
, gnutls_alert_get
,
85 DEF_GNUTLS_FN (const char *, gnutls_alert_get_name
,
86 (gnutls_alert_description_t
));
87 DEF_GNUTLS_FN (int, gnutls_alert_send_appropriate
, (gnutls_session_t
, int));
88 DEF_GNUTLS_FN (int, gnutls_anon_allocate_client_credentials
,
89 (gnutls_anon_client_credentials_t
*));
90 DEF_GNUTLS_FN (void, gnutls_anon_free_client_credentials
,
91 (gnutls_anon_client_credentials_t
));
92 DEF_GNUTLS_FN (int, gnutls_bye
, (gnutls_session_t
, gnutls_close_request_t
));
93 DEF_GNUTLS_FN (int, gnutls_certificate_allocate_credentials
,
94 (gnutls_certificate_credentials_t
*));
95 DEF_GNUTLS_FN (void, gnutls_certificate_free_credentials
,
96 (gnutls_certificate_credentials_t
));
97 DEF_GNUTLS_FN (const gnutls_datum_t
*, gnutls_certificate_get_peers
,
98 (gnutls_session_t
, unsigned int *));
99 DEF_GNUTLS_FN (void, gnutls_certificate_set_verify_flags
,
100 (gnutls_certificate_credentials_t
, unsigned int));
101 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_crl_file
,
102 (gnutls_certificate_credentials_t
, const char *,
103 gnutls_x509_crt_fmt_t
));
104 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_key_file
,
105 (gnutls_certificate_credentials_t
, const char *, const char *,
106 gnutls_x509_crt_fmt_t
));
107 #if GNUTLS_VERSION_MAJOR + \
108 (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
109 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_system_trust
,
110 (gnutls_certificate_credentials_t
));
112 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_trust_file
,
113 (gnutls_certificate_credentials_t
, const char *,
114 gnutls_x509_crt_fmt_t
));
115 DEF_GNUTLS_FN (gnutls_certificate_type_t
, gnutls_certificate_type_get
,
117 DEF_GNUTLS_FN (int, gnutls_certificate_verify_peers2
,
118 (gnutls_session_t
, unsigned int *));
119 DEF_GNUTLS_FN (int, gnutls_credentials_set
,
120 (gnutls_session_t
, gnutls_credentials_type_t
, void *));
121 DEF_GNUTLS_FN (void, gnutls_deinit
, (gnutls_session_t
));
122 DEF_GNUTLS_FN (void, gnutls_dh_set_prime_bits
,
123 (gnutls_session_t
, unsigned int));
124 DEF_GNUTLS_FN (int, gnutls_dh_get_prime_bits
, (gnutls_session_t
));
125 DEF_GNUTLS_FN (int, gnutls_error_is_fatal
, (int));
126 DEF_GNUTLS_FN (int, gnutls_global_init
, (void));
127 DEF_GNUTLS_FN (void, gnutls_global_set_log_function
, (gnutls_log_func
));
129 DEF_GNUTLS_FN (void, gnutls_global_set_audit_log_function
, (gnutls_audit_log_func
));
131 DEF_GNUTLS_FN (void, gnutls_global_set_log_level
, (int));
132 DEF_GNUTLS_FN (void, gnutls_global_set_mem_functions
,
133 (gnutls_alloc_function
, gnutls_alloc_function
,
134 gnutls_is_secure_function
, gnutls_realloc_function
,
135 gnutls_free_function
));
136 DEF_GNUTLS_FN (int, gnutls_handshake
, (gnutls_session_t
));
137 DEF_GNUTLS_FN (int, gnutls_init
, (gnutls_session_t
*, gnutls_connection_end_t
));
138 DEF_GNUTLS_FN (int, gnutls_priority_set_direct
,
139 (gnutls_session_t
, const char *, const char **));
140 DEF_GNUTLS_FN (size_t, gnutls_record_check_pending
, (gnutls_session_t
));
141 DEF_GNUTLS_FN (ssize_t
, gnutls_record_recv
, (gnutls_session_t
, void *, size_t));
142 DEF_GNUTLS_FN (ssize_t
, gnutls_record_send
,
143 (gnutls_session_t
, const void *, size_t));
144 DEF_GNUTLS_FN (const char *, gnutls_strerror
, (int));
145 DEF_GNUTLS_FN (void, gnutls_transport_set_errno
, (gnutls_session_t
, int));
146 DEF_GNUTLS_FN (const char *, gnutls_check_version
, (const char *));
147 DEF_GNUTLS_FN (void, gnutls_transport_set_lowat
, (gnutls_session_t
, int));
148 DEF_GNUTLS_FN (void, gnutls_transport_set_ptr2
,
149 (gnutls_session_t
, gnutls_transport_ptr_t
,
150 gnutls_transport_ptr_t
));
151 DEF_GNUTLS_FN (void, gnutls_transport_set_pull_function
,
152 (gnutls_session_t
, gnutls_pull_func
));
153 DEF_GNUTLS_FN (void, gnutls_transport_set_push_function
,
154 (gnutls_session_t
, gnutls_push_func
));
155 DEF_GNUTLS_FN (int, gnutls_x509_crt_check_hostname
,
156 (gnutls_x509_crt_t
, const char *));
157 DEF_GNUTLS_FN (void, gnutls_x509_crt_deinit
, (gnutls_x509_crt_t
));
158 DEF_GNUTLS_FN (int, gnutls_x509_crt_import
,
159 (gnutls_x509_crt_t
, const gnutls_datum_t
*,
160 gnutls_x509_crt_fmt_t
));
161 DEF_GNUTLS_FN (int, gnutls_x509_crt_init
, (gnutls_x509_crt_t
*));
162 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_fingerprint
,
164 gnutls_digest_algorithm_t
, void *, size_t *));
165 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_version
,
166 (gnutls_x509_crt_t
));
167 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_serial
,
168 (gnutls_x509_crt_t
, void *, size_t *));
169 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_issuer_dn
,
170 (gnutls_x509_crt_t
, char *, size_t *));
171 DEF_GNUTLS_FN (time_t, gnutls_x509_crt_get_activation_time
,
172 (gnutls_x509_crt_t
));
173 DEF_GNUTLS_FN (time_t, gnutls_x509_crt_get_expiration_time
,
174 (gnutls_x509_crt_t
));
175 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_dn
,
176 (gnutls_x509_crt_t
, char *, size_t *));
177 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_pk_algorithm
,
178 (gnutls_x509_crt_t
, unsigned int *));
179 DEF_GNUTLS_FN (const char*, gnutls_pk_algorithm_get_name
,
180 (gnutls_pk_algorithm_t
));
181 DEF_GNUTLS_FN (int, gnutls_pk_bits_to_sec_param
,
182 (gnutls_pk_algorithm_t
, unsigned int));
183 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_issuer_unique_id
,
184 (gnutls_x509_crt_t
, char *, size_t *));
185 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_subject_unique_id
,
186 (gnutls_x509_crt_t
, char *, size_t *));
187 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_signature_algorithm
,
188 (gnutls_x509_crt_t
));
189 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_signature
,
190 (gnutls_x509_crt_t
, char *, size_t *));
191 DEF_GNUTLS_FN (int, gnutls_x509_crt_get_key_id
,
192 (gnutls_x509_crt_t
, unsigned int,
193 unsigned char *, size_t *_size
));
194 DEF_GNUTLS_FN (const char*, gnutls_sec_param_get_name
, (gnutls_sec_param_t
));
195 DEF_GNUTLS_FN (const char*, gnutls_sign_get_name
, (gnutls_sign_algorithm_t
));
196 DEF_GNUTLS_FN (int, gnutls_server_name_set
, (gnutls_session_t
,
197 gnutls_server_name_type_t
,
198 const void *, size_t));
199 DEF_GNUTLS_FN (gnutls_kx_algorithm_t
, gnutls_kx_get
, (gnutls_session_t
));
200 DEF_GNUTLS_FN (const char*, gnutls_kx_get_name
, (gnutls_kx_algorithm_t
));
201 DEF_GNUTLS_FN (gnutls_protocol_t
, gnutls_protocol_get_version
,
203 DEF_GNUTLS_FN (const char*, gnutls_protocol_get_name
, (gnutls_protocol_t
));
204 DEF_GNUTLS_FN (gnutls_cipher_algorithm_t
, gnutls_cipher_get
,
206 DEF_GNUTLS_FN (const char*, gnutls_cipher_get_name
,
207 (gnutls_cipher_algorithm_t
));
208 DEF_GNUTLS_FN (gnutls_mac_algorithm_t
, gnutls_mac_get
, (gnutls_session_t
));
209 DEF_GNUTLS_FN (const char*, gnutls_mac_get_name
, (gnutls_mac_algorithm_t
));
213 init_gnutls_functions (void)
216 int max_log_level
= 1;
218 if (!(library
= w32_delayed_load (Qgnutls_dll
)))
220 GNUTLS_LOG (1, max_log_level
, "GnuTLS library not found");
224 LOAD_GNUTLS_FN (library
, gnutls_alert_get
);
225 LOAD_GNUTLS_FN (library
, gnutls_alert_get_name
);
226 LOAD_GNUTLS_FN (library
, gnutls_alert_send_appropriate
);
227 LOAD_GNUTLS_FN (library
, gnutls_anon_allocate_client_credentials
);
228 LOAD_GNUTLS_FN (library
, gnutls_anon_free_client_credentials
);
229 LOAD_GNUTLS_FN (library
, gnutls_bye
);
230 LOAD_GNUTLS_FN (library
, gnutls_certificate_allocate_credentials
);
231 LOAD_GNUTLS_FN (library
, gnutls_certificate_free_credentials
);
232 LOAD_GNUTLS_FN (library
, gnutls_certificate_get_peers
);
233 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_verify_flags
);
234 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_crl_file
);
235 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_key_file
);
236 #if GNUTLS_VERSION_MAJOR + \
237 (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
238 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_system_trust
);
240 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_trust_file
);
241 LOAD_GNUTLS_FN (library
, gnutls_certificate_type_get
);
242 LOAD_GNUTLS_FN (library
, gnutls_certificate_verify_peers2
);
243 LOAD_GNUTLS_FN (library
, gnutls_credentials_set
);
244 LOAD_GNUTLS_FN (library
, gnutls_deinit
);
245 LOAD_GNUTLS_FN (library
, gnutls_dh_set_prime_bits
);
246 LOAD_GNUTLS_FN (library
, gnutls_dh_get_prime_bits
);
247 LOAD_GNUTLS_FN (library
, gnutls_error_is_fatal
);
248 LOAD_GNUTLS_FN (library
, gnutls_global_init
);
249 LOAD_GNUTLS_FN (library
, gnutls_global_set_log_function
);
251 LOAD_GNUTLS_FN (library
, gnutls_global_set_audit_log_function
);
253 LOAD_GNUTLS_FN (library
, gnutls_global_set_log_level
);
254 LOAD_GNUTLS_FN (library
, gnutls_global_set_mem_functions
);
255 LOAD_GNUTLS_FN (library
, gnutls_handshake
);
256 LOAD_GNUTLS_FN (library
, gnutls_init
);
257 LOAD_GNUTLS_FN (library
, gnutls_priority_set_direct
);
258 LOAD_GNUTLS_FN (library
, gnutls_record_check_pending
);
259 LOAD_GNUTLS_FN (library
, gnutls_record_recv
);
260 LOAD_GNUTLS_FN (library
, gnutls_record_send
);
261 LOAD_GNUTLS_FN (library
, gnutls_strerror
);
262 LOAD_GNUTLS_FN (library
, gnutls_transport_set_errno
);
263 LOAD_GNUTLS_FN (library
, gnutls_check_version
);
264 /* We don't need to call gnutls_transport_set_lowat in GnuTLS 2.11.1
265 and later, and the function was removed entirely in 3.0.0. */
266 if (!fn_gnutls_check_version ("2.11.1"))
267 LOAD_GNUTLS_FN (library
, gnutls_transport_set_lowat
);
268 LOAD_GNUTLS_FN (library
, gnutls_transport_set_ptr2
);
269 LOAD_GNUTLS_FN (library
, gnutls_transport_set_pull_function
);
270 LOAD_GNUTLS_FN (library
, gnutls_transport_set_push_function
);
271 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_check_hostname
);
272 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_deinit
);
273 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_import
);
274 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_init
);
275 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_fingerprint
);
276 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_version
);
277 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_serial
);
278 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_issuer_dn
);
279 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_activation_time
);
280 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_expiration_time
);
281 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_dn
);
282 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_pk_algorithm
);
283 LOAD_GNUTLS_FN (library
, gnutls_pk_algorithm_get_name
);
284 LOAD_GNUTLS_FN (library
, gnutls_pk_bits_to_sec_param
);
285 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_issuer_unique_id
);
286 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_subject_unique_id
);
287 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_signature_algorithm
);
288 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_signature
);
289 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_get_key_id
);
290 LOAD_GNUTLS_FN (library
, gnutls_sec_param_get_name
);
291 LOAD_GNUTLS_FN (library
, gnutls_sign_get_name
);
292 LOAD_GNUTLS_FN (library
, gnutls_server_name_set
);
293 LOAD_GNUTLS_FN (library
, gnutls_kx_get
);
294 LOAD_GNUTLS_FN (library
, gnutls_kx_get_name
);
295 LOAD_GNUTLS_FN (library
, gnutls_protocol_get_version
);
296 LOAD_GNUTLS_FN (library
, gnutls_protocol_get_name
);
297 LOAD_GNUTLS_FN (library
, gnutls_cipher_get
);
298 LOAD_GNUTLS_FN (library
, gnutls_cipher_get_name
);
299 LOAD_GNUTLS_FN (library
, gnutls_mac_get
);
300 LOAD_GNUTLS_FN (library
, gnutls_mac_get_name
);
302 max_log_level
= global_gnutls_log_level
;
305 Lisp_Object name
= CAR_SAFE (Fget (Qgnutls_dll
, QCloaded_from
));
306 GNUTLS_LOG2 (1, max_log_level
, "GnuTLS library loaded:",
307 STRINGP (name
) ? (const char *) SDATA (name
) : "unknown");
313 #else /* !WINDOWSNT */
315 #define fn_gnutls_alert_get gnutls_alert_get
316 #define fn_gnutls_alert_get_name gnutls_alert_get_name
317 #define fn_gnutls_alert_send_appropriate gnutls_alert_send_appropriate
318 #define fn_gnutls_anon_allocate_client_credentials gnutls_anon_allocate_client_credentials
319 #define fn_gnutls_anon_free_client_credentials gnutls_anon_free_client_credentials
320 #define fn_gnutls_bye gnutls_bye
321 #define fn_gnutls_certificate_allocate_credentials gnutls_certificate_allocate_credentials
322 #define fn_gnutls_certificate_free_credentials gnutls_certificate_free_credentials
323 #define fn_gnutls_certificate_get_peers gnutls_certificate_get_peers
324 #define fn_gnutls_certificate_set_verify_flags gnutls_certificate_set_verify_flags
325 #define fn_gnutls_certificate_set_x509_crl_file gnutls_certificate_set_x509_crl_file
326 #define fn_gnutls_certificate_set_x509_key_file gnutls_certificate_set_x509_key_file
327 #if GNUTLS_VERSION_MAJOR + \
328 (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
329 #define fn_gnutls_certificate_set_x509_system_trust gnutls_certificate_set_x509_system_trust
331 #define fn_gnutls_certificate_set_x509_trust_file gnutls_certificate_set_x509_trust_file
332 #define fn_gnutls_certificate_type_get gnutls_certificate_type_get
333 #define fn_gnutls_certificate_verify_peers2 gnutls_certificate_verify_peers2
334 #define fn_gnutls_cipher_get gnutls_cipher_get
335 #define fn_gnutls_cipher_get_name gnutls_cipher_get_name
336 #define fn_gnutls_credentials_set gnutls_credentials_set
337 #define fn_gnutls_deinit gnutls_deinit
338 #define fn_gnutls_dh_get_prime_bits gnutls_dh_get_prime_bits
339 #define fn_gnutls_dh_set_prime_bits gnutls_dh_set_prime_bits
340 #define fn_gnutls_error_is_fatal gnutls_error_is_fatal
341 #define fn_gnutls_global_init gnutls_global_init
343 #define fn_gnutls_global_set_audit_log_function gnutls_global_set_audit_log_function
345 #define fn_gnutls_global_set_log_function gnutls_global_set_log_function
346 #define fn_gnutls_global_set_log_level gnutls_global_set_log_level
347 #define fn_gnutls_global_set_mem_functions gnutls_global_set_mem_functions
348 #define fn_gnutls_handshake gnutls_handshake
349 #define fn_gnutls_init gnutls_init
350 #define fn_gnutls_kx_get gnutls_kx_get
351 #define fn_gnutls_kx_get_name gnutls_kx_get_name
352 #define fn_gnutls_mac_get gnutls_mac_get
353 #define fn_gnutls_mac_get_name gnutls_mac_get_name
354 #define fn_gnutls_pk_algorithm_get_name gnutls_pk_algorithm_get_name
355 #define fn_gnutls_pk_bits_to_sec_param gnutls_pk_bits_to_sec_param
356 #define fn_gnutls_priority_set_direct gnutls_priority_set_direct
357 #define fn_gnutls_protocol_get_name gnutls_protocol_get_name
358 #define fn_gnutls_protocol_get_version gnutls_protocol_get_version
359 #define fn_gnutls_record_check_pending gnutls_record_check_pending
360 #define fn_gnutls_record_recv gnutls_record_recv
361 #define fn_gnutls_record_send gnutls_record_send
362 #define fn_gnutls_sec_param_get_name gnutls_sec_param_get_name
363 #define fn_gnutls_server_name_set gnutls_server_name_set
364 #define fn_gnutls_sign_get_name gnutls_sign_get_name
365 #define fn_gnutls_strerror gnutls_strerror
366 #define fn_gnutls_transport_set_ptr2 gnutls_transport_set_ptr2
367 #define fn_gnutls_x509_crt_check_hostname gnutls_x509_crt_check_hostname
368 #define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit
369 #define fn_gnutls_x509_crt_get_activation_time gnutls_x509_crt_get_activation_time
370 #define fn_gnutls_x509_crt_get_dn gnutls_x509_crt_get_dn
371 #define fn_gnutls_x509_crt_get_expiration_time gnutls_x509_crt_get_expiration_time
372 #define fn_gnutls_x509_crt_get_fingerprint gnutls_x509_crt_get_fingerprint
373 #define fn_gnutls_x509_crt_get_issuer_dn gnutls_x509_crt_get_issuer_dn
374 #define fn_gnutls_x509_crt_get_issuer_unique_id gnutls_x509_crt_get_issuer_unique_id
375 #define fn_gnutls_x509_crt_get_key_id gnutls_x509_crt_get_key_id
376 #define fn_gnutls_x509_crt_get_pk_algorithm gnutls_x509_crt_get_pk_algorithm
377 #define fn_gnutls_x509_crt_get_serial gnutls_x509_crt_get_serial
378 #define fn_gnutls_x509_crt_get_signature_algorithm gnutls_x509_crt_get_signature_algorithm
379 #define fn_gnutls_x509_crt_get_subject_unique_id gnutls_x509_crt_get_subject_unique_id
380 #define fn_gnutls_x509_crt_get_version gnutls_x509_crt_get_version
381 #define fn_gnutls_x509_crt_import gnutls_x509_crt_import
382 #define fn_gnutls_x509_crt_init gnutls_x509_crt_init
384 #endif /* !WINDOWSNT */
388 /* Log a simple audit message. */
390 gnutls_audit_log_function (gnutls_session_t session
, const char *string
)
392 if (global_gnutls_log_level
>= 1)
394 message ("gnutls.c: [audit] %s", string
);
399 /* Log a simple message. */
401 gnutls_log_function (int level
, const char *string
)
403 message ("gnutls.c: [%d] %s", level
, string
);
406 /* Log a message and a string. */
408 gnutls_log_function2 (int level
, const char *string
, const char *extra
)
410 message ("gnutls.c: [%d] %s %s", level
, string
, extra
);
413 /* Log a message and an integer. */
415 gnutls_log_function2i (int level
, const char *string
, int extra
)
417 message ("gnutls.c: [%d] %s %d", level
, string
, extra
);
421 emacs_gnutls_handshake (struct Lisp_Process
*proc
)
423 gnutls_session_t state
= proc
->gnutls_state
;
426 if (proc
->gnutls_initstage
< GNUTLS_STAGE_HANDSHAKE_CANDO
)
429 if (proc
->gnutls_initstage
< GNUTLS_STAGE_TRANSPORT_POINTERS_SET
)
432 /* On W32 we cannot transfer socket handles between different runtime
433 libraries, so we tell GnuTLS to use our special push/pull
435 fn_gnutls_transport_set_ptr2 (state
,
436 (gnutls_transport_ptr_t
) proc
,
437 (gnutls_transport_ptr_t
) proc
);
438 fn_gnutls_transport_set_push_function (state
, &emacs_gnutls_push
);
439 fn_gnutls_transport_set_pull_function (state
, &emacs_gnutls_pull
);
441 /* For non blocking sockets or other custom made pull/push
442 functions the gnutls_transport_set_lowat must be called, with
443 a zero low water mark value. (GnuTLS 2.10.4 documentation)
445 (Note: this is probably not strictly necessary as the lowat
446 value is only used when no custom pull/push functions are
448 /* According to GnuTLS NEWS file, lowat level has been set to
449 zero by default in version 2.11.1, and the function
450 gnutls_transport_set_lowat was removed from the library in
452 if (!fn_gnutls_check_version ("2.11.1"))
453 fn_gnutls_transport_set_lowat (state
, 0);
455 /* This is how GnuTLS takes sockets: as file descriptors passed
456 in. For an Emacs process socket, infd and outfd are the
457 same but we use this two-argument version for clarity. */
458 fn_gnutls_transport_set_ptr2 (state
,
459 (void *) (intptr_t) proc
->infd
,
460 (void *) (intptr_t) proc
->outfd
);
463 proc
->gnutls_initstage
= GNUTLS_STAGE_TRANSPORT_POINTERS_SET
;
468 ret
= fn_gnutls_handshake (state
);
469 emacs_gnutls_handle_error (state
, ret
);
472 while (ret
< 0 && fn_gnutls_error_is_fatal (ret
) == 0);
474 proc
->gnutls_initstage
= GNUTLS_STAGE_HANDSHAKE_TRIED
;
476 if (ret
== GNUTLS_E_SUCCESS
)
478 /* Here we're finally done. */
479 proc
->gnutls_initstage
= GNUTLS_STAGE_READY
;
483 fn_gnutls_alert_send_appropriate (state
, ret
);
489 emacs_gnutls_record_check_pending (gnutls_session_t state
)
491 return fn_gnutls_record_check_pending (state
);
496 emacs_gnutls_transport_set_errno (gnutls_session_t state
, int err
)
498 fn_gnutls_transport_set_errno (state
, err
);
503 emacs_gnutls_write (struct Lisp_Process
*proc
, const char *buf
, ptrdiff_t nbyte
)
506 ptrdiff_t bytes_written
;
507 gnutls_session_t state
= proc
->gnutls_state
;
509 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
)
519 rtnval
= fn_gnutls_record_send (state
, buf
, nbyte
);
523 if (rtnval
== GNUTLS_E_INTERRUPTED
)
527 /* If we get GNUTLS_E_AGAIN, then set errno
528 appropriately so that send_process retries the
529 correct way instead of erroring out. */
530 if (rtnval
== GNUTLS_E_AGAIN
)
538 bytes_written
+= rtnval
;
541 emacs_gnutls_handle_error (state
, rtnval
);
542 return (bytes_written
);
546 emacs_gnutls_read (struct Lisp_Process
*proc
, char *buf
, ptrdiff_t nbyte
)
549 gnutls_session_t state
= proc
->gnutls_state
;
551 int log_level
= proc
->gnutls_log_level
;
553 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
)
555 /* If the handshake count is under the limit, try the handshake
556 again and increment the handshake count. This count is kept
557 per process (connection), not globally. */
558 if (proc
->gnutls_handshakes_tried
< GNUTLS_EMACS_HANDSHAKES_LIMIT
)
560 proc
->gnutls_handshakes_tried
++;
561 emacs_gnutls_handshake (proc
);
562 GNUTLS_LOG2i (5, log_level
, "Retried handshake",
563 proc
->gnutls_handshakes_tried
);
567 GNUTLS_LOG (2, log_level
, "Giving up on handshake; resetting retries");
568 proc
->gnutls_handshakes_tried
= 0;
571 rtnval
= fn_gnutls_record_recv (state
, buf
, nbyte
);
574 else if (rtnval
== GNUTLS_E_UNEXPECTED_PACKET_LENGTH
)
575 /* The peer closed the connection. */
577 else if (emacs_gnutls_handle_error (state
, rtnval
))
578 /* non-fatal error */
581 /* a fatal error occurred */
586 /* Report a GnuTLS error to the user.
587 Return true if the error code was successfully handled. */
589 emacs_gnutls_handle_error (gnutls_session_t session
, int err
)
591 int max_log_level
= 0;
596 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
600 max_log_level
= global_gnutls_log_level
;
602 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
604 str
= fn_gnutls_strerror (err
);
608 if (fn_gnutls_error_is_fatal (err
))
611 GNUTLS_LOG2 (1, max_log_level
, "fatal error:", str
);
632 if (err
== GNUTLS_E_WARNING_ALERT_RECEIVED
633 || err
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
635 int alert
= fn_gnutls_alert_get (session
);
636 int level
= (err
== GNUTLS_E_FATAL_ALERT_RECEIVED
) ? 0 : 1;
637 str
= fn_gnutls_alert_get_name (alert
);
641 GNUTLS_LOG2 (level
, max_log_level
, "Received alert: ", str
);
646 /* convert an integer error to a Lisp_Object; it will be either a
647 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
648 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
651 gnutls_make_error (int err
)
655 case GNUTLS_E_SUCCESS
:
658 return Qgnutls_e_again
;
659 case GNUTLS_E_INTERRUPTED
:
660 return Qgnutls_e_interrupted
;
661 case GNUTLS_E_INVALID_SESSION
:
662 return Qgnutls_e_invalid_session
;
665 return make_number (err
);
669 emacs_gnutls_deinit (Lisp_Object proc
)
673 CHECK_PROCESS (proc
);
675 if (XPROCESS (proc
)->gnutls_p
== 0)
678 log_level
= XPROCESS (proc
)->gnutls_log_level
;
680 if (XPROCESS (proc
)->gnutls_x509_cred
)
682 GNUTLS_LOG (2, log_level
, "Deallocating x509 credentials");
683 fn_gnutls_certificate_free_credentials (XPROCESS (proc
)->gnutls_x509_cred
);
684 XPROCESS (proc
)->gnutls_x509_cred
= NULL
;
687 if (XPROCESS (proc
)->gnutls_anon_cred
)
689 GNUTLS_LOG (2, log_level
, "Deallocating anon credentials");
690 fn_gnutls_anon_free_client_credentials (XPROCESS (proc
)->gnutls_anon_cred
);
691 XPROCESS (proc
)->gnutls_anon_cred
= NULL
;
694 if (XPROCESS (proc
)->gnutls_state
)
696 fn_gnutls_deinit (XPROCESS (proc
)->gnutls_state
);
697 XPROCESS (proc
)->gnutls_state
= NULL
;
698 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_INIT
)
699 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
- 1;
702 XPROCESS (proc
)->gnutls_p
= 0;
706 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage
, Sgnutls_get_initstage
, 1, 1, 0,
707 doc
: /* Return the GnuTLS init stage of process PROC.
708 See also `gnutls-boot'. */)
711 CHECK_PROCESS (proc
);
713 return make_number (GNUTLS_INITSTAGE (proc
));
716 DEFUN ("gnutls-errorp", Fgnutls_errorp
, Sgnutls_errorp
, 1, 1, 0,
717 doc
: /* Return t if ERROR indicates a GnuTLS problem.
718 ERROR is an integer or a symbol with an integer `gnutls-code' property.
719 usage: (gnutls-errorp ERROR) */)
722 if (EQ (err
, Qt
)) return Qnil
;
727 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp
, Sgnutls_error_fatalp
, 1, 1, 0,
728 doc
: /* Return non-nil if ERROR is fatal.
729 ERROR is an integer or a symbol with an integer `gnutls-code' property.
730 Usage: (gnutls-error-fatalp ERROR) */)
735 if (EQ (err
, Qt
)) return Qnil
;
739 code
= Fget (err
, Qgnutls_code
);
746 error ("Symbol has no numeric gnutls-code property");
750 if (! TYPE_RANGED_INTEGERP (int, err
))
751 error ("Not an error symbol or code");
753 if (0 == fn_gnutls_error_is_fatal (XINT (err
)))
759 DEFUN ("gnutls-error-string", Fgnutls_error_string
, Sgnutls_error_string
, 1, 1, 0,
760 doc
: /* Return a description of ERROR.
761 ERROR is an integer or a symbol with an integer `gnutls-code' property.
762 usage: (gnutls-error-string ERROR) */)
767 if (EQ (err
, Qt
)) return build_string ("Not an error");
771 code
= Fget (err
, Qgnutls_code
);
778 return build_string ("Symbol has no numeric gnutls-code property");
782 if (! TYPE_RANGED_INTEGERP (int, err
))
783 return build_string ("Not an error symbol or code");
785 return build_string (fn_gnutls_strerror (XINT (err
)));
788 DEFUN ("gnutls-deinit", Fgnutls_deinit
, Sgnutls_deinit
, 1, 1, 0,
789 doc
: /* Deallocate GnuTLS resources associated with process PROC.
790 See also `gnutls-init'. */)
793 return emacs_gnutls_deinit (proc
);
797 gnutls_hex_string (unsigned char *buf
, ptrdiff_t buf_size
, const char *prefix
)
799 ptrdiff_t prefix_length
= strlen (prefix
);
800 if ((STRING_BYTES_BOUND
- prefix_length
) / 3 < buf_size
)
802 Lisp_Object ret
= make_uninit_string (prefix_length
+ 3 * buf_size
804 char *string
= SSDATA (ret
);
805 strcpy (string
, prefix
);
807 for (ptrdiff_t i
= 0; i
< buf_size
; i
++)
808 sprintf (string
+ i
* 3 + prefix_length
,
809 i
== buf_size
- 1 ? "%02x" : "%02x:",
816 gnutls_certificate_details (gnutls_x509_crt_t cert
)
818 Lisp_Object res
= Qnil
;
824 int version
= fn_gnutls_x509_crt_get_version (cert
);
825 if (version
>= GNUTLS_E_SUCCESS
)
826 res
= nconc2 (res
, list2 (intern (":version"),
827 make_number (version
)));
832 err
= fn_gnutls_x509_crt_get_serial (cert
, NULL
, &buf_size
);
833 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
835 void *serial
= xmalloc (buf_size
);
836 err
= fn_gnutls_x509_crt_get_serial (cert
, serial
, &buf_size
);
837 if (err
>= GNUTLS_E_SUCCESS
)
838 res
= nconc2 (res
, list2 (intern (":serial-number"),
839 gnutls_hex_string (serial
, buf_size
, "")));
845 err
= fn_gnutls_x509_crt_get_issuer_dn (cert
, NULL
, &buf_size
);
846 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
848 char *dn
= xmalloc (buf_size
);
849 err
= fn_gnutls_x509_crt_get_issuer_dn (cert
, dn
, &buf_size
);
850 if (err
>= GNUTLS_E_SUCCESS
)
851 res
= nconc2 (res
, list2 (intern (":issuer"),
852 make_string (dn
, buf_size
)));
858 /* Add 1 to the buffer size, since 1900 is added to tm_year and
859 that might add 1 to the year length. */
860 char buf
[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
862 time_t tim
= fn_gnutls_x509_crt_get_activation_time (cert
);
864 if (gmtime_r (&tim
, &t
) && strftime (buf
, sizeof buf
, "%Y-%m-%d", &t
))
865 res
= nconc2 (res
, list2 (intern (":valid-from"), build_string (buf
)));
867 tim
= fn_gnutls_x509_crt_get_expiration_time (cert
);
868 if (gmtime_r (&tim
, &t
) && strftime (buf
, sizeof buf
, "%Y-%m-%d", &t
))
869 res
= nconc2 (res
, list2 (intern (":valid-to"), build_string (buf
)));
874 err
= fn_gnutls_x509_crt_get_dn (cert
, NULL
, &buf_size
);
875 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
877 char *dn
= xmalloc (buf_size
);
878 err
= fn_gnutls_x509_crt_get_dn (cert
, dn
, &buf_size
);
879 if (err
>= GNUTLS_E_SUCCESS
)
880 res
= nconc2 (res
, list2 (intern (":subject"),
881 make_string (dn
, buf_size
)));
885 /* Versions older than 2.11 doesn't have these four functions. */
886 #if GNUTLS_VERSION_NUMBER >= 0x020b00
887 /* SubjectPublicKeyInfo. */
891 err
= fn_gnutls_x509_crt_get_pk_algorithm (cert
, &bits
);
892 if (err
>= GNUTLS_E_SUCCESS
)
894 const char *name
= fn_gnutls_pk_algorithm_get_name (err
);
896 res
= nconc2 (res
, list2 (intern (":public-key-algorithm"),
897 build_string (name
)));
899 name
= fn_gnutls_sec_param_get_name (fn_gnutls_pk_bits_to_sec_param
901 res
= nconc2 (res
, list2 (intern (":certificate-security-level"),
902 build_string (name
)));
908 err
= fn_gnutls_x509_crt_get_issuer_unique_id (cert
, NULL
, &buf_size
);
909 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
911 char *buf
= xmalloc (buf_size
);
912 err
= fn_gnutls_x509_crt_get_issuer_unique_id (cert
, buf
, &buf_size
);
913 if (err
>= GNUTLS_E_SUCCESS
)
914 res
= nconc2 (res
, list2 (intern (":issuer-unique-id"),
915 make_string (buf
, buf_size
)));
920 err
= fn_gnutls_x509_crt_get_subject_unique_id (cert
, NULL
, &buf_size
);
921 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
923 char *buf
= xmalloc (buf_size
);
924 err
= fn_gnutls_x509_crt_get_subject_unique_id (cert
, buf
, &buf_size
);
925 if (err
>= GNUTLS_E_SUCCESS
)
926 res
= nconc2 (res
, list2 (intern (":subject-unique-id"),
927 make_string (buf
, buf_size
)));
933 err
= fn_gnutls_x509_crt_get_signature_algorithm (cert
);
934 if (err
>= GNUTLS_E_SUCCESS
)
936 const char *name
= fn_gnutls_sign_get_name (err
);
938 res
= nconc2 (res
, list2 (intern (":signature-algorithm"),
939 build_string (name
)));
944 err
= fn_gnutls_x509_crt_get_key_id (cert
, 0, NULL
, &buf_size
);
945 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
947 void *buf
= xmalloc (buf_size
);
948 err
= fn_gnutls_x509_crt_get_key_id (cert
, 0, buf
, &buf_size
);
949 if (err
>= GNUTLS_E_SUCCESS
)
950 res
= nconc2 (res
, list2 (intern (":public-key-id"),
951 gnutls_hex_string (buf
, buf_size
, "sha1:")));
955 /* Certificate fingerprint. */
957 err
= fn_gnutls_x509_crt_get_fingerprint (cert
, GNUTLS_DIG_SHA1
,
959 if (err
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
961 void *buf
= xmalloc (buf_size
);
962 err
= fn_gnutls_x509_crt_get_fingerprint (cert
, GNUTLS_DIG_SHA1
,
964 if (err
>= GNUTLS_E_SUCCESS
)
965 res
= nconc2 (res
, list2 (intern (":certificate-id"),
966 gnutls_hex_string (buf
, buf_size
, "sha1:")));
973 DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe
, Sgnutls_peer_status_warning_describe
, 1, 1, 0,
974 doc
: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
975 (Lisp_Object status_symbol
)
977 CHECK_SYMBOL (status_symbol
);
979 if (EQ (status_symbol
, intern (":invalid")))
980 return build_string ("certificate could not be verified");
982 if (EQ (status_symbol
, intern (":revoked")))
983 return build_string ("certificate was revoked (CRL)");
985 if (EQ (status_symbol
, intern (":self-signed")))
986 return build_string ("certificate signer was not found (self-signed)");
988 if (EQ (status_symbol
, intern (":not-ca")))
989 return build_string ("certificate signer is not a CA");
991 if (EQ (status_symbol
, intern (":insecure")))
992 return build_string ("certificate was signed with an insecure algorithm");
994 if (EQ (status_symbol
, intern (":not-activated")))
995 return build_string ("certificate is not yet activated");
997 if (EQ (status_symbol
, intern (":expired")))
998 return build_string ("certificate has expired");
1000 if (EQ (status_symbol
, intern (":no-host-match")))
1001 return build_string ("certificate host does not match hostname");
1006 DEFUN ("gnutls-peer-status", Fgnutls_peer_status
, Sgnutls_peer_status
, 1, 1, 0,
1007 doc
: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
1008 The return value is a property list with top-level keys :warnings and
1009 :certificate. The :warnings entry is a list of symbols you can describe with
1010 `gnutls-peer-status-warning-describe'. */)
1013 Lisp_Object warnings
= Qnil
, result
= Qnil
;
1014 unsigned int verification
;
1015 gnutls_session_t state
;
1017 CHECK_PROCESS (proc
);
1019 if (GNUTLS_INITSTAGE (proc
) < GNUTLS_STAGE_INIT
)
1022 /* Then collect any warnings already computed by the handshake. */
1023 verification
= XPROCESS (proc
)->gnutls_peer_verification
;
1025 if (verification
& GNUTLS_CERT_INVALID
)
1026 warnings
= Fcons (intern (":invalid"), warnings
);
1028 if (verification
& GNUTLS_CERT_REVOKED
)
1029 warnings
= Fcons (intern (":revoked"), warnings
);
1031 if (verification
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
1032 warnings
= Fcons (intern (":self-signed"), warnings
);
1034 if (verification
& GNUTLS_CERT_SIGNER_NOT_CA
)
1035 warnings
= Fcons (intern (":not-ca"), warnings
);
1037 if (verification
& GNUTLS_CERT_INSECURE_ALGORITHM
)
1038 warnings
= Fcons (intern (":insecure"), warnings
);
1040 if (verification
& GNUTLS_CERT_NOT_ACTIVATED
)
1041 warnings
= Fcons (intern (":not-activated"), warnings
);
1043 if (verification
& GNUTLS_CERT_EXPIRED
)
1044 warnings
= Fcons (intern (":expired"), warnings
);
1046 if (XPROCESS (proc
)->gnutls_extra_peer_verification
&
1047 CERTIFICATE_NOT_MATCHING
)
1048 warnings
= Fcons (intern (":no-host-match"), warnings
);
1050 if (!NILP (warnings
))
1051 result
= list2 (intern (":warnings"), warnings
);
1053 /* This could get called in the INIT stage, when the certificate is
1055 if (XPROCESS (proc
)->gnutls_certificate
!= NULL
)
1056 result
= nconc2 (result
, list2
1057 (intern (":certificate"),
1058 gnutls_certificate_details (XPROCESS (proc
)->gnutls_certificate
)));
1060 state
= XPROCESS (proc
)->gnutls_state
;
1062 /* Diffie-Hellman prime bits. */
1064 int bits
= fn_gnutls_dh_get_prime_bits (state
);
1066 result
= nconc2 (result
, list2 (intern (":diffie-hellman-prime-bits"),
1067 make_number (bits
)));
1072 (result
, list2 (intern (":key-exchange"),
1073 build_string (fn_gnutls_kx_get_name
1074 (fn_gnutls_kx_get (state
)))));
1076 /* Protocol name. */
1078 (result
, list2 (intern (":protocol"),
1079 build_string (fn_gnutls_protocol_get_name
1080 (fn_gnutls_protocol_get_version (state
)))));
1084 (result
, list2 (intern (":cipher"),
1085 build_string (fn_gnutls_cipher_get_name
1086 (fn_gnutls_cipher_get (state
)))));
1090 (result
, list2 (intern (":mac"),
1091 build_string (fn_gnutls_mac_get_name
1092 (fn_gnutls_mac_get (state
)))));
1098 /* Initialize global GnuTLS state to defaults.
1099 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1100 Return zero on success. */
1102 emacs_gnutls_global_init (void)
1104 int ret
= GNUTLS_E_SUCCESS
;
1106 if (!gnutls_global_initialized
)
1108 fn_gnutls_global_set_mem_functions (xmalloc
, xmalloc
, NULL
,
1110 ret
= fn_gnutls_global_init ();
1112 gnutls_global_initialized
= 1;
1114 return gnutls_make_error (ret
);
1118 gnutls_ip_address_p (char *string
)
1122 while ((c
= *string
++) != 0)
1123 if (! ((c
== '.' || c
== ':' || (c
>= '0' && c
<= '9'))))
1130 /* Deinitialize global GnuTLS state.
1131 See also `gnutls-global-init'. */
1133 emacs_gnutls_global_deinit (void)
1135 if (gnutls_global_initialized
)
1136 gnutls_global_deinit ();
1138 gnutls_global_initialized
= 0;
1140 return gnutls_make_error (GNUTLS_E_SUCCESS
);
1144 DEFUN ("gnutls-boot", Fgnutls_boot
, Sgnutls_boot
, 3, 3, 0,
1145 doc
: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1146 Currently only client mode is supported. Return a success/failure
1147 value you can check with `gnutls-errorp'.
1149 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
1150 PROPLIST is a property list with the following keys:
1152 :hostname is a string naming the remote host.
1154 :priority is a GnuTLS priority string, defaults to "NORMAL".
1156 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
1158 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
1160 :keylist is an alist of PEM-encoded key files and PEM-encoded
1161 certificates for `gnutls-x509pki'.
1163 :callbacks is an alist of callback functions, see below.
1165 :loglevel is the debug level requested from GnuTLS, try 4.
1167 :verify-flags is a bitset as per GnuTLS'
1168 gnutls_certificate_set_verify_flags.
1170 :verify-hostname-error is ignored. Pass :hostname in :verify-error
1173 :verify-error is a list of symbols to express verification checks or
1174 `t' to do all checks. Currently it can contain `:trustfiles' and
1175 `:hostname' to verify the certificate or the hostname respectively.
1177 :min-prime-bits is the minimum accepted number of bits the client will
1178 accept in Diffie-Hellman key exchange.
1180 The debug level will be set for this process AND globally for GnuTLS.
1181 So if you set it higher or lower at any point, it affects global
1184 Note that the priority is set on the client. The server does not use
1185 the protocols's priority except for disabling protocols that were not
1188 Processes must be initialized with this function before other GnuTLS
1189 functions are used. This function allocates resources which can only
1190 be deallocated by calling `gnutls-deinit' or by calling it again.
1192 The callbacks alist can have a `verify' key, associated with a
1193 verification function (UNUSED).
1195 Each authentication type may need additional information in order to
1196 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
1197 one trustfile (usually a CA bundle). */)
1198 (Lisp_Object proc
, Lisp_Object type
, Lisp_Object proplist
)
1200 int ret
= GNUTLS_E_SUCCESS
;
1201 int max_log_level
= 0;
1202 bool verify_error_all
= 0;
1204 gnutls_session_t state
;
1205 gnutls_certificate_credentials_t x509_cred
= NULL
;
1206 gnutls_anon_client_credentials_t anon_cred
= NULL
;
1207 Lisp_Object global_init
;
1208 char const *priority_string_ptr
= "NORMAL"; /* default priority string. */
1209 unsigned int peer_verification
;
1212 /* Placeholders for the property list elements. */
1213 Lisp_Object priority_string
;
1214 Lisp_Object trustfiles
;
1215 Lisp_Object crlfiles
;
1216 Lisp_Object keylist
;
1217 /* Lisp_Object callbacks; */
1218 Lisp_Object loglevel
;
1219 Lisp_Object hostname
;
1220 Lisp_Object verify_error
;
1221 Lisp_Object prime_bits
;
1222 Lisp_Object warnings
;
1224 CHECK_PROCESS (proc
);
1225 CHECK_SYMBOL (type
);
1226 CHECK_LIST (proplist
);
1228 if (NILP (Fgnutls_available_p ()))
1229 error ("GnuTLS not available");
1231 if (!EQ (type
, Qgnutls_x509pki
) && !EQ (type
, Qgnutls_anon
))
1232 error ("Invalid GnuTLS credential type");
1234 hostname
= Fplist_get (proplist
, QCgnutls_bootprop_hostname
);
1235 priority_string
= Fplist_get (proplist
, QCgnutls_bootprop_priority
);
1236 trustfiles
= Fplist_get (proplist
, QCgnutls_bootprop_trustfiles
);
1237 keylist
= Fplist_get (proplist
, QCgnutls_bootprop_keylist
);
1238 crlfiles
= Fplist_get (proplist
, QCgnutls_bootprop_crlfiles
);
1239 loglevel
= Fplist_get (proplist
, QCgnutls_bootprop_loglevel
);
1240 verify_error
= Fplist_get (proplist
, QCgnutls_bootprop_verify_error
);
1241 prime_bits
= Fplist_get (proplist
, QCgnutls_bootprop_min_prime_bits
);
1243 if (EQ (verify_error
, Qt
))
1245 verify_error_all
= 1;
1247 else if (NILP (Flistp (verify_error
)))
1249 error ("gnutls-boot: invalid :verify_error parameter (not a list)");
1252 if (!STRINGP (hostname
))
1253 error ("gnutls-boot: invalid :hostname parameter (not a string)");
1254 c_hostname
= SSDATA (hostname
);
1256 state
= XPROCESS (proc
)->gnutls_state
;
1258 if (TYPE_RANGED_INTEGERP (int, loglevel
))
1260 fn_gnutls_global_set_log_function (gnutls_log_function
);
1262 fn_gnutls_global_set_audit_log_function (gnutls_audit_log_function
);
1264 fn_gnutls_global_set_log_level (XINT (loglevel
));
1265 max_log_level
= XINT (loglevel
);
1266 XPROCESS (proc
)->gnutls_log_level
= max_log_level
;
1269 GNUTLS_LOG2 (1, max_log_level
, "connecting to host:", c_hostname
);
1271 /* Always initialize globals. */
1272 global_init
= emacs_gnutls_global_init ();
1273 if (! NILP (Fgnutls_errorp (global_init
)))
1276 /* Before allocating new credentials, deallocate any credentials
1277 that PROC might already have. */
1278 emacs_gnutls_deinit (proc
);
1280 /* Mark PROC as a GnuTLS process. */
1281 XPROCESS (proc
)->gnutls_state
= NULL
;
1282 XPROCESS (proc
)->gnutls_x509_cred
= NULL
;
1283 XPROCESS (proc
)->gnutls_anon_cred
= NULL
;
1284 pset_gnutls_cred_type (XPROCESS (proc
), type
);
1285 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_EMPTY
;
1287 GNUTLS_LOG (1, max_log_level
, "allocating credentials");
1288 if (EQ (type
, Qgnutls_x509pki
))
1290 Lisp_Object verify_flags
;
1291 unsigned int gnutls_verify_flags
= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
;
1293 GNUTLS_LOG (2, max_log_level
, "allocating x509 credentials");
1294 fn_gnutls_certificate_allocate_credentials (&x509_cred
);
1295 XPROCESS (proc
)->gnutls_x509_cred
= x509_cred
;
1297 verify_flags
= Fplist_get (proplist
, QCgnutls_bootprop_verify_flags
);
1298 if (NUMBERP (verify_flags
))
1300 gnutls_verify_flags
= XINT (verify_flags
);
1301 GNUTLS_LOG (2, max_log_level
, "setting verification flags");
1303 else if (NILP (verify_flags
))
1304 GNUTLS_LOG (2, max_log_level
, "using default verification flags");
1306 GNUTLS_LOG (2, max_log_level
, "ignoring invalid verify-flags");
1308 fn_gnutls_certificate_set_verify_flags (x509_cred
, gnutls_verify_flags
);
1310 else /* Qgnutls_anon: */
1312 GNUTLS_LOG (2, max_log_level
, "allocating anon credentials");
1313 fn_gnutls_anon_allocate_client_credentials (&anon_cred
);
1314 XPROCESS (proc
)->gnutls_anon_cred
= anon_cred
;
1317 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_ALLOC
;
1319 if (EQ (type
, Qgnutls_x509pki
))
1321 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
1322 int file_format
= GNUTLS_X509_FMT_PEM
;
1325 #if GNUTLS_VERSION_MAJOR + \
1326 (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
1327 ret
= fn_gnutls_certificate_set_x509_system_trust (x509_cred
);
1328 if (ret
< GNUTLS_E_SUCCESS
)
1329 GNUTLS_LOG2i (4, max_log_level
,
1330 "setting system trust failed with code ", ret
);
1333 for (tail
= trustfiles
; CONSP (tail
); tail
= XCDR (tail
))
1335 Lisp_Object trustfile
= XCAR (tail
);
1336 if (STRINGP (trustfile
))
1338 GNUTLS_LOG2 (1, max_log_level
, "setting the trustfile: ",
1339 SSDATA (trustfile
));
1340 trustfile
= ENCODE_FILE (trustfile
);
1342 /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
1343 file names on Windows, we need to re-encode the file
1344 name using the current ANSI codepage. */
1345 trustfile
= ansi_encode_filename (trustfile
);
1347 ret
= fn_gnutls_certificate_set_x509_trust_file
1352 if (ret
< GNUTLS_E_SUCCESS
)
1353 return gnutls_make_error (ret
);
1357 emacs_gnutls_deinit (proc
);
1358 error ("Invalid trustfile");
1362 for (tail
= crlfiles
; CONSP (tail
); tail
= XCDR (tail
))
1364 Lisp_Object crlfile
= XCAR (tail
);
1365 if (STRINGP (crlfile
))
1367 GNUTLS_LOG2 (1, max_log_level
, "setting the CRL file: ",
1369 crlfile
= ENCODE_FILE (crlfile
);
1371 crlfile
= ansi_encode_filename (crlfile
);
1373 ret
= fn_gnutls_certificate_set_x509_crl_file
1374 (x509_cred
, SSDATA (crlfile
), file_format
);
1376 if (ret
< GNUTLS_E_SUCCESS
)
1377 return gnutls_make_error (ret
);
1381 emacs_gnutls_deinit (proc
);
1382 error ("Invalid CRL file");
1386 for (tail
= keylist
; CONSP (tail
); tail
= XCDR (tail
))
1388 Lisp_Object keyfile
= Fcar (XCAR (tail
));
1389 Lisp_Object certfile
= Fcar (Fcdr (XCAR (tail
)));
1390 if (STRINGP (keyfile
) && STRINGP (certfile
))
1392 GNUTLS_LOG2 (1, max_log_level
, "setting the client key file: ",
1394 GNUTLS_LOG2 (1, max_log_level
, "setting the client cert file: ",
1396 keyfile
= ENCODE_FILE (keyfile
);
1397 certfile
= ENCODE_FILE (certfile
);
1399 keyfile
= ansi_encode_filename (keyfile
);
1400 certfile
= ansi_encode_filename (certfile
);
1402 ret
= fn_gnutls_certificate_set_x509_key_file
1403 (x509_cred
, SSDATA (certfile
), SSDATA (keyfile
), file_format
);
1405 if (ret
< GNUTLS_E_SUCCESS
)
1406 return gnutls_make_error (ret
);
1410 emacs_gnutls_deinit (proc
);
1411 error (STRINGP (keyfile
) ? "Invalid client cert file"
1412 : "Invalid client key file");
1417 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_FILES
;
1418 GNUTLS_LOG (1, max_log_level
, "gnutls callbacks");
1419 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CALLBACKS
;
1421 /* Call gnutls_init here: */
1423 GNUTLS_LOG (1, max_log_level
, "gnutls_init");
1424 ret
= fn_gnutls_init (&state
, GNUTLS_CLIENT
);
1425 XPROCESS (proc
)->gnutls_state
= state
;
1426 if (ret
< GNUTLS_E_SUCCESS
)
1427 return gnutls_make_error (ret
);
1428 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
;
1430 if (STRINGP (priority_string
))
1432 priority_string_ptr
= SSDATA (priority_string
);
1433 GNUTLS_LOG2 (1, max_log_level
, "got non-default priority string:",
1434 priority_string_ptr
);
1438 GNUTLS_LOG2 (1, max_log_level
, "using default priority string:",
1439 priority_string_ptr
);
1442 GNUTLS_LOG (1, max_log_level
, "setting the priority string");
1443 ret
= fn_gnutls_priority_set_direct (state
,
1444 priority_string_ptr
,
1446 if (ret
< GNUTLS_E_SUCCESS
)
1447 return gnutls_make_error (ret
);
1449 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_PRIORITY
;
1451 if (INTEGERP (prime_bits
))
1452 fn_gnutls_dh_set_prime_bits (state
, XUINT (prime_bits
));
1454 ret
= EQ (type
, Qgnutls_x509pki
)
1455 ? fn_gnutls_credentials_set (state
, GNUTLS_CRD_CERTIFICATE
, x509_cred
)
1456 : fn_gnutls_credentials_set (state
, GNUTLS_CRD_ANON
, anon_cred
);
1457 if (ret
< GNUTLS_E_SUCCESS
)
1458 return gnutls_make_error (ret
);
1460 if (!gnutls_ip_address_p (c_hostname
))
1462 ret
= fn_gnutls_server_name_set (state
, GNUTLS_NAME_DNS
, c_hostname
,
1463 strlen (c_hostname
));
1464 if (ret
< GNUTLS_E_SUCCESS
)
1465 return gnutls_make_error (ret
);
1468 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_SET
;
1469 ret
= emacs_gnutls_handshake (XPROCESS (proc
));
1470 if (ret
< GNUTLS_E_SUCCESS
)
1471 return gnutls_make_error (ret
);
1473 /* Now verify the peer, following
1474 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1475 The peer should present at least one certificate in the chain; do a
1476 check of the certificate's hostname with
1477 gnutls_x509_crt_check_hostname against :hostname. */
1479 ret
= fn_gnutls_certificate_verify_peers2 (state
, &peer_verification
);
1480 if (ret
< GNUTLS_E_SUCCESS
)
1481 return gnutls_make_error (ret
);
1483 XPROCESS (proc
)->gnutls_peer_verification
= peer_verification
;
1485 warnings
= Fplist_get (Fgnutls_peer_status (proc
), intern (":warnings"));
1486 if (!NILP (warnings
))
1489 for (tail
= warnings
; CONSP (tail
); tail
= XCDR (tail
))
1491 Lisp_Object warning
= XCAR (tail
);
1492 Lisp_Object message
= Fgnutls_peer_status_warning_describe (warning
);
1493 if (!NILP (message
))
1494 GNUTLS_LOG2 (1, max_log_level
, "verification:", SSDATA (message
));
1498 if (peer_verification
!= 0)
1500 if (verify_error_all
1501 || !NILP (Fmember (QCgnutls_bootprop_trustfiles
, verify_error
)))
1503 emacs_gnutls_deinit (proc
);
1504 error ("Certificate validation failed %s, verification code %d",
1505 c_hostname
, peer_verification
);
1509 GNUTLS_LOG2 (1, max_log_level
, "certificate validation failed:",
1514 /* Up to here the process is the same for X.509 certificates and
1515 OpenPGP keys. From now on X.509 certificates are assumed. This
1516 can be easily extended to work with openpgp keys as well. */
1517 if (fn_gnutls_certificate_type_get (state
) == GNUTLS_CRT_X509
)
1519 gnutls_x509_crt_t gnutls_verify_cert
;
1520 const gnutls_datum_t
*gnutls_verify_cert_list
;
1521 unsigned int gnutls_verify_cert_list_size
;
1523 ret
= fn_gnutls_x509_crt_init (&gnutls_verify_cert
);
1524 if (ret
< GNUTLS_E_SUCCESS
)
1525 return gnutls_make_error (ret
);
1527 gnutls_verify_cert_list
=
1528 fn_gnutls_certificate_get_peers (state
, &gnutls_verify_cert_list_size
);
1530 if (gnutls_verify_cert_list
== NULL
)
1532 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1533 emacs_gnutls_deinit (proc
);
1534 error ("No x509 certificate was found\n");
1537 /* We only check the first certificate in the given chain. */
1538 ret
= fn_gnutls_x509_crt_import (gnutls_verify_cert
,
1539 &gnutls_verify_cert_list
[0],
1540 GNUTLS_X509_FMT_DER
);
1542 if (ret
< GNUTLS_E_SUCCESS
)
1544 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1545 return gnutls_make_error (ret
);
1548 XPROCESS (proc
)->gnutls_certificate
= gnutls_verify_cert
;
1550 if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert
, c_hostname
))
1552 XPROCESS (proc
)->gnutls_extra_peer_verification
|=
1553 CERTIFICATE_NOT_MATCHING
;
1554 if (verify_error_all
1555 || !NILP (Fmember (QCgnutls_bootprop_hostname
, verify_error
)))
1557 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1558 emacs_gnutls_deinit (proc
);
1559 error ("The x509 certificate does not match \"%s\"", c_hostname
);
1563 GNUTLS_LOG2 (1, max_log_level
, "x509 certificate does not match:",
1569 /* Set this flag only if the whole initialization succeeded. */
1570 XPROCESS (proc
)->gnutls_p
= 1;
1572 return gnutls_make_error (ret
);
1575 DEFUN ("gnutls-bye", Fgnutls_bye
,
1576 Sgnutls_bye
, 2, 2, 0,
1577 doc
: /* Terminate current GnuTLS connection for process PROC.
1578 The connection should have been initiated using `gnutls-handshake'.
1580 If CONT is not nil the TLS connection gets terminated and further
1581 receives and sends will be disallowed. If the return value is zero you
1582 may continue using the connection. If CONT is nil, GnuTLS actually
1583 sends an alert containing a close request and waits for the peer to
1584 reply with the same message. In order to reuse the connection you
1585 should wait for an EOF from the peer.
1587 This function may also return `gnutls-e-again', or
1588 `gnutls-e-interrupted'. */)
1589 (Lisp_Object proc
, Lisp_Object cont
)
1591 gnutls_session_t state
;
1594 CHECK_PROCESS (proc
);
1596 state
= XPROCESS (proc
)->gnutls_state
;
1598 fn_gnutls_x509_crt_deinit (XPROCESS (proc
)->gnutls_certificate
);
1600 ret
= fn_gnutls_bye (state
,
1601 NILP (cont
) ? GNUTLS_SHUT_RDWR
: GNUTLS_SHUT_WR
);
1603 return gnutls_make_error (ret
);
1606 #endif /* HAVE_GNUTLS */
1608 DEFUN ("gnutls-available-p", Fgnutls_available_p
, Sgnutls_available_p
, 0, 0, 0,
1609 doc
: /* Return t if GnuTLS is available in this instance of Emacs. */)
1614 Lisp_Object found
= Fassq (Qgnutls_dll
, Vlibrary_cache
);
1616 return XCDR (found
);
1620 status
= init_gnutls_functions () ? Qt
: Qnil
;
1621 Vlibrary_cache
= Fcons (Fcons (Qgnutls_dll
, status
), Vlibrary_cache
);
1624 # else /* !WINDOWSNT */
1626 # endif /* !WINDOWSNT */
1627 #else /* !HAVE_GNUTLS */
1629 #endif /* !HAVE_GNUTLS */
1633 syms_of_gnutls (void)
1636 gnutls_global_initialized
= 0;
1638 DEFSYM (Qgnutls_dll
, "gnutls");
1639 DEFSYM (Qgnutls_code
, "gnutls-code");
1640 DEFSYM (Qgnutls_anon
, "gnutls-anon");
1641 DEFSYM (Qgnutls_x509pki
, "gnutls-x509pki");
1642 DEFSYM (QCgnutls_bootprop_hostname
, ":hostname");
1643 DEFSYM (QCgnutls_bootprop_priority
, ":priority");
1644 DEFSYM (QCgnutls_bootprop_trustfiles
, ":trustfiles");
1645 DEFSYM (QCgnutls_bootprop_keylist
, ":keylist");
1646 DEFSYM (QCgnutls_bootprop_crlfiles
, ":crlfiles");
1647 DEFSYM (QCgnutls_bootprop_callbacks
, ":callbacks");
1648 DEFSYM (QCgnutls_bootprop_callbacks_verify
, "verify");
1649 DEFSYM (QCgnutls_bootprop_min_prime_bits
, ":min-prime-bits");
1650 DEFSYM (QCgnutls_bootprop_loglevel
, ":loglevel");
1651 DEFSYM (QCgnutls_bootprop_verify_flags
, ":verify-flags");
1652 DEFSYM (QCgnutls_bootprop_verify_error
, ":verify-error");
1654 DEFSYM (Qgnutls_e_interrupted
, "gnutls-e-interrupted");
1655 Fput (Qgnutls_e_interrupted
, Qgnutls_code
,
1656 make_number (GNUTLS_E_INTERRUPTED
));
1658 DEFSYM (Qgnutls_e_again
, "gnutls-e-again");
1659 Fput (Qgnutls_e_again
, Qgnutls_code
,
1660 make_number (GNUTLS_E_AGAIN
));
1662 DEFSYM (Qgnutls_e_invalid_session
, "gnutls-e-invalid-session");
1663 Fput (Qgnutls_e_invalid_session
, Qgnutls_code
,
1664 make_number (GNUTLS_E_INVALID_SESSION
));
1666 DEFSYM (Qgnutls_e_not_ready_for_handshake
, "gnutls-e-not-ready-for-handshake");
1667 Fput (Qgnutls_e_not_ready_for_handshake
, Qgnutls_code
,
1668 make_number (GNUTLS_E_APPLICATION_ERROR_MIN
));
1670 defsubr (&Sgnutls_get_initstage
);
1671 defsubr (&Sgnutls_errorp
);
1672 defsubr (&Sgnutls_error_fatalp
);
1673 defsubr (&Sgnutls_error_string
);
1674 defsubr (&Sgnutls_boot
);
1675 defsubr (&Sgnutls_deinit
);
1676 defsubr (&Sgnutls_bye
);
1677 defsubr (&Sgnutls_peer_status
);
1678 defsubr (&Sgnutls_peer_status_warning_describe
);
1680 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level
,
1681 doc
: /* Logging level used by the GnuTLS functions.
1682 Set this larger than 0 to get debug output in the *Messages* buffer.
1683 1 is for important messages, 2 is for debug data, and higher numbers
1684 are as per the GnuTLS logging conventions. */);
1685 global_gnutls_log_level
= 0;
1687 #endif /* HAVE_GNUTLS */
1689 defsubr (&Sgnutls_available_p
);