Subject: Restore correct Gnus newsgroup name after sending message
[emacs.git] / src / gnutls.c
blobd0d7f2dfc84217f3f0592a5a7b09ca470aaa9ac2
1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2017 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 (at
9 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/>. */
19 #include <config.h>
20 #include <errno.h>
21 #include <stdio.h>
23 #include "lisp.h"
24 #include "process.h"
25 #include "gnutls.h"
26 #include "coding.h"
28 #ifdef HAVE_GNUTLS
30 #ifdef WINDOWSNT
31 #include <windows.h>
32 #include "w32.h"
33 #endif
35 static bool emacs_gnutls_handle_error (gnutls_session_t, int);
37 static bool gnutls_global_initialized;
39 static void gnutls_log_function (int, const char *);
40 static void gnutls_log_function2 (int, const char *, const char *);
41 #ifdef HAVE_GNUTLS3
42 static void gnutls_audit_log_function (gnutls_session_t, const char *);
43 #endif
45 enum extra_peer_verification
47 CERTIFICATE_NOT_MATCHING = 2
51 #ifdef WINDOWSNT
53 DEF_DLL_FN (gnutls_alert_description_t, gnutls_alert_get,
54 (gnutls_session_t));
55 DEF_DLL_FN (const char *, gnutls_alert_get_name,
56 (gnutls_alert_description_t));
57 DEF_DLL_FN (int, gnutls_anon_allocate_client_credentials,
58 (gnutls_anon_client_credentials_t *));
59 DEF_DLL_FN (void, gnutls_anon_free_client_credentials,
60 (gnutls_anon_client_credentials_t));
61 DEF_DLL_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
62 DEF_DLL_FN (int, gnutls_certificate_allocate_credentials,
63 (gnutls_certificate_credentials_t *));
64 DEF_DLL_FN (void, gnutls_certificate_free_credentials,
65 (gnutls_certificate_credentials_t));
66 DEF_DLL_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
67 (gnutls_session_t, unsigned int *));
68 DEF_DLL_FN (void, gnutls_certificate_set_verify_flags,
69 (gnutls_certificate_credentials_t, unsigned int));
70 DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
71 (gnutls_certificate_credentials_t, const char *,
72 gnutls_x509_crt_fmt_t));
73 DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
74 (gnutls_certificate_credentials_t, const char *, const char *,
75 gnutls_x509_crt_fmt_t));
76 # if ((GNUTLS_VERSION_MAJOR \
77 + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
78 > 3)
79 DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
80 (gnutls_certificate_credentials_t));
81 # endif
82 DEF_DLL_FN (int, gnutls_certificate_set_x509_trust_file,
83 (gnutls_certificate_credentials_t, const char *,
84 gnutls_x509_crt_fmt_t));
85 DEF_DLL_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
86 (gnutls_session_t));
87 DEF_DLL_FN (int, gnutls_certificate_verify_peers2,
88 (gnutls_session_t, unsigned int *));
89 DEF_DLL_FN (int, gnutls_credentials_set,
90 (gnutls_session_t, gnutls_credentials_type_t, void *));
91 DEF_DLL_FN (void, gnutls_deinit, (gnutls_session_t));
92 DEF_DLL_FN (void, gnutls_dh_set_prime_bits,
93 (gnutls_session_t, unsigned int));
94 DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
95 DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
96 DEF_DLL_FN (int, gnutls_global_init, (void));
97 DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
98 # ifdef HAVE_GNUTLS3
99 DEF_DLL_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
100 # endif
101 DEF_DLL_FN (void, gnutls_global_set_log_level, (int));
102 DEF_DLL_FN (int, gnutls_handshake, (gnutls_session_t));
103 DEF_DLL_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
104 DEF_DLL_FN (int, gnutls_priority_set_direct,
105 (gnutls_session_t, const char *, const char **));
106 DEF_DLL_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
107 DEF_DLL_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
108 DEF_DLL_FN (ssize_t, gnutls_record_send,
109 (gnutls_session_t, const void *, size_t));
110 DEF_DLL_FN (const char *, gnutls_strerror, (int));
111 DEF_DLL_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
112 DEF_DLL_FN (void, gnutls_transport_set_ptr2,
113 (gnutls_session_t, gnutls_transport_ptr_t,
114 gnutls_transport_ptr_t));
115 DEF_DLL_FN (void, gnutls_transport_set_pull_function,
116 (gnutls_session_t, gnutls_pull_func));
117 DEF_DLL_FN (void, gnutls_transport_set_push_function,
118 (gnutls_session_t, gnutls_push_func));
119 DEF_DLL_FN (int, gnutls_x509_crt_check_hostname,
120 (gnutls_x509_crt_t, const char *));
121 DEF_DLL_FN (int, gnutls_x509_crt_check_issuer,
122 (gnutls_x509_crt_t, gnutls_x509_crt_t));
123 DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
124 DEF_DLL_FN (int, gnutls_x509_crt_import,
125 (gnutls_x509_crt_t, const gnutls_datum_t *,
126 gnutls_x509_crt_fmt_t));
127 DEF_DLL_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
128 DEF_DLL_FN (int, gnutls_x509_crt_get_fingerprint,
129 (gnutls_x509_crt_t,
130 gnutls_digest_algorithm_t, void *, size_t *));
131 DEF_DLL_FN (int, gnutls_x509_crt_get_version,
132 (gnutls_x509_crt_t));
133 DEF_DLL_FN (int, gnutls_x509_crt_get_serial,
134 (gnutls_x509_crt_t, void *, size_t *));
135 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_dn,
136 (gnutls_x509_crt_t, char *, size_t *));
137 DEF_DLL_FN (time_t, gnutls_x509_crt_get_activation_time,
138 (gnutls_x509_crt_t));
139 DEF_DLL_FN (time_t, gnutls_x509_crt_get_expiration_time,
140 (gnutls_x509_crt_t));
141 DEF_DLL_FN (int, gnutls_x509_crt_get_dn,
142 (gnutls_x509_crt_t, char *, size_t *));
143 DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm,
144 (gnutls_x509_crt_t, unsigned int *));
145 DEF_DLL_FN (const char*, gnutls_pk_algorithm_get_name,
146 (gnutls_pk_algorithm_t));
147 DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param,
148 (gnutls_pk_algorithm_t, unsigned int));
149 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_unique_id,
150 (gnutls_x509_crt_t, char *, size_t *));
151 DEF_DLL_FN (int, gnutls_x509_crt_get_subject_unique_id,
152 (gnutls_x509_crt_t, char *, size_t *));
153 DEF_DLL_FN (int, gnutls_x509_crt_get_signature_algorithm,
154 (gnutls_x509_crt_t));
155 DEF_DLL_FN (int, gnutls_x509_crt_get_key_id,
156 (gnutls_x509_crt_t, unsigned int, unsigned char *, size_t *_size));
157 DEF_DLL_FN (const char*, gnutls_sec_param_get_name, (gnutls_sec_param_t));
158 DEF_DLL_FN (const char*, gnutls_sign_get_name, (gnutls_sign_algorithm_t));
159 DEF_DLL_FN (int, gnutls_server_name_set,
160 (gnutls_session_t, gnutls_server_name_type_t,
161 const void *, size_t));
162 DEF_DLL_FN (gnutls_kx_algorithm_t, gnutls_kx_get, (gnutls_session_t));
163 DEF_DLL_FN (const char*, gnutls_kx_get_name, (gnutls_kx_algorithm_t));
164 DEF_DLL_FN (gnutls_protocol_t, gnutls_protocol_get_version,
165 (gnutls_session_t));
166 DEF_DLL_FN (const char*, gnutls_protocol_get_name, (gnutls_protocol_t));
167 DEF_DLL_FN (gnutls_cipher_algorithm_t, gnutls_cipher_get,
168 (gnutls_session_t));
169 DEF_DLL_FN (const char*, gnutls_cipher_get_name,
170 (gnutls_cipher_algorithm_t));
171 DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
172 DEF_DLL_FN (const char*, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
175 static bool
176 init_gnutls_functions (void)
178 HMODULE library;
179 int max_log_level = 1;
181 if (!(library = w32_delayed_load (Qgnutls)))
183 GNUTLS_LOG (1, max_log_level, "GnuTLS library not found");
184 return 0;
187 LOAD_DLL_FN (library, gnutls_alert_get);
188 LOAD_DLL_FN (library, gnutls_alert_get_name);
189 LOAD_DLL_FN (library, gnutls_anon_allocate_client_credentials);
190 LOAD_DLL_FN (library, gnutls_anon_free_client_credentials);
191 LOAD_DLL_FN (library, gnutls_bye);
192 LOAD_DLL_FN (library, gnutls_certificate_allocate_credentials);
193 LOAD_DLL_FN (library, gnutls_certificate_free_credentials);
194 LOAD_DLL_FN (library, gnutls_certificate_get_peers);
195 LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
196 LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
197 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
198 # if ((GNUTLS_VERSION_MAJOR \
199 + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
200 > 3)
201 LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
202 # endif
203 LOAD_DLL_FN (library, gnutls_certificate_set_x509_trust_file);
204 LOAD_DLL_FN (library, gnutls_certificate_type_get);
205 LOAD_DLL_FN (library, gnutls_certificate_verify_peers2);
206 LOAD_DLL_FN (library, gnutls_credentials_set);
207 LOAD_DLL_FN (library, gnutls_deinit);
208 LOAD_DLL_FN (library, gnutls_dh_set_prime_bits);
209 LOAD_DLL_FN (library, gnutls_dh_get_prime_bits);
210 LOAD_DLL_FN (library, gnutls_error_is_fatal);
211 LOAD_DLL_FN (library, gnutls_global_init);
212 LOAD_DLL_FN (library, gnutls_global_set_log_function);
213 # ifdef HAVE_GNUTLS3
214 LOAD_DLL_FN (library, gnutls_global_set_audit_log_function);
215 # endif
216 LOAD_DLL_FN (library, gnutls_global_set_log_level);
217 LOAD_DLL_FN (library, gnutls_handshake);
218 LOAD_DLL_FN (library, gnutls_init);
219 LOAD_DLL_FN (library, gnutls_priority_set_direct);
220 LOAD_DLL_FN (library, gnutls_record_check_pending);
221 LOAD_DLL_FN (library, gnutls_record_recv);
222 LOAD_DLL_FN (library, gnutls_record_send);
223 LOAD_DLL_FN (library, gnutls_strerror);
224 LOAD_DLL_FN (library, gnutls_transport_set_errno);
225 LOAD_DLL_FN (library, gnutls_transport_set_ptr2);
226 LOAD_DLL_FN (library, gnutls_transport_set_pull_function);
227 LOAD_DLL_FN (library, gnutls_transport_set_push_function);
228 LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname);
229 LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer);
230 LOAD_DLL_FN (library, gnutls_x509_crt_deinit);
231 LOAD_DLL_FN (library, gnutls_x509_crt_import);
232 LOAD_DLL_FN (library, gnutls_x509_crt_init);
233 LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint);
234 LOAD_DLL_FN (library, gnutls_x509_crt_get_version);
235 LOAD_DLL_FN (library, gnutls_x509_crt_get_serial);
236 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_dn);
237 LOAD_DLL_FN (library, gnutls_x509_crt_get_activation_time);
238 LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time);
239 LOAD_DLL_FN (library, gnutls_x509_crt_get_dn);
240 LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm);
241 LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name);
242 LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param);
243 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id);
244 LOAD_DLL_FN (library, gnutls_x509_crt_get_subject_unique_id);
245 LOAD_DLL_FN (library, gnutls_x509_crt_get_signature_algorithm);
246 LOAD_DLL_FN (library, gnutls_x509_crt_get_key_id);
247 LOAD_DLL_FN (library, gnutls_sec_param_get_name);
248 LOAD_DLL_FN (library, gnutls_sign_get_name);
249 LOAD_DLL_FN (library, gnutls_server_name_set);
250 LOAD_DLL_FN (library, gnutls_kx_get);
251 LOAD_DLL_FN (library, gnutls_kx_get_name);
252 LOAD_DLL_FN (library, gnutls_protocol_get_version);
253 LOAD_DLL_FN (library, gnutls_protocol_get_name);
254 LOAD_DLL_FN (library, gnutls_cipher_get);
255 LOAD_DLL_FN (library, gnutls_cipher_get_name);
256 LOAD_DLL_FN (library, gnutls_mac_get);
257 LOAD_DLL_FN (library, gnutls_mac_get_name);
259 max_log_level = global_gnutls_log_level;
262 Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from));
263 GNUTLS_LOG2 (1, max_log_level, "GnuTLS library loaded:",
264 STRINGP (name) ? (const char *) SDATA (name) : "unknown");
267 return 1;
270 # define gnutls_alert_get fn_gnutls_alert_get
271 # define gnutls_alert_get_name fn_gnutls_alert_get_name
272 # define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
273 # define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
274 # define gnutls_bye fn_gnutls_bye
275 # define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
276 # define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
277 # define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
278 # define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
279 # define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
280 # define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
281 # define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
282 # define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
283 # define gnutls_certificate_type_get fn_gnutls_certificate_type_get
284 # define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
285 # define gnutls_cipher_get fn_gnutls_cipher_get
286 # define gnutls_cipher_get_name fn_gnutls_cipher_get_name
287 # define gnutls_credentials_set fn_gnutls_credentials_set
288 # define gnutls_deinit fn_gnutls_deinit
289 # define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
290 # define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
291 # define gnutls_error_is_fatal fn_gnutls_error_is_fatal
292 # define gnutls_global_init fn_gnutls_global_init
293 # define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
294 # define gnutls_global_set_log_function fn_gnutls_global_set_log_function
295 # define gnutls_global_set_log_level fn_gnutls_global_set_log_level
296 # define gnutls_handshake fn_gnutls_handshake
297 # define gnutls_init fn_gnutls_init
298 # define gnutls_kx_get fn_gnutls_kx_get
299 # define gnutls_kx_get_name fn_gnutls_kx_get_name
300 # define gnutls_mac_get fn_gnutls_mac_get
301 # define gnutls_mac_get_name fn_gnutls_mac_get_name
302 # define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
303 # define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
304 # define gnutls_priority_set_direct fn_gnutls_priority_set_direct
305 # define gnutls_protocol_get_name fn_gnutls_protocol_get_name
306 # define gnutls_protocol_get_version fn_gnutls_protocol_get_version
307 # define gnutls_record_check_pending fn_gnutls_record_check_pending
308 # define gnutls_record_recv fn_gnutls_record_recv
309 # define gnutls_record_send fn_gnutls_record_send
310 # define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
311 # define gnutls_server_name_set fn_gnutls_server_name_set
312 # define gnutls_sign_get_name fn_gnutls_sign_get_name
313 # define gnutls_strerror fn_gnutls_strerror
314 # define gnutls_transport_set_errno fn_gnutls_transport_set_errno
315 # define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
316 # define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
317 # define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
318 # define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
319 # define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
320 # define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
321 # define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
322 # define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
323 # define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
324 # define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
325 # define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
326 # define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
327 # define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
328 # define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
329 # define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
330 # define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
331 # define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
332 # define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
333 # define gnutls_x509_crt_import fn_gnutls_x509_crt_import
334 # define gnutls_x509_crt_init fn_gnutls_x509_crt_init
336 #endif
339 /* Report memory exhaustion if ERR is an out-of-memory indication. */
340 static void
341 check_memory_full (int err)
343 /* When GnuTLS exhausts memory, it doesn't say how much memory it
344 asked for, so tell the Emacs allocator that GnuTLS asked for no
345 bytes. This isn't accurate, but it's good enough. */
346 if (err == GNUTLS_E_MEMORY_ERROR)
347 memory_full (0);
350 #ifdef HAVE_GNUTLS3
351 /* Log a simple audit message. */
352 static void
353 gnutls_audit_log_function (gnutls_session_t session, const char *string)
355 if (global_gnutls_log_level >= 1)
357 message ("gnutls.c: [audit] %s", string);
360 #endif
362 /* Log a simple message. */
363 static void
364 gnutls_log_function (int level, const char *string)
366 message ("gnutls.c: [%d] %s", level, string);
369 /* Log a message and a string. */
370 static void
371 gnutls_log_function2 (int level, const char *string, const char *extra)
373 message ("gnutls.c: [%d] %s %s", level, string, extra);
377 gnutls_try_handshake (struct Lisp_Process *proc)
379 gnutls_session_t state = proc->gnutls_state;
380 int ret;
381 bool non_blocking = proc->is_non_blocking_client;
383 if (proc->gnutls_complete_negotiation_p)
384 non_blocking = false;
386 if (non_blocking)
387 proc->gnutls_p = true;
391 ret = gnutls_handshake (state);
392 emacs_gnutls_handle_error (state, ret);
393 maybe_quit ();
395 while (ret < 0
396 && gnutls_error_is_fatal (ret) == 0
397 && ! non_blocking);
399 proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
401 if (ret == GNUTLS_E_SUCCESS)
403 /* Here we're finally done. */
404 proc->gnutls_initstage = GNUTLS_STAGE_READY;
406 else
408 /* check_memory_full (gnutls_alert_send_appropriate (state, ret)); */
410 return ret;
413 #ifndef WINDOWSNT
414 static int
415 emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
417 int err = errno;
419 switch (err)
421 # ifdef _AIX
422 /* This is taken from the GnuTLS system_errno function circa 2016;
423 see <http://savannah.gnu.org/support/?107464>. */
424 case 0:
425 errno = EAGAIN;
426 /* Fall through. */
427 # endif
428 case EINPROGRESS:
429 case ENOTCONN:
430 return EAGAIN;
432 default:
433 return err;
436 #endif
438 static int
439 emacs_gnutls_handshake (struct Lisp_Process *proc)
441 gnutls_session_t state = proc->gnutls_state;
443 if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO)
444 return -1;
446 if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET)
448 #ifdef WINDOWSNT
449 /* On W32 we cannot transfer socket handles between different runtime
450 libraries, so we tell GnuTLS to use our special push/pull
451 functions. */
452 gnutls_transport_set_ptr2 (state,
453 (gnutls_transport_ptr_t) proc,
454 (gnutls_transport_ptr_t) proc);
455 gnutls_transport_set_push_function (state, &emacs_gnutls_push);
456 gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
457 #else
458 /* This is how GnuTLS takes sockets: as file descriptors passed
459 in. For an Emacs process socket, infd and outfd are the
460 same but we use this two-argument version for clarity. */
461 gnutls_transport_set_ptr2 (state,
462 (void *) (intptr_t) proc->infd,
463 (void *) (intptr_t) proc->outfd);
464 if (proc->is_non_blocking_client)
465 gnutls_transport_set_errno_function (state,
466 emacs_gnutls_nonblock_errno);
467 #endif
469 proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
472 return gnutls_try_handshake (proc);
475 ptrdiff_t
476 emacs_gnutls_record_check_pending (gnutls_session_t state)
478 return gnutls_record_check_pending (state);
481 #ifdef WINDOWSNT
482 void
483 emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
485 gnutls_transport_set_errno (state, err);
487 #endif
489 ptrdiff_t
490 emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
492 ssize_t rtnval = 0;
493 ptrdiff_t bytes_written;
494 gnutls_session_t state = proc->gnutls_state;
496 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
498 errno = EAGAIN;
499 return 0;
502 bytes_written = 0;
504 while (nbyte > 0)
506 rtnval = gnutls_record_send (state, buf, nbyte);
508 if (rtnval < 0)
510 if (rtnval == GNUTLS_E_INTERRUPTED)
511 continue;
512 else
514 /* If we get GNUTLS_E_AGAIN, then set errno
515 appropriately so that send_process retries the
516 correct way instead of erroring out. */
517 if (rtnval == GNUTLS_E_AGAIN)
518 errno = EAGAIN;
519 break;
523 buf += rtnval;
524 nbyte -= rtnval;
525 bytes_written += rtnval;
528 emacs_gnutls_handle_error (state, rtnval);
529 return (bytes_written);
532 ptrdiff_t
533 emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
535 ssize_t rtnval;
536 gnutls_session_t state = proc->gnutls_state;
538 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
540 errno = EAGAIN;
541 return -1;
544 rtnval = gnutls_record_recv (state, buf, nbyte);
545 if (rtnval >= 0)
546 return rtnval;
547 else if (rtnval == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
548 /* The peer closed the connection. */
549 return 0;
550 else if (emacs_gnutls_handle_error (state, rtnval))
551 /* non-fatal error */
552 return -1;
553 else {
554 /* a fatal error occurred */
555 return 0;
559 /* Report a GnuTLS error to the user.
560 Return true if the error code was successfully handled. */
561 static bool
562 emacs_gnutls_handle_error (gnutls_session_t session, int err)
564 int max_log_level = 0;
566 bool ret;
567 const char *str;
569 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
570 if (err >= 0)
571 return 1;
573 check_memory_full (err);
575 max_log_level = global_gnutls_log_level;
577 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
579 str = gnutls_strerror (err);
580 if (!str)
581 str = "unknown";
583 if (gnutls_error_is_fatal (err))
585 int level = 1;
586 /* Mostly ignore "The TLS connection was non-properly
587 terminated" message which just means that the peer closed the
588 connection. */
589 #ifdef HAVE_GNUTLS3
590 if (err == GNUTLS_E_PREMATURE_TERMINATION)
591 level = 3;
592 #endif
594 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
595 ret = 0;
597 else
599 ret = 1;
601 switch (err)
603 case GNUTLS_E_AGAIN:
604 GNUTLS_LOG2 (3,
605 max_log_level,
606 "retry:",
607 str);
608 default:
609 GNUTLS_LOG2 (1,
610 max_log_level,
611 "non-fatal error:",
612 str);
616 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
617 || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
619 int alert = gnutls_alert_get (session);
620 int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
621 str = gnutls_alert_get_name (alert);
622 if (!str)
623 str = "unknown";
625 GNUTLS_LOG2 (level, max_log_level, "Received alert: ", str);
627 return ret;
630 /* convert an integer error to a Lisp_Object; it will be either a
631 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
632 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
633 to Qt. */
634 static Lisp_Object
635 gnutls_make_error (int err)
637 switch (err)
639 case GNUTLS_E_SUCCESS:
640 return Qt;
641 case GNUTLS_E_AGAIN:
642 return Qgnutls_e_again;
643 case GNUTLS_E_INTERRUPTED:
644 return Qgnutls_e_interrupted;
645 case GNUTLS_E_INVALID_SESSION:
646 return Qgnutls_e_invalid_session;
649 check_memory_full (err);
650 return make_number (err);
653 Lisp_Object
654 emacs_gnutls_deinit (Lisp_Object proc)
656 int log_level;
658 CHECK_PROCESS (proc);
660 if (! XPROCESS (proc)->gnutls_p)
661 return Qnil;
663 log_level = XPROCESS (proc)->gnutls_log_level;
665 if (XPROCESS (proc)->gnutls_x509_cred)
667 GNUTLS_LOG (2, log_level, "Deallocating x509 credentials");
668 gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
669 XPROCESS (proc)->gnutls_x509_cred = NULL;
672 if (XPROCESS (proc)->gnutls_anon_cred)
674 GNUTLS_LOG (2, log_level, "Deallocating anon credentials");
675 gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
676 XPROCESS (proc)->gnutls_anon_cred = NULL;
679 if (XPROCESS (proc)->gnutls_state)
681 gnutls_deinit (XPROCESS (proc)->gnutls_state);
682 XPROCESS (proc)->gnutls_state = NULL;
683 if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
684 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
687 XPROCESS (proc)->gnutls_p = false;
688 return Qt;
691 DEFUN ("gnutls-asynchronous-parameters", Fgnutls_asynchronous_parameters,
692 Sgnutls_asynchronous_parameters, 2, 2, 0,
693 doc: /* Mark this process as being a pre-init GnuTLS process.
694 The second parameter is the list of parameters to feed to gnutls-boot
695 to finish setting up the connection. */)
696 (Lisp_Object proc, Lisp_Object params)
698 CHECK_PROCESS (proc);
700 XPROCESS (proc)->gnutls_boot_parameters = params;
701 return Qnil;
704 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0,
705 doc: /* Return the GnuTLS init stage of process PROC.
706 See also `gnutls-boot'. */)
707 (Lisp_Object proc)
709 CHECK_PROCESS (proc);
711 return make_number (GNUTLS_INITSTAGE (proc));
714 DEFUN ("gnutls-errorp", Fgnutls_errorp, Sgnutls_errorp, 1, 1, 0,
715 doc: /* Return t if ERROR indicates a GnuTLS problem.
716 ERROR is an integer or a symbol with an integer `gnutls-code' property.
717 usage: (gnutls-errorp ERROR) */
718 attributes: const)
719 (Lisp_Object err)
721 if (EQ (err, Qt)
722 || EQ (err, Qgnutls_e_again))
723 return Qnil;
725 return Qt;
728 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp, Sgnutls_error_fatalp, 1, 1, 0,
729 doc: /* Return non-nil if ERROR is fatal.
730 ERROR is an integer or a symbol with an integer `gnutls-code' property.
731 Usage: (gnutls-error-fatalp ERROR) */)
732 (Lisp_Object err)
734 Lisp_Object code;
736 if (EQ (err, Qt)) return Qnil;
738 if (SYMBOLP (err))
740 code = Fget (err, Qgnutls_code);
741 if (NUMBERP (code))
743 err = code;
745 else
747 error ("Symbol has no numeric gnutls-code property");
751 if (! TYPE_RANGED_INTEGERP (int, err))
752 error ("Not an error symbol or code");
754 if (0 == gnutls_error_is_fatal (XINT (err)))
755 return Qnil;
757 return Qt;
760 DEFUN ("gnutls-error-string", Fgnutls_error_string, Sgnutls_error_string, 1, 1, 0,
761 doc: /* Return a description of ERROR.
762 ERROR is an integer or a symbol with an integer `gnutls-code' property.
763 usage: (gnutls-error-string ERROR) */)
764 (Lisp_Object err)
766 Lisp_Object code;
768 if (EQ (err, Qt)) return build_string ("Not an error");
770 if (SYMBOLP (err))
772 code = Fget (err, Qgnutls_code);
773 if (NUMBERP (code))
775 err = code;
777 else
779 return build_string ("Symbol has no numeric gnutls-code property");
783 if (! TYPE_RANGED_INTEGERP (int, err))
784 return build_string ("Not an error symbol or code");
786 return build_string (gnutls_strerror (XINT (err)));
789 DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
790 doc: /* Deallocate GnuTLS resources associated with process PROC.
791 See also `gnutls-init'. */)
792 (Lisp_Object proc)
794 return emacs_gnutls_deinit (proc);
797 static Lisp_Object
798 gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
800 ptrdiff_t prefix_length = strlen (prefix);
801 ptrdiff_t retlen;
802 if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
803 || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
804 string_overflow ();
805 Lisp_Object ret = make_uninit_string (retlen);
806 char *string = SSDATA (ret);
807 strcpy (string, prefix);
809 for (ptrdiff_t i = 0; i < buf_size; i++)
810 sprintf (string + i * 3 + prefix_length,
811 i == buf_size - 1 ? "%02x" : "%02x:",
812 buf[i]);
814 return ret;
817 static Lisp_Object
818 gnutls_certificate_details (gnutls_x509_crt_t cert)
820 Lisp_Object res = Qnil;
821 int err;
822 size_t buf_size;
824 /* Version. */
826 int version = gnutls_x509_crt_get_version (cert);
827 check_memory_full (version);
828 if (version >= GNUTLS_E_SUCCESS)
829 res = nconc2 (res, list2 (intern (":version"),
830 make_number (version)));
833 /* Serial. */
834 buf_size = 0;
835 err = gnutls_x509_crt_get_serial (cert, NULL, &buf_size);
836 check_memory_full (err);
837 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
839 void *serial = xmalloc (buf_size);
840 err = gnutls_x509_crt_get_serial (cert, serial, &buf_size);
841 check_memory_full (err);
842 if (err >= GNUTLS_E_SUCCESS)
843 res = nconc2 (res, list2 (intern (":serial-number"),
844 gnutls_hex_string (serial, buf_size, "")));
845 xfree (serial);
848 /* Issuer. */
849 buf_size = 0;
850 err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &buf_size);
851 check_memory_full (err);
852 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
854 char *dn = xmalloc (buf_size);
855 err = gnutls_x509_crt_get_issuer_dn (cert, dn, &buf_size);
856 check_memory_full (err);
857 if (err >= GNUTLS_E_SUCCESS)
858 res = nconc2 (res, list2 (intern (":issuer"),
859 make_string (dn, buf_size)));
860 xfree (dn);
863 /* Validity. */
865 /* Add 1 to the buffer size, since 1900 is added to tm_year and
866 that might add 1 to the year length. */
867 char buf[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
868 struct tm t;
869 time_t tim = gnutls_x509_crt_get_activation_time (cert);
871 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
872 res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf)));
874 tim = gnutls_x509_crt_get_expiration_time (cert);
875 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
876 res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf)));
879 /* Subject. */
880 buf_size = 0;
881 err = gnutls_x509_crt_get_dn (cert, NULL, &buf_size);
882 check_memory_full (err);
883 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
885 char *dn = xmalloc (buf_size);
886 err = gnutls_x509_crt_get_dn (cert, dn, &buf_size);
887 check_memory_full (err);
888 if (err >= GNUTLS_E_SUCCESS)
889 res = nconc2 (res, list2 (intern (":subject"),
890 make_string (dn, buf_size)));
891 xfree (dn);
894 /* SubjectPublicKeyInfo. */
896 unsigned int bits;
898 err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
899 check_memory_full (err);
900 if (err >= GNUTLS_E_SUCCESS)
902 const char *name = gnutls_pk_algorithm_get_name (err);
903 if (name)
904 res = nconc2 (res, list2 (intern (":public-key-algorithm"),
905 build_string (name)));
907 name = gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
908 (err, bits));
909 res = nconc2 (res, list2 (intern (":certificate-security-level"),
910 build_string (name)));
914 /* Unique IDs. */
915 buf_size = 0;
916 err = gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size);
917 check_memory_full (err);
918 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
920 char *buf = xmalloc (buf_size);
921 err = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
922 check_memory_full (err);
923 if (err >= GNUTLS_E_SUCCESS)
924 res = nconc2 (res, list2 (intern (":issuer-unique-id"),
925 make_string (buf, buf_size)));
926 xfree (buf);
929 buf_size = 0;
930 err = gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size);
931 check_memory_full (err);
932 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
934 char *buf = xmalloc (buf_size);
935 err = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
936 check_memory_full (err);
937 if (err >= GNUTLS_E_SUCCESS)
938 res = nconc2 (res, list2 (intern (":subject-unique-id"),
939 make_string (buf, buf_size)));
940 xfree (buf);
943 /* Signature. */
944 err = gnutls_x509_crt_get_signature_algorithm (cert);
945 check_memory_full (err);
946 if (err >= GNUTLS_E_SUCCESS)
948 const char *name = gnutls_sign_get_name (err);
949 if (name)
950 res = nconc2 (res, list2 (intern (":signature-algorithm"),
951 build_string (name)));
954 /* Public key ID. */
955 buf_size = 0;
956 err = gnutls_x509_crt_get_key_id (cert, 0, NULL, &buf_size);
957 check_memory_full (err);
958 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
960 void *buf = xmalloc (buf_size);
961 err = gnutls_x509_crt_get_key_id (cert, 0, buf, &buf_size);
962 check_memory_full (err);
963 if (err >= GNUTLS_E_SUCCESS)
964 res = nconc2 (res, list2 (intern (":public-key-id"),
965 gnutls_hex_string (buf, buf_size, "sha1:")));
966 xfree (buf);
969 /* Certificate fingerprint. */
970 buf_size = 0;
971 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
972 NULL, &buf_size);
973 check_memory_full (err);
974 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
976 void *buf = xmalloc (buf_size);
977 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
978 buf, &buf_size);
979 check_memory_full (err);
980 if (err >= GNUTLS_E_SUCCESS)
981 res = nconc2 (res, list2 (intern (":certificate-id"),
982 gnutls_hex_string (buf, buf_size, "sha1:")));
983 xfree (buf);
986 return res;
989 DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe, Sgnutls_peer_status_warning_describe, 1, 1, 0,
990 doc: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
991 (Lisp_Object status_symbol)
993 CHECK_SYMBOL (status_symbol);
995 if (EQ (status_symbol, intern (":invalid")))
996 return build_string ("certificate could not be verified");
998 if (EQ (status_symbol, intern (":revoked")))
999 return build_string ("certificate was revoked (CRL)");
1001 if (EQ (status_symbol, intern (":self-signed")))
1002 return build_string ("certificate signer was not found (self-signed)");
1004 if (EQ (status_symbol, intern (":unknown-ca")))
1005 return build_string ("the certificate was signed by an unknown "
1006 "and therefore untrusted authority");
1008 if (EQ (status_symbol, intern (":not-ca")))
1009 return build_string ("certificate signer is not a CA");
1011 if (EQ (status_symbol, intern (":insecure")))
1012 return build_string ("certificate was signed with an insecure algorithm");
1014 if (EQ (status_symbol, intern (":not-activated")))
1015 return build_string ("certificate is not yet activated");
1017 if (EQ (status_symbol, intern (":expired")))
1018 return build_string ("certificate has expired");
1020 if (EQ (status_symbol, intern (":no-host-match")))
1021 return build_string ("certificate host does not match hostname");
1023 return Qnil;
1026 DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0,
1027 doc: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
1028 The return value is a property list with top-level keys :warnings and
1029 :certificate. The :warnings entry is a list of symbols you can describe with
1030 `gnutls-peer-status-warning-describe'. */)
1031 (Lisp_Object proc)
1033 Lisp_Object warnings = Qnil, result = Qnil;
1034 unsigned int verification;
1035 gnutls_session_t state;
1037 CHECK_PROCESS (proc);
1039 if (GNUTLS_INITSTAGE (proc) != GNUTLS_STAGE_READY)
1040 return Qnil;
1042 /* Then collect any warnings already computed by the handshake. */
1043 verification = XPROCESS (proc)->gnutls_peer_verification;
1045 if (verification & GNUTLS_CERT_INVALID)
1046 warnings = Fcons (intern (":invalid"), warnings);
1048 if (verification & GNUTLS_CERT_REVOKED)
1049 warnings = Fcons (intern (":revoked"), warnings);
1051 if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
1052 warnings = Fcons (intern (":unknown-ca"), warnings);
1054 if (verification & GNUTLS_CERT_SIGNER_NOT_CA)
1055 warnings = Fcons (intern (":not-ca"), warnings);
1057 if (verification & GNUTLS_CERT_INSECURE_ALGORITHM)
1058 warnings = Fcons (intern (":insecure"), warnings);
1060 if (verification & GNUTLS_CERT_NOT_ACTIVATED)
1061 warnings = Fcons (intern (":not-activated"), warnings);
1063 if (verification & GNUTLS_CERT_EXPIRED)
1064 warnings = Fcons (intern (":expired"), warnings);
1066 if (XPROCESS (proc)->gnutls_extra_peer_verification &
1067 CERTIFICATE_NOT_MATCHING)
1068 warnings = Fcons (intern (":no-host-match"), warnings);
1070 /* This could get called in the INIT stage, when the certificate is
1071 not yet set. */
1072 if (XPROCESS (proc)->gnutls_certificate != NULL &&
1073 gnutls_x509_crt_check_issuer(XPROCESS (proc)->gnutls_certificate,
1074 XPROCESS (proc)->gnutls_certificate))
1075 warnings = Fcons (intern (":self-signed"), warnings);
1077 if (!NILP (warnings))
1078 result = list2 (intern (":warnings"), warnings);
1080 /* This could get called in the INIT stage, when the certificate is
1081 not yet set. */
1082 if (XPROCESS (proc)->gnutls_certificate != NULL)
1083 result = nconc2 (result, list2
1084 (intern (":certificate"),
1085 gnutls_certificate_details (XPROCESS (proc)->gnutls_certificate)));
1087 state = XPROCESS (proc)->gnutls_state;
1089 /* Diffie-Hellman prime bits. */
1091 int bits = gnutls_dh_get_prime_bits (state);
1092 check_memory_full (bits);
1093 if (bits > 0)
1094 result = nconc2 (result, list2 (intern (":diffie-hellman-prime-bits"),
1095 make_number (bits)));
1098 /* Key exchange. */
1099 result = nconc2
1100 (result, list2 (intern (":key-exchange"),
1101 build_string (gnutls_kx_get_name
1102 (gnutls_kx_get (state)))));
1104 /* Protocol name. */
1105 result = nconc2
1106 (result, list2 (intern (":protocol"),
1107 build_string (gnutls_protocol_get_name
1108 (gnutls_protocol_get_version (state)))));
1110 /* Cipher name. */
1111 result = nconc2
1112 (result, list2 (intern (":cipher"),
1113 build_string (gnutls_cipher_get_name
1114 (gnutls_cipher_get (state)))));
1116 /* MAC name. */
1117 result = nconc2
1118 (result, list2 (intern (":mac"),
1119 build_string (gnutls_mac_get_name
1120 (gnutls_mac_get (state)))));
1123 return result;
1126 /* Initialize global GnuTLS state to defaults.
1127 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1128 Return zero on success. */
1129 Lisp_Object
1130 emacs_gnutls_global_init (void)
1132 int ret = GNUTLS_E_SUCCESS;
1134 if (!gnutls_global_initialized)
1136 ret = gnutls_global_init ();
1137 if (ret == GNUTLS_E_SUCCESS)
1138 gnutls_global_initialized = 1;
1141 return gnutls_make_error (ret);
1144 static bool
1145 gnutls_ip_address_p (char *string)
1147 char c;
1149 while ((c = *string++) != 0)
1150 if (! ((c == '.' || c == ':' || (c >= '0' && c <= '9'))))
1151 return false;
1153 return true;
1156 #if 0
1157 /* Deinitialize global GnuTLS state.
1158 See also `gnutls-global-init'. */
1159 static Lisp_Object
1160 emacs_gnutls_global_deinit (void)
1162 if (gnutls_global_initialized)
1163 gnutls_global_deinit ();
1165 gnutls_global_initialized = 0;
1167 return gnutls_make_error (GNUTLS_E_SUCCESS);
1169 #endif
1171 static void ATTRIBUTE_FORMAT_PRINTF (2, 3)
1172 boot_error (struct Lisp_Process *p, const char *m, ...)
1174 va_list ap;
1175 va_start (ap, m);
1176 if (p->is_non_blocking_client)
1177 pset_status (p, list2 (Qfailed, vformat_string (m, ap)));
1178 else
1179 verror (m, ap);
1180 va_end (ap);
1183 Lisp_Object
1184 gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1186 int ret;
1187 struct Lisp_Process *p = XPROCESS (proc);
1188 gnutls_session_t state = p->gnutls_state;
1189 unsigned int peer_verification;
1190 Lisp_Object warnings;
1191 int max_log_level = p->gnutls_log_level;
1192 Lisp_Object hostname, verify_error;
1193 bool verify_error_all = false;
1194 char *c_hostname;
1196 if (NILP (proplist))
1197 proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters));
1199 verify_error = Fplist_get (proplist, QCverify_error);
1200 hostname = Fplist_get (proplist, QChostname);
1202 if (EQ (verify_error, Qt))
1203 verify_error_all = true;
1204 else if (NILP (Flistp (verify_error)))
1206 boot_error (p,
1207 "gnutls-boot: invalid :verify_error parameter (not a list)");
1208 return Qnil;
1211 if (!STRINGP (hostname))
1213 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1214 return Qnil;
1216 c_hostname = SSDATA (hostname);
1218 /* Now verify the peer, following
1219 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1220 The peer should present at least one certificate in the chain; do a
1221 check of the certificate's hostname with
1222 gnutls_x509_crt_check_hostname against :hostname. */
1224 ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
1225 if (ret < GNUTLS_E_SUCCESS)
1226 return gnutls_make_error (ret);
1228 XPROCESS (proc)->gnutls_peer_verification = peer_verification;
1230 warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
1231 if (!NILP (warnings))
1233 for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail))
1235 Lisp_Object warning = XCAR (tail);
1236 Lisp_Object message = Fgnutls_peer_status_warning_describe (warning);
1237 if (!NILP (message))
1238 GNUTLS_LOG2 (1, max_log_level, "verification:", SSDATA (message));
1242 if (peer_verification != 0)
1244 if (verify_error_all
1245 || !NILP (Fmember (QCtrustfiles, verify_error)))
1247 emacs_gnutls_deinit (proc);
1248 boot_error (p,
1249 "Certificate validation failed %s, verification code %x",
1250 c_hostname, peer_verification);
1251 return Qnil;
1253 else
1255 GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
1256 c_hostname);
1260 /* Up to here the process is the same for X.509 certificates and
1261 OpenPGP keys. From now on X.509 certificates are assumed. This
1262 can be easily extended to work with openpgp keys as well. */
1263 if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
1265 gnutls_x509_crt_t gnutls_verify_cert;
1266 const gnutls_datum_t *gnutls_verify_cert_list;
1267 unsigned int gnutls_verify_cert_list_size;
1269 ret = gnutls_x509_crt_init (&gnutls_verify_cert);
1270 if (ret < GNUTLS_E_SUCCESS)
1271 return gnutls_make_error (ret);
1273 gnutls_verify_cert_list
1274 = gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
1276 if (gnutls_verify_cert_list == NULL)
1278 gnutls_x509_crt_deinit (gnutls_verify_cert);
1279 emacs_gnutls_deinit (proc);
1280 boot_error (p, "No x509 certificate was found\n");
1281 return Qnil;
1284 /* Check only the first certificate in the given chain. */
1285 ret = gnutls_x509_crt_import (gnutls_verify_cert,
1286 &gnutls_verify_cert_list[0],
1287 GNUTLS_X509_FMT_DER);
1289 if (ret < GNUTLS_E_SUCCESS)
1291 gnutls_x509_crt_deinit (gnutls_verify_cert);
1292 return gnutls_make_error (ret);
1295 XPROCESS (proc)->gnutls_certificate = gnutls_verify_cert;
1297 int err = gnutls_x509_crt_check_hostname (gnutls_verify_cert,
1298 c_hostname);
1299 check_memory_full (err);
1300 if (!err)
1302 XPROCESS (proc)->gnutls_extra_peer_verification
1303 |= CERTIFICATE_NOT_MATCHING;
1304 if (verify_error_all
1305 || !NILP (Fmember (QChostname, verify_error)))
1307 gnutls_x509_crt_deinit (gnutls_verify_cert);
1308 emacs_gnutls_deinit (proc);
1309 boot_error (p, "The x509 certificate does not match \"%s\"",
1310 c_hostname);
1311 return Qnil;
1313 else
1314 GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
1315 c_hostname);
1319 /* Set this flag only if the whole initialization succeeded. */
1320 XPROCESS (proc)->gnutls_p = true;
1322 return gnutls_make_error (ret);
1325 DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1326 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1327 Currently only client mode is supported. Return a success/failure
1328 value you can check with `gnutls-errorp'.
1330 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
1331 PROPLIST is a property list with the following keys:
1333 :hostname is a string naming the remote host.
1335 :priority is a GnuTLS priority string, defaults to "NORMAL".
1337 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
1339 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
1341 :keylist is an alist of PEM-encoded key files and PEM-encoded
1342 certificates for `gnutls-x509pki'.
1344 :callbacks is an alist of callback functions, see below.
1346 :loglevel is the debug level requested from GnuTLS, try 4.
1348 :verify-flags is a bitset as per GnuTLS'
1349 gnutls_certificate_set_verify_flags.
1351 :verify-hostname-error is ignored. Pass :hostname in :verify-error
1352 instead.
1354 :verify-error is a list of symbols to express verification checks or
1355 t to do all checks. Currently it can contain `:trustfiles' and
1356 `:hostname' to verify the certificate or the hostname respectively.
1358 :min-prime-bits is the minimum accepted number of bits the client will
1359 accept in Diffie-Hellman key exchange.
1361 :complete-negotiation, if non-nil, will make negotiation complete
1362 before returning even on non-blocking sockets.
1364 The debug level will be set for this process AND globally for GnuTLS.
1365 So if you set it higher or lower at any point, it affects global
1366 debugging.
1368 Note that the priority is set on the client. The server does not use
1369 the protocols's priority except for disabling protocols that were not
1370 specified.
1372 Processes must be initialized with this function before other GnuTLS
1373 functions are used. This function allocates resources which can only
1374 be deallocated by calling `gnutls-deinit' or by calling it again.
1376 The callbacks alist can have a `verify' key, associated with a
1377 verification function (UNUSED).
1379 Each authentication type may need additional information in order to
1380 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
1381 one trustfile (usually a CA bundle). */)
1382 (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist)
1384 int ret = GNUTLS_E_SUCCESS;
1385 int max_log_level = 0;
1387 gnutls_session_t state;
1388 gnutls_certificate_credentials_t x509_cred = NULL;
1389 gnutls_anon_client_credentials_t anon_cred = NULL;
1390 Lisp_Object global_init;
1391 char const *priority_string_ptr = "NORMAL"; /* default priority string. */
1392 char *c_hostname;
1394 /* Placeholders for the property list elements. */
1395 Lisp_Object priority_string;
1396 Lisp_Object trustfiles;
1397 Lisp_Object crlfiles;
1398 Lisp_Object keylist;
1399 /* Lisp_Object callbacks; */
1400 Lisp_Object loglevel;
1401 Lisp_Object hostname;
1402 Lisp_Object prime_bits;
1403 struct Lisp_Process *p = XPROCESS (proc);
1405 CHECK_PROCESS (proc);
1406 CHECK_SYMBOL (type);
1407 CHECK_LIST (proplist);
1409 if (NILP (Fgnutls_available_p ()))
1411 boot_error (p, "GnuTLS not available");
1412 return Qnil;
1415 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon))
1417 boot_error (p, "Invalid GnuTLS credential type");
1418 return Qnil;
1421 hostname = Fplist_get (proplist, QChostname);
1422 priority_string = Fplist_get (proplist, QCpriority);
1423 trustfiles = Fplist_get (proplist, QCtrustfiles);
1424 keylist = Fplist_get (proplist, QCkeylist);
1425 crlfiles = Fplist_get (proplist, QCcrlfiles);
1426 loglevel = Fplist_get (proplist, QCloglevel);
1427 prime_bits = Fplist_get (proplist, QCmin_prime_bits);
1429 if (!STRINGP (hostname))
1431 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1432 return Qnil;
1434 c_hostname = SSDATA (hostname);
1436 state = XPROCESS (proc)->gnutls_state;
1438 if (TYPE_RANGED_INTEGERP (int, loglevel))
1440 gnutls_global_set_log_function (gnutls_log_function);
1441 #ifdef HAVE_GNUTLS3
1442 gnutls_global_set_audit_log_function (gnutls_audit_log_function);
1443 #endif
1444 gnutls_global_set_log_level (XINT (loglevel));
1445 max_log_level = XINT (loglevel);
1446 XPROCESS (proc)->gnutls_log_level = max_log_level;
1449 GNUTLS_LOG2 (1, max_log_level, "connecting to host:", c_hostname);
1451 /* Always initialize globals. */
1452 global_init = emacs_gnutls_global_init ();
1453 if (! NILP (Fgnutls_errorp (global_init)))
1454 return global_init;
1456 /* Before allocating new credentials, deallocate any credentials
1457 that PROC might already have. */
1458 emacs_gnutls_deinit (proc);
1460 /* Mark PROC as a GnuTLS process. */
1461 XPROCESS (proc)->gnutls_state = NULL;
1462 XPROCESS (proc)->gnutls_x509_cred = NULL;
1463 XPROCESS (proc)->gnutls_anon_cred = NULL;
1464 pset_gnutls_cred_type (XPROCESS (proc), type);
1465 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY;
1467 GNUTLS_LOG (1, max_log_level, "allocating credentials");
1468 if (EQ (type, Qgnutls_x509pki))
1470 Lisp_Object verify_flags;
1471 unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1473 GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
1474 check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
1475 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1477 verify_flags = Fplist_get (proplist, QCverify_flags);
1478 if (NUMBERP (verify_flags))
1480 gnutls_verify_flags = XINT (verify_flags);
1481 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1483 else if (NILP (verify_flags))
1484 GNUTLS_LOG (2, max_log_level, "using default verification flags");
1485 else
1486 GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
1488 gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
1490 else /* Qgnutls_anon: */
1492 GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
1493 check_memory_full (gnutls_anon_allocate_client_credentials (&anon_cred));
1494 XPROCESS (proc)->gnutls_anon_cred = anon_cred;
1497 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC;
1499 if (EQ (type, Qgnutls_x509pki))
1501 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
1502 int file_format = GNUTLS_X509_FMT_PEM;
1503 Lisp_Object tail;
1505 #if GNUTLS_VERSION_MAJOR + \
1506 (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
1507 ret = gnutls_certificate_set_x509_system_trust (x509_cred);
1508 if (ret < GNUTLS_E_SUCCESS)
1510 check_memory_full (ret);
1511 GNUTLS_LOG2i (4, max_log_level,
1512 "setting system trust failed with code ", ret);
1514 #endif
1516 for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
1518 Lisp_Object trustfile = XCAR (tail);
1519 if (STRINGP (trustfile))
1521 GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
1522 SSDATA (trustfile));
1523 trustfile = ENCODE_FILE (trustfile);
1524 #ifdef WINDOWSNT
1525 /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
1526 file names on Windows, we need to re-encode the file
1527 name using the current ANSI codepage. */
1528 trustfile = ansi_encode_filename (trustfile);
1529 #endif
1530 ret = gnutls_certificate_set_x509_trust_file
1531 (x509_cred,
1532 SSDATA (trustfile),
1533 file_format);
1535 if (ret < GNUTLS_E_SUCCESS)
1536 return gnutls_make_error (ret);
1538 else
1540 emacs_gnutls_deinit (proc);
1541 boot_error (p, "Invalid trustfile");
1542 return Qnil;
1546 for (tail = crlfiles; CONSP (tail); tail = XCDR (tail))
1548 Lisp_Object crlfile = XCAR (tail);
1549 if (STRINGP (crlfile))
1551 GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
1552 SSDATA (crlfile));
1553 crlfile = ENCODE_FILE (crlfile);
1554 #ifdef WINDOWSNT
1555 crlfile = ansi_encode_filename (crlfile);
1556 #endif
1557 ret = gnutls_certificate_set_x509_crl_file
1558 (x509_cred, SSDATA (crlfile), file_format);
1560 if (ret < GNUTLS_E_SUCCESS)
1561 return gnutls_make_error (ret);
1563 else
1565 emacs_gnutls_deinit (proc);
1566 boot_error (p, "Invalid CRL file");
1567 return Qnil;
1571 for (tail = keylist; CONSP (tail); tail = XCDR (tail))
1573 Lisp_Object keyfile = Fcar (XCAR (tail));
1574 Lisp_Object certfile = Fcar (Fcdr (XCAR (tail)));
1575 if (STRINGP (keyfile) && STRINGP (certfile))
1577 GNUTLS_LOG2 (1, max_log_level, "setting the client key file: ",
1578 SSDATA (keyfile));
1579 GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
1580 SSDATA (certfile));
1581 keyfile = ENCODE_FILE (keyfile);
1582 certfile = ENCODE_FILE (certfile);
1583 #ifdef WINDOWSNT
1584 keyfile = ansi_encode_filename (keyfile);
1585 certfile = ansi_encode_filename (certfile);
1586 #endif
1587 ret = gnutls_certificate_set_x509_key_file
1588 (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
1590 if (ret < GNUTLS_E_SUCCESS)
1591 return gnutls_make_error (ret);
1593 else
1595 emacs_gnutls_deinit (proc);
1596 boot_error (p, STRINGP (keyfile) ? "Invalid client cert file"
1597 : "Invalid client key file");
1598 return Qnil;
1603 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES;
1604 GNUTLS_LOG (1, max_log_level, "gnutls callbacks");
1605 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS;
1607 /* Call gnutls_init here: */
1609 GNUTLS_LOG (1, max_log_level, "gnutls_init");
1610 int gnutls_flags = GNUTLS_CLIENT;
1611 #ifdef GNUTLS_NONBLOCK
1612 if (XPROCESS (proc)->is_non_blocking_client)
1613 gnutls_flags |= GNUTLS_NONBLOCK;
1614 #endif
1615 ret = gnutls_init (&state, gnutls_flags);
1616 XPROCESS (proc)->gnutls_state = state;
1617 if (ret < GNUTLS_E_SUCCESS)
1618 return gnutls_make_error (ret);
1619 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT;
1621 if (STRINGP (priority_string))
1623 priority_string_ptr = SSDATA (priority_string);
1624 GNUTLS_LOG2 (1, max_log_level, "got non-default priority string:",
1625 priority_string_ptr);
1627 else
1629 GNUTLS_LOG2 (1, max_log_level, "using default priority string:",
1630 priority_string_ptr);
1633 GNUTLS_LOG (1, max_log_level, "setting the priority string");
1634 ret = gnutls_priority_set_direct (state, priority_string_ptr, NULL);
1635 if (ret < GNUTLS_E_SUCCESS)
1636 return gnutls_make_error (ret);
1638 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY;
1640 if (INTEGERP (prime_bits))
1641 gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
1643 ret = EQ (type, Qgnutls_x509pki)
1644 ? gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
1645 : gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
1646 if (ret < GNUTLS_E_SUCCESS)
1647 return gnutls_make_error (ret);
1649 if (!gnutls_ip_address_p (c_hostname))
1651 ret = gnutls_server_name_set (state, GNUTLS_NAME_DNS, c_hostname,
1652 strlen (c_hostname));
1653 if (ret < GNUTLS_E_SUCCESS)
1654 return gnutls_make_error (ret);
1657 XPROCESS (proc)->gnutls_complete_negotiation_p =
1658 !NILP (Fplist_get (proplist, QCcomplete_negotiation));
1659 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
1660 ret = emacs_gnutls_handshake (XPROCESS (proc));
1661 if (ret < GNUTLS_E_SUCCESS)
1662 return gnutls_make_error (ret);
1664 return gnutls_verify_boot (proc, proplist);
1667 DEFUN ("gnutls-bye", Fgnutls_bye,
1668 Sgnutls_bye, 2, 2, 0,
1669 doc: /* Terminate current GnuTLS connection for process PROC.
1670 The connection should have been initiated using `gnutls-handshake'.
1672 If CONT is not nil the TLS connection gets terminated and further
1673 receives and sends will be disallowed. If the return value is zero you
1674 may continue using the connection. If CONT is nil, GnuTLS actually
1675 sends an alert containing a close request and waits for the peer to
1676 reply with the same message. In order to reuse the connection you
1677 should wait for an EOF from the peer.
1679 This function may also return `gnutls-e-again', or
1680 `gnutls-e-interrupted'. */)
1681 (Lisp_Object proc, Lisp_Object cont)
1683 gnutls_session_t state;
1684 int ret;
1686 CHECK_PROCESS (proc);
1688 state = XPROCESS (proc)->gnutls_state;
1690 gnutls_x509_crt_deinit (XPROCESS (proc)->gnutls_certificate);
1692 ret = gnutls_bye (state, NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
1694 return gnutls_make_error (ret);
1697 #endif /* HAVE_GNUTLS */
1699 DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
1700 doc: /* Return t if GnuTLS is available in this instance of Emacs. */)
1701 (void)
1703 #ifdef HAVE_GNUTLS
1704 # ifdef WINDOWSNT
1705 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
1706 if (CONSP (found))
1707 return XCDR (found);
1708 else
1710 Lisp_Object status;
1711 status = init_gnutls_functions () ? Qt : Qnil;
1712 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
1713 return status;
1715 # else /* !WINDOWSNT */
1716 return Qt;
1717 # endif /* !WINDOWSNT */
1718 #else /* !HAVE_GNUTLS */
1719 return Qnil;
1720 #endif /* !HAVE_GNUTLS */
1723 void
1724 syms_of_gnutls (void)
1726 DEFSYM (Qlibgnutls_version, "libgnutls-version");
1727 Fset (Qlibgnutls_version,
1728 #ifdef HAVE_GNUTLS
1729 make_number (GNUTLS_VERSION_MAJOR * 10000
1730 + GNUTLS_VERSION_MINOR * 100
1731 + GNUTLS_VERSION_PATCH)
1732 #else
1733 make_number (-1)
1734 #endif
1736 #ifdef HAVE_GNUTLS
1737 gnutls_global_initialized = 0;
1739 DEFSYM (Qgnutls_code, "gnutls-code");
1740 DEFSYM (Qgnutls_anon, "gnutls-anon");
1741 DEFSYM (Qgnutls_x509pki, "gnutls-x509pki");
1743 /* The following are for the property list of 'gnutls-boot'. */
1744 DEFSYM (QChostname, ":hostname");
1745 DEFSYM (QCpriority, ":priority");
1746 DEFSYM (QCtrustfiles, ":trustfiles");
1747 DEFSYM (QCkeylist, ":keylist");
1748 DEFSYM (QCcrlfiles, ":crlfiles");
1749 DEFSYM (QCmin_prime_bits, ":min-prime-bits");
1750 DEFSYM (QCloglevel, ":loglevel");
1751 DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
1752 DEFSYM (QCverify_flags, ":verify-flags");
1753 DEFSYM (QCverify_error, ":verify-error");
1755 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
1756 Fput (Qgnutls_e_interrupted, Qgnutls_code,
1757 make_number (GNUTLS_E_INTERRUPTED));
1759 DEFSYM (Qgnutls_e_again, "gnutls-e-again");
1760 Fput (Qgnutls_e_again, Qgnutls_code,
1761 make_number (GNUTLS_E_AGAIN));
1763 DEFSYM (Qgnutls_e_invalid_session, "gnutls-e-invalid-session");
1764 Fput (Qgnutls_e_invalid_session, Qgnutls_code,
1765 make_number (GNUTLS_E_INVALID_SESSION));
1767 DEFSYM (Qgnutls_e_not_ready_for_handshake, "gnutls-e-not-ready-for-handshake");
1768 Fput (Qgnutls_e_not_ready_for_handshake, Qgnutls_code,
1769 make_number (GNUTLS_E_APPLICATION_ERROR_MIN));
1771 defsubr (&Sgnutls_get_initstage);
1772 defsubr (&Sgnutls_asynchronous_parameters);
1773 defsubr (&Sgnutls_errorp);
1774 defsubr (&Sgnutls_error_fatalp);
1775 defsubr (&Sgnutls_error_string);
1776 defsubr (&Sgnutls_boot);
1777 defsubr (&Sgnutls_deinit);
1778 defsubr (&Sgnutls_bye);
1779 defsubr (&Sgnutls_peer_status);
1780 defsubr (&Sgnutls_peer_status_warning_describe);
1782 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
1783 doc: /* Logging level used by the GnuTLS functions.
1784 Set this larger than 0 to get debug output in the *Messages* buffer.
1785 1 is for important messages, 2 is for debug data, and higher numbers
1786 are as per the GnuTLS logging conventions. */);
1787 global_gnutls_log_level = 0;
1789 #endif /* HAVE_GNUTLS */
1791 defsubr (&Sgnutls_available_p);