Fix (mapcar F S) crash when F alters S’s length
[emacs.git] / src / gnutls.c
blob7f05ac4bc475c73fafa32188ebc9b62875ef2681
1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2016 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
29 #include <gnutls/gnutls.h>
31 #ifdef WINDOWSNT
32 #include <windows.h>
33 #include "w32.h"
34 #endif
36 static bool emacs_gnutls_handle_error (gnutls_session_t, int);
38 static bool gnutls_global_initialized;
40 static void gnutls_log_function (int, const char *);
41 static void gnutls_log_function2 (int, const char *, const char *);
42 #ifdef HAVE_GNUTLS3
43 static void gnutls_audit_log_function (gnutls_session_t, const char *);
44 #endif
46 enum extra_peer_verification
48 CERTIFICATE_NOT_MATCHING = 2
52 #ifdef WINDOWSNT
54 DEF_DLL_FN (gnutls_alert_description_t, gnutls_alert_get,
55 (gnutls_session_t));
56 DEF_DLL_FN (const char *, gnutls_alert_get_name,
57 (gnutls_alert_description_t));
58 DEF_DLL_FN (int, gnutls_anon_allocate_client_credentials,
59 (gnutls_anon_client_credentials_t *));
60 DEF_DLL_FN (void, gnutls_anon_free_client_credentials,
61 (gnutls_anon_client_credentials_t));
62 DEF_DLL_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
63 DEF_DLL_FN (int, gnutls_certificate_allocate_credentials,
64 (gnutls_certificate_credentials_t *));
65 DEF_DLL_FN (void, gnutls_certificate_free_credentials,
66 (gnutls_certificate_credentials_t));
67 DEF_DLL_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
68 (gnutls_session_t, unsigned int *));
69 DEF_DLL_FN (void, gnutls_certificate_set_verify_flags,
70 (gnutls_certificate_credentials_t, unsigned int));
71 DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
72 (gnutls_certificate_credentials_t, const char *,
73 gnutls_x509_crt_fmt_t));
74 DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
75 (gnutls_certificate_credentials_t, const char *, const char *,
76 gnutls_x509_crt_fmt_t));
77 # if ((GNUTLS_VERSION_MAJOR \
78 + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
79 > 3)
80 DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
81 (gnutls_certificate_credentials_t));
82 # endif
83 DEF_DLL_FN (int, gnutls_certificate_set_x509_trust_file,
84 (gnutls_certificate_credentials_t, const char *,
85 gnutls_x509_crt_fmt_t));
86 DEF_DLL_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
87 (gnutls_session_t));
88 DEF_DLL_FN (int, gnutls_certificate_verify_peers2,
89 (gnutls_session_t, unsigned int *));
90 DEF_DLL_FN (int, gnutls_credentials_set,
91 (gnutls_session_t, gnutls_credentials_type_t, void *));
92 DEF_DLL_FN (void, gnutls_deinit, (gnutls_session_t));
93 DEF_DLL_FN (void, gnutls_dh_set_prime_bits,
94 (gnutls_session_t, unsigned int));
95 DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
96 DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
97 DEF_DLL_FN (int, gnutls_global_init, (void));
98 DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
99 # ifdef HAVE_GNUTLS3
100 DEF_DLL_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
101 # endif
102 DEF_DLL_FN (void, gnutls_global_set_log_level, (int));
103 DEF_DLL_FN (int, gnutls_handshake, (gnutls_session_t));
104 DEF_DLL_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
105 DEF_DLL_FN (int, gnutls_priority_set_direct,
106 (gnutls_session_t, const char *, const char **));
107 DEF_DLL_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
108 DEF_DLL_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
109 DEF_DLL_FN (ssize_t, gnutls_record_send,
110 (gnutls_session_t, const void *, size_t));
111 DEF_DLL_FN (const char *, gnutls_strerror, (int));
112 DEF_DLL_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
113 DEF_DLL_FN (const char *, gnutls_check_version, (const char *));
114 DEF_DLL_FN (void, gnutls_transport_set_lowat, (gnutls_session_t, int));
115 DEF_DLL_FN (void, gnutls_transport_set_ptr2,
116 (gnutls_session_t, gnutls_transport_ptr_t,
117 gnutls_transport_ptr_t));
118 DEF_DLL_FN (void, gnutls_transport_set_pull_function,
119 (gnutls_session_t, gnutls_pull_func));
120 DEF_DLL_FN (void, gnutls_transport_set_push_function,
121 (gnutls_session_t, gnutls_push_func));
122 DEF_DLL_FN (int, gnutls_x509_crt_check_hostname,
123 (gnutls_x509_crt_t, const char *));
124 DEF_DLL_FN (int, gnutls_x509_crt_check_issuer,
125 (gnutls_x509_crt_t, gnutls_x509_crt_t));
126 DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
127 DEF_DLL_FN (int, gnutls_x509_crt_import,
128 (gnutls_x509_crt_t, const gnutls_datum_t *,
129 gnutls_x509_crt_fmt_t));
130 DEF_DLL_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
131 DEF_DLL_FN (int, gnutls_x509_crt_get_fingerprint,
132 (gnutls_x509_crt_t,
133 gnutls_digest_algorithm_t, void *, size_t *));
134 DEF_DLL_FN (int, gnutls_x509_crt_get_version,
135 (gnutls_x509_crt_t));
136 DEF_DLL_FN (int, gnutls_x509_crt_get_serial,
137 (gnutls_x509_crt_t, void *, size_t *));
138 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_dn,
139 (gnutls_x509_crt_t, char *, size_t *));
140 DEF_DLL_FN (time_t, gnutls_x509_crt_get_activation_time,
141 (gnutls_x509_crt_t));
142 DEF_DLL_FN (time_t, gnutls_x509_crt_get_expiration_time,
143 (gnutls_x509_crt_t));
144 DEF_DLL_FN (int, gnutls_x509_crt_get_dn,
145 (gnutls_x509_crt_t, char *, size_t *));
146 DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm,
147 (gnutls_x509_crt_t, unsigned int *));
148 DEF_DLL_FN (const char*, gnutls_pk_algorithm_get_name,
149 (gnutls_pk_algorithm_t));
150 DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param,
151 (gnutls_pk_algorithm_t, unsigned int));
152 DEF_DLL_FN (int, gnutls_x509_crt_get_issuer_unique_id,
153 (gnutls_x509_crt_t, char *, size_t *));
154 DEF_DLL_FN (int, gnutls_x509_crt_get_subject_unique_id,
155 (gnutls_x509_crt_t, char *, size_t *));
156 DEF_DLL_FN (int, gnutls_x509_crt_get_signature_algorithm,
157 (gnutls_x509_crt_t));
158 DEF_DLL_FN (int, gnutls_x509_crt_get_key_id,
159 (gnutls_x509_crt_t, unsigned int, unsigned char *, size_t *_size));
160 DEF_DLL_FN (const char*, gnutls_sec_param_get_name, (gnutls_sec_param_t));
161 DEF_DLL_FN (const char*, gnutls_sign_get_name, (gnutls_sign_algorithm_t));
162 DEF_DLL_FN (int, gnutls_server_name_set,
163 (gnutls_session_t, gnutls_server_name_type_t,
164 const void *, size_t));
165 DEF_DLL_FN (gnutls_kx_algorithm_t, gnutls_kx_get, (gnutls_session_t));
166 DEF_DLL_FN (const char*, gnutls_kx_get_name, (gnutls_kx_algorithm_t));
167 DEF_DLL_FN (gnutls_protocol_t, gnutls_protocol_get_version,
168 (gnutls_session_t));
169 DEF_DLL_FN (const char*, gnutls_protocol_get_name, (gnutls_protocol_t));
170 DEF_DLL_FN (gnutls_cipher_algorithm_t, gnutls_cipher_get,
171 (gnutls_session_t));
172 DEF_DLL_FN (const char*, gnutls_cipher_get_name,
173 (gnutls_cipher_algorithm_t));
174 DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
175 DEF_DLL_FN (const char*, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
178 static bool
179 init_gnutls_functions (void)
181 HMODULE library;
182 int max_log_level = 1;
184 if (!(library = w32_delayed_load (Qgnutls)))
186 GNUTLS_LOG (1, max_log_level, "GnuTLS library not found");
187 return 0;
190 LOAD_DLL_FN (library, gnutls_alert_get);
191 LOAD_DLL_FN (library, gnutls_alert_get_name);
192 LOAD_DLL_FN (library, gnutls_anon_allocate_client_credentials);
193 LOAD_DLL_FN (library, gnutls_anon_free_client_credentials);
194 LOAD_DLL_FN (library, gnutls_bye);
195 LOAD_DLL_FN (library, gnutls_certificate_allocate_credentials);
196 LOAD_DLL_FN (library, gnutls_certificate_free_credentials);
197 LOAD_DLL_FN (library, gnutls_certificate_get_peers);
198 LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
199 LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
200 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
201 # if ((GNUTLS_VERSION_MAJOR \
202 + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
203 > 3)
204 LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
205 # endif
206 LOAD_DLL_FN (library, gnutls_certificate_set_x509_trust_file);
207 LOAD_DLL_FN (library, gnutls_certificate_type_get);
208 LOAD_DLL_FN (library, gnutls_certificate_verify_peers2);
209 LOAD_DLL_FN (library, gnutls_credentials_set);
210 LOAD_DLL_FN (library, gnutls_deinit);
211 LOAD_DLL_FN (library, gnutls_dh_set_prime_bits);
212 LOAD_DLL_FN (library, gnutls_dh_get_prime_bits);
213 LOAD_DLL_FN (library, gnutls_error_is_fatal);
214 LOAD_DLL_FN (library, gnutls_global_init);
215 LOAD_DLL_FN (library, gnutls_global_set_log_function);
216 # ifdef HAVE_GNUTLS3
217 LOAD_DLL_FN (library, gnutls_global_set_audit_log_function);
218 # endif
219 LOAD_DLL_FN (library, gnutls_global_set_log_level);
220 LOAD_DLL_FN (library, gnutls_handshake);
221 LOAD_DLL_FN (library, gnutls_init);
222 LOAD_DLL_FN (library, gnutls_priority_set_direct);
223 LOAD_DLL_FN (library, gnutls_record_check_pending);
224 LOAD_DLL_FN (library, gnutls_record_recv);
225 LOAD_DLL_FN (library, gnutls_record_send);
226 LOAD_DLL_FN (library, gnutls_strerror);
227 LOAD_DLL_FN (library, gnutls_transport_set_errno);
228 LOAD_DLL_FN (library, gnutls_check_version);
229 /* We don't need to call gnutls_transport_set_lowat in GnuTLS 2.11.1
230 and later, and the function was removed entirely in 3.0.0. */
231 if (!fn_gnutls_check_version ("2.11.1"))
232 LOAD_DLL_FN (library, gnutls_transport_set_lowat);
233 LOAD_DLL_FN (library, gnutls_transport_set_ptr2);
234 LOAD_DLL_FN (library, gnutls_transport_set_pull_function);
235 LOAD_DLL_FN (library, gnutls_transport_set_push_function);
236 LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname);
237 LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer);
238 LOAD_DLL_FN (library, gnutls_x509_crt_deinit);
239 LOAD_DLL_FN (library, gnutls_x509_crt_import);
240 LOAD_DLL_FN (library, gnutls_x509_crt_init);
241 LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint);
242 LOAD_DLL_FN (library, gnutls_x509_crt_get_version);
243 LOAD_DLL_FN (library, gnutls_x509_crt_get_serial);
244 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_dn);
245 LOAD_DLL_FN (library, gnutls_x509_crt_get_activation_time);
246 LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time);
247 LOAD_DLL_FN (library, gnutls_x509_crt_get_dn);
248 LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm);
249 LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name);
250 LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param);
251 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id);
252 LOAD_DLL_FN (library, gnutls_x509_crt_get_subject_unique_id);
253 LOAD_DLL_FN (library, gnutls_x509_crt_get_signature_algorithm);
254 LOAD_DLL_FN (library, gnutls_x509_crt_get_key_id);
255 LOAD_DLL_FN (library, gnutls_sec_param_get_name);
256 LOAD_DLL_FN (library, gnutls_sign_get_name);
257 LOAD_DLL_FN (library, gnutls_server_name_set);
258 LOAD_DLL_FN (library, gnutls_kx_get);
259 LOAD_DLL_FN (library, gnutls_kx_get_name);
260 LOAD_DLL_FN (library, gnutls_protocol_get_version);
261 LOAD_DLL_FN (library, gnutls_protocol_get_name);
262 LOAD_DLL_FN (library, gnutls_cipher_get);
263 LOAD_DLL_FN (library, gnutls_cipher_get_name);
264 LOAD_DLL_FN (library, gnutls_mac_get);
265 LOAD_DLL_FN (library, gnutls_mac_get_name);
267 max_log_level = global_gnutls_log_level;
270 Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from));
271 GNUTLS_LOG2 (1, max_log_level, "GnuTLS library loaded:",
272 STRINGP (name) ? (const char *) SDATA (name) : "unknown");
275 return 1;
278 # define gnutls_alert_get fn_gnutls_alert_get
279 # define gnutls_alert_get_name fn_gnutls_alert_get_name
280 # define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
281 # define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
282 # define gnutls_bye fn_gnutls_bye
283 # define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
284 # define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
285 # define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
286 # define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
287 # define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
288 # define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
289 # define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
290 # define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
291 # define gnutls_certificate_type_get fn_gnutls_certificate_type_get
292 # define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
293 # define gnutls_check_version fn_gnutls_check_version
294 # define gnutls_cipher_get fn_gnutls_cipher_get
295 # define gnutls_cipher_get_name fn_gnutls_cipher_get_name
296 # define gnutls_credentials_set fn_gnutls_credentials_set
297 # define gnutls_deinit fn_gnutls_deinit
298 # define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
299 # define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
300 # define gnutls_error_is_fatal fn_gnutls_error_is_fatal
301 # define gnutls_global_init fn_gnutls_global_init
302 # define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
303 # define gnutls_global_set_log_function fn_gnutls_global_set_log_function
304 # define gnutls_global_set_log_level fn_gnutls_global_set_log_level
305 # define gnutls_handshake fn_gnutls_handshake
306 # define gnutls_init fn_gnutls_init
307 # define gnutls_kx_get fn_gnutls_kx_get
308 # define gnutls_kx_get_name fn_gnutls_kx_get_name
309 # define gnutls_mac_get fn_gnutls_mac_get
310 # define gnutls_mac_get_name fn_gnutls_mac_get_name
311 # define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
312 # define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
313 # define gnutls_priority_set_direct fn_gnutls_priority_set_direct
314 # define gnutls_protocol_get_name fn_gnutls_protocol_get_name
315 # define gnutls_protocol_get_version fn_gnutls_protocol_get_version
316 # define gnutls_record_check_pending fn_gnutls_record_check_pending
317 # define gnutls_record_recv fn_gnutls_record_recv
318 # define gnutls_record_send fn_gnutls_record_send
319 # define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
320 # define gnutls_server_name_set fn_gnutls_server_name_set
321 # define gnutls_sign_get_name fn_gnutls_sign_get_name
322 # define gnutls_strerror fn_gnutls_strerror
323 # define gnutls_transport_set_errno fn_gnutls_transport_set_errno
324 # define gnutls_transport_set_lowat fn_gnutls_transport_set_lowat
325 # define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
326 # define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
327 # define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
328 # define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
329 # define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
330 # define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
331 # define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
332 # define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
333 # define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
334 # define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
335 # define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
336 # define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
337 # define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
338 # define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
339 # define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
340 # define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
341 # define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
342 # define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
343 # define gnutls_x509_crt_import fn_gnutls_x509_crt_import
344 # define gnutls_x509_crt_init fn_gnutls_x509_crt_init
346 #endif
349 /* Report memory exhaustion if ERR is an out-of-memory indication. */
350 static void
351 check_memory_full (int err)
353 /* When GnuTLS exhausts memory, it doesn't say how much memory it
354 asked for, so tell the Emacs allocator that GnuTLS asked for no
355 bytes. This isn't accurate, but it's good enough. */
356 if (err == GNUTLS_E_MEMORY_ERROR)
357 memory_full (0);
360 #ifdef HAVE_GNUTLS3
361 /* Log a simple audit message. */
362 static void
363 gnutls_audit_log_function (gnutls_session_t session, const char *string)
365 if (global_gnutls_log_level >= 1)
367 message ("gnutls.c: [audit] %s", string);
370 #endif
372 /* Log a simple message. */
373 static void
374 gnutls_log_function (int level, const char *string)
376 message ("gnutls.c: [%d] %s", level, string);
379 /* Log a message and a string. */
380 static void
381 gnutls_log_function2 (int level, const char *string, const char *extra)
383 message ("gnutls.c: [%d] %s %s", level, string, extra);
387 gnutls_try_handshake (struct Lisp_Process *proc)
389 gnutls_session_t state = proc->gnutls_state;
390 int ret;
391 bool non_blocking = proc->is_non_blocking_client;
393 if (proc->gnutls_complete_negotiation_p)
394 non_blocking = false;
396 if (non_blocking)
397 proc->gnutls_p = true;
401 ret = gnutls_handshake (state);
402 emacs_gnutls_handle_error (state, ret);
403 QUIT;
405 while (ret < 0
406 && gnutls_error_is_fatal (ret) == 0
407 && ! non_blocking);
409 proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
411 if (ret == GNUTLS_E_SUCCESS)
413 /* Here we're finally done. */
414 proc->gnutls_initstage = GNUTLS_STAGE_READY;
416 else
418 /* check_memory_full (gnutls_alert_send_appropriate (state, ret)); */
420 return ret;
423 static int
424 emacs_gnutls_handshake (struct Lisp_Process *proc)
426 gnutls_session_t state = proc->gnutls_state;
428 if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO)
429 return -1;
431 if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET)
433 #ifdef WINDOWSNT
434 /* On W32 we cannot transfer socket handles between different runtime
435 libraries, so we tell GnuTLS to use our special push/pull
436 functions. */
437 gnutls_transport_set_ptr2 (state,
438 (gnutls_transport_ptr_t) proc,
439 (gnutls_transport_ptr_t) proc);
440 gnutls_transport_set_push_function (state, &emacs_gnutls_push);
441 gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
443 /* For non blocking sockets or other custom made pull/push
444 functions the gnutls_transport_set_lowat must be called, with
445 a zero low water mark value. (GnuTLS 2.10.4 documentation)
447 (Note: this is probably not strictly necessary as the lowat
448 value is only used when no custom pull/push functions are
449 set.) */
450 /* According to GnuTLS NEWS file, lowat level has been set to
451 zero by default in version 2.11.1, and the function
452 gnutls_transport_set_lowat was removed from the library in
453 version 2.99.0. */
454 if (!gnutls_check_version ("2.11.1"))
455 gnutls_transport_set_lowat (state, 0);
456 #else
457 /* This is how GnuTLS takes sockets: as file descriptors passed
458 in. For an Emacs process socket, infd and outfd are the
459 same but we use this two-argument version for clarity. */
460 gnutls_transport_set_ptr2 (state,
461 (void *) (intptr_t) proc->infd,
462 (void *) (intptr_t) proc->outfd);
463 #endif
465 proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
468 return gnutls_try_handshake (proc);
471 ptrdiff_t
472 emacs_gnutls_record_check_pending (gnutls_session_t state)
474 return gnutls_record_check_pending (state);
477 #ifdef WINDOWSNT
478 void
479 emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
481 gnutls_transport_set_errno (state, err);
483 #endif
485 ptrdiff_t
486 emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
488 ssize_t rtnval = 0;
489 ptrdiff_t bytes_written;
490 gnutls_session_t state = proc->gnutls_state;
492 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
494 errno = EAGAIN;
495 return 0;
498 bytes_written = 0;
500 while (nbyte > 0)
502 rtnval = gnutls_record_send (state, buf, nbyte);
504 if (rtnval < 0)
506 if (rtnval == GNUTLS_E_INTERRUPTED)
507 continue;
508 else
510 /* If we get GNUTLS_E_AGAIN, then set errno
511 appropriately so that send_process retries the
512 correct way instead of erroring out. */
513 if (rtnval == GNUTLS_E_AGAIN)
514 errno = EAGAIN;
515 break;
519 buf += rtnval;
520 nbyte -= rtnval;
521 bytes_written += rtnval;
524 emacs_gnutls_handle_error (state, rtnval);
525 return (bytes_written);
528 ptrdiff_t
529 emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
531 ssize_t rtnval;
532 gnutls_session_t state = proc->gnutls_state;
534 if (proc->gnutls_initstage != GNUTLS_STAGE_READY)
536 errno = EAGAIN;
537 return -1;
540 rtnval = gnutls_record_recv (state, buf, nbyte);
541 if (rtnval >= 0)
542 return rtnval;
543 else if (rtnval == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
544 /* The peer closed the connection. */
545 return 0;
546 else if (emacs_gnutls_handle_error (state, rtnval))
547 /* non-fatal error */
548 return -1;
549 else {
550 /* a fatal error occurred */
551 return 0;
555 /* Report a GnuTLS error to the user.
556 Return true if the error code was successfully handled. */
557 static bool
558 emacs_gnutls_handle_error (gnutls_session_t session, int err)
560 int max_log_level = 0;
562 bool ret;
563 const char *str;
565 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
566 if (err >= 0)
567 return 1;
569 check_memory_full (err);
571 max_log_level = global_gnutls_log_level;
573 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
575 str = gnutls_strerror (err);
576 if (!str)
577 str = "unknown";
579 if (gnutls_error_is_fatal (err))
581 ret = 0;
582 GNUTLS_LOG2 (1, max_log_level, "fatal error:", str);
584 else
586 ret = 1;
588 switch (err)
590 case GNUTLS_E_AGAIN:
591 GNUTLS_LOG2 (3,
592 max_log_level,
593 "retry:",
594 str);
595 default:
596 GNUTLS_LOG2 (1,
597 max_log_level,
598 "non-fatal error:",
599 str);
603 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
604 || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
606 int alert = gnutls_alert_get (session);
607 int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
608 str = gnutls_alert_get_name (alert);
609 if (!str)
610 str = "unknown";
612 GNUTLS_LOG2 (level, max_log_level, "Received alert: ", str);
614 return ret;
617 /* convert an integer error to a Lisp_Object; it will be either a
618 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
619 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
620 to Qt. */
621 static Lisp_Object
622 gnutls_make_error (int err)
624 switch (err)
626 case GNUTLS_E_SUCCESS:
627 return Qt;
628 case GNUTLS_E_AGAIN:
629 return Qgnutls_e_again;
630 case GNUTLS_E_INTERRUPTED:
631 return Qgnutls_e_interrupted;
632 case GNUTLS_E_INVALID_SESSION:
633 return Qgnutls_e_invalid_session;
636 check_memory_full (err);
637 return make_number (err);
640 Lisp_Object
641 emacs_gnutls_deinit (Lisp_Object proc)
643 int log_level;
645 CHECK_PROCESS (proc);
647 if (! XPROCESS (proc)->gnutls_p)
648 return Qnil;
650 log_level = XPROCESS (proc)->gnutls_log_level;
652 if (XPROCESS (proc)->gnutls_x509_cred)
654 GNUTLS_LOG (2, log_level, "Deallocating x509 credentials");
655 gnutls_certificate_free_credentials (XPROCESS (proc)->gnutls_x509_cred);
656 XPROCESS (proc)->gnutls_x509_cred = NULL;
659 if (XPROCESS (proc)->gnutls_anon_cred)
661 GNUTLS_LOG (2, log_level, "Deallocating anon credentials");
662 gnutls_anon_free_client_credentials (XPROCESS (proc)->gnutls_anon_cred);
663 XPROCESS (proc)->gnutls_anon_cred = NULL;
666 if (XPROCESS (proc)->gnutls_state)
668 gnutls_deinit (XPROCESS (proc)->gnutls_state);
669 XPROCESS (proc)->gnutls_state = NULL;
670 if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
671 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
674 XPROCESS (proc)->gnutls_p = false;
675 return Qt;
678 DEFUN ("gnutls-asynchronous-parameters", Fgnutls_asynchronous_parameters,
679 Sgnutls_asynchronous_parameters, 2, 2, 0,
680 doc: /* Mark this process as being a pre-init GnuTLS process.
681 The second parameter is the list of parameters to feed to gnutls-boot
682 to finish setting up the connection. */)
683 (Lisp_Object proc, Lisp_Object params)
685 CHECK_PROCESS (proc);
687 XPROCESS (proc)->gnutls_boot_parameters = params;
688 return Qnil;
691 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage, Sgnutls_get_initstage, 1, 1, 0,
692 doc: /* Return the GnuTLS init stage of process PROC.
693 See also `gnutls-boot'. */)
694 (Lisp_Object proc)
696 CHECK_PROCESS (proc);
698 return make_number (GNUTLS_INITSTAGE (proc));
701 DEFUN ("gnutls-errorp", Fgnutls_errorp, Sgnutls_errorp, 1, 1, 0,
702 doc: /* Return t if ERROR indicates a GnuTLS problem.
703 ERROR is an integer or a symbol with an integer `gnutls-code' property.
704 usage: (gnutls-errorp ERROR) */
705 attributes: const)
706 (Lisp_Object err)
708 if (EQ (err, Qt)
709 || EQ (err, Qgnutls_e_again))
710 return Qnil;
712 return Qt;
715 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp, Sgnutls_error_fatalp, 1, 1, 0,
716 doc: /* Return non-nil if ERROR is fatal.
717 ERROR is an integer or a symbol with an integer `gnutls-code' property.
718 Usage: (gnutls-error-fatalp ERROR) */)
719 (Lisp_Object err)
721 Lisp_Object code;
723 if (EQ (err, Qt)) return Qnil;
725 if (SYMBOLP (err))
727 code = Fget (err, Qgnutls_code);
728 if (NUMBERP (code))
730 err = code;
732 else
734 error ("Symbol has no numeric gnutls-code property");
738 if (! TYPE_RANGED_INTEGERP (int, err))
739 error ("Not an error symbol or code");
741 if (0 == gnutls_error_is_fatal (XINT (err)))
742 return Qnil;
744 return Qt;
747 DEFUN ("gnutls-error-string", Fgnutls_error_string, Sgnutls_error_string, 1, 1, 0,
748 doc: /* Return a description of ERROR.
749 ERROR is an integer or a symbol with an integer `gnutls-code' property.
750 usage: (gnutls-error-string ERROR) */)
751 (Lisp_Object err)
753 Lisp_Object code;
755 if (EQ (err, Qt)) return build_string ("Not an error");
757 if (SYMBOLP (err))
759 code = Fget (err, Qgnutls_code);
760 if (NUMBERP (code))
762 err = code;
764 else
766 return build_string ("Symbol has no numeric gnutls-code property");
770 if (! TYPE_RANGED_INTEGERP (int, err))
771 return build_string ("Not an error symbol or code");
773 return build_string (gnutls_strerror (XINT (err)));
776 DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
777 doc: /* Deallocate GnuTLS resources associated with process PROC.
778 See also `gnutls-init'. */)
779 (Lisp_Object proc)
781 return emacs_gnutls_deinit (proc);
784 static Lisp_Object
785 gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
787 ptrdiff_t prefix_length = strlen (prefix);
788 ptrdiff_t retlen;
789 if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
790 || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
791 string_overflow ();
792 Lisp_Object ret = make_uninit_string (retlen);
793 char *string = SSDATA (ret);
794 strcpy (string, prefix);
796 for (ptrdiff_t i = 0; i < buf_size; i++)
797 sprintf (string + i * 3 + prefix_length,
798 i == buf_size - 1 ? "%02x" : "%02x:",
799 buf[i]);
801 return ret;
804 static Lisp_Object
805 gnutls_certificate_details (gnutls_x509_crt_t cert)
807 Lisp_Object res = Qnil;
808 int err;
809 size_t buf_size;
811 /* Version. */
813 int version = gnutls_x509_crt_get_version (cert);
814 check_memory_full (version);
815 if (version >= GNUTLS_E_SUCCESS)
816 res = nconc2 (res, list2 (intern (":version"),
817 make_number (version)));
820 /* Serial. */
821 buf_size = 0;
822 err = gnutls_x509_crt_get_serial (cert, NULL, &buf_size);
823 check_memory_full (err);
824 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
826 void *serial = xmalloc (buf_size);
827 err = gnutls_x509_crt_get_serial (cert, serial, &buf_size);
828 check_memory_full (err);
829 if (err >= GNUTLS_E_SUCCESS)
830 res = nconc2 (res, list2 (intern (":serial-number"),
831 gnutls_hex_string (serial, buf_size, "")));
832 xfree (serial);
835 /* Issuer. */
836 buf_size = 0;
837 err = gnutls_x509_crt_get_issuer_dn (cert, NULL, &buf_size);
838 check_memory_full (err);
839 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
841 char *dn = xmalloc (buf_size);
842 err = gnutls_x509_crt_get_issuer_dn (cert, dn, &buf_size);
843 check_memory_full (err);
844 if (err >= GNUTLS_E_SUCCESS)
845 res = nconc2 (res, list2 (intern (":issuer"),
846 make_string (dn, buf_size)));
847 xfree (dn);
850 /* Validity. */
852 /* Add 1 to the buffer size, since 1900 is added to tm_year and
853 that might add 1 to the year length. */
854 char buf[INT_STRLEN_BOUND (int) + 1 + sizeof "-12-31"];
855 struct tm t;
856 time_t tim = gnutls_x509_crt_get_activation_time (cert);
858 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
859 res = nconc2 (res, list2 (intern (":valid-from"), build_string (buf)));
861 tim = gnutls_x509_crt_get_expiration_time (cert);
862 if (gmtime_r (&tim, &t) && strftime (buf, sizeof buf, "%Y-%m-%d", &t))
863 res = nconc2 (res, list2 (intern (":valid-to"), build_string (buf)));
866 /* Subject. */
867 buf_size = 0;
868 err = gnutls_x509_crt_get_dn (cert, NULL, &buf_size);
869 check_memory_full (err);
870 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
872 char *dn = xmalloc (buf_size);
873 err = gnutls_x509_crt_get_dn (cert, dn, &buf_size);
874 check_memory_full (err);
875 if (err >= GNUTLS_E_SUCCESS)
876 res = nconc2 (res, list2 (intern (":subject"),
877 make_string (dn, buf_size)));
878 xfree (dn);
881 /* Versions older than 2.11 doesn't have these four functions. */
882 #if GNUTLS_VERSION_NUMBER >= 0x020b00
883 /* SubjectPublicKeyInfo. */
885 unsigned int bits;
887 err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
888 check_memory_full (err);
889 if (err >= GNUTLS_E_SUCCESS)
891 const char *name = gnutls_pk_algorithm_get_name (err);
892 if (name)
893 res = nconc2 (res, list2 (intern (":public-key-algorithm"),
894 build_string (name)));
896 name = gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
897 (err, bits));
898 res = nconc2 (res, list2 (intern (":certificate-security-level"),
899 build_string (name)));
903 /* Unique IDs. */
904 buf_size = 0;
905 err = gnutls_x509_crt_get_issuer_unique_id (cert, NULL, &buf_size);
906 check_memory_full (err);
907 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
909 char *buf = xmalloc (buf_size);
910 err = gnutls_x509_crt_get_issuer_unique_id (cert, buf, &buf_size);
911 check_memory_full (err);
912 if (err >= GNUTLS_E_SUCCESS)
913 res = nconc2 (res, list2 (intern (":issuer-unique-id"),
914 make_string (buf, buf_size)));
915 xfree (buf);
918 buf_size = 0;
919 err = gnutls_x509_crt_get_subject_unique_id (cert, NULL, &buf_size);
920 check_memory_full (err);
921 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
923 char *buf = xmalloc (buf_size);
924 err = gnutls_x509_crt_get_subject_unique_id (cert, buf, &buf_size);
925 check_memory_full (err);
926 if (err >= GNUTLS_E_SUCCESS)
927 res = nconc2 (res, list2 (intern (":subject-unique-id"),
928 make_string (buf, buf_size)));
929 xfree (buf);
931 #endif
933 /* Signature. */
934 err = gnutls_x509_crt_get_signature_algorithm (cert);
935 check_memory_full (err);
936 if (err >= GNUTLS_E_SUCCESS)
938 const char *name = gnutls_sign_get_name (err);
939 if (name)
940 res = nconc2 (res, list2 (intern (":signature-algorithm"),
941 build_string (name)));
944 /* Public key ID. */
945 buf_size = 0;
946 err = gnutls_x509_crt_get_key_id (cert, 0, NULL, &buf_size);
947 check_memory_full (err);
948 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
950 void *buf = xmalloc (buf_size);
951 err = gnutls_x509_crt_get_key_id (cert, 0, buf, &buf_size);
952 check_memory_full (err);
953 if (err >= GNUTLS_E_SUCCESS)
954 res = nconc2 (res, list2 (intern (":public-key-id"),
955 gnutls_hex_string (buf, buf_size, "sha1:")));
956 xfree (buf);
959 /* Certificate fingerprint. */
960 buf_size = 0;
961 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
962 NULL, &buf_size);
963 check_memory_full (err);
964 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
966 void *buf = xmalloc (buf_size);
967 err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1,
968 buf, &buf_size);
969 check_memory_full (err);
970 if (err >= GNUTLS_E_SUCCESS)
971 res = nconc2 (res, list2 (intern (":certificate-id"),
972 gnutls_hex_string (buf, buf_size, "sha1:")));
973 xfree (buf);
976 return res;
979 DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_describe, Sgnutls_peer_status_warning_describe, 1, 1, 0,
980 doc: /* Describe the warning of a GnuTLS peer status from `gnutls-peer-status'. */)
981 (Lisp_Object status_symbol)
983 CHECK_SYMBOL (status_symbol);
985 if (EQ (status_symbol, intern (":invalid")))
986 return build_string ("certificate could not be verified");
988 if (EQ (status_symbol, intern (":revoked")))
989 return build_string ("certificate was revoked (CRL)");
991 if (EQ (status_symbol, intern (":self-signed")))
992 return build_string ("certificate signer was not found (self-signed)");
994 if (EQ (status_symbol, intern (":unknown-ca")))
995 return build_string ("the certificate was signed by an unknown "
996 "and therefore untrusted authority");
998 if (EQ (status_symbol, intern (":not-ca")))
999 return build_string ("certificate signer is not a CA");
1001 if (EQ (status_symbol, intern (":insecure")))
1002 return build_string ("certificate was signed with an insecure algorithm");
1004 if (EQ (status_symbol, intern (":not-activated")))
1005 return build_string ("certificate is not yet activated");
1007 if (EQ (status_symbol, intern (":expired")))
1008 return build_string ("certificate has expired");
1010 if (EQ (status_symbol, intern (":no-host-match")))
1011 return build_string ("certificate host does not match hostname");
1013 return Qnil;
1016 DEFUN ("gnutls-peer-status", Fgnutls_peer_status, Sgnutls_peer_status, 1, 1, 0,
1017 doc: /* Describe a GnuTLS PROC peer certificate and any warnings about it.
1018 The return value is a property list with top-level keys :warnings and
1019 :certificate. The :warnings entry is a list of symbols you can describe with
1020 `gnutls-peer-status-warning-describe'. */)
1021 (Lisp_Object proc)
1023 Lisp_Object warnings = Qnil, result = Qnil;
1024 unsigned int verification;
1025 gnutls_session_t state;
1027 CHECK_PROCESS (proc);
1029 if (GNUTLS_INITSTAGE (proc) != GNUTLS_STAGE_READY)
1030 return Qnil;
1032 /* Then collect any warnings already computed by the handshake. */
1033 verification = XPROCESS (proc)->gnutls_peer_verification;
1035 if (verification & GNUTLS_CERT_INVALID)
1036 warnings = Fcons (intern (":invalid"), warnings);
1038 if (verification & GNUTLS_CERT_REVOKED)
1039 warnings = Fcons (intern (":revoked"), warnings);
1041 if (verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
1042 warnings = Fcons (intern (":unknown-ca"), warnings);
1044 if (verification & GNUTLS_CERT_SIGNER_NOT_CA)
1045 warnings = Fcons (intern (":not-ca"), warnings);
1047 if (verification & GNUTLS_CERT_INSECURE_ALGORITHM)
1048 warnings = Fcons (intern (":insecure"), warnings);
1050 if (verification & GNUTLS_CERT_NOT_ACTIVATED)
1051 warnings = Fcons (intern (":not-activated"), warnings);
1053 if (verification & GNUTLS_CERT_EXPIRED)
1054 warnings = Fcons (intern (":expired"), warnings);
1056 if (XPROCESS (proc)->gnutls_extra_peer_verification &
1057 CERTIFICATE_NOT_MATCHING)
1058 warnings = Fcons (intern (":no-host-match"), warnings);
1060 /* This could get called in the INIT stage, when the certificate is
1061 not yet set. */
1062 if (XPROCESS (proc)->gnutls_certificate != NULL &&
1063 gnutls_x509_crt_check_issuer(XPROCESS (proc)->gnutls_certificate,
1064 XPROCESS (proc)->gnutls_certificate))
1065 warnings = Fcons (intern (":self-signed"), warnings);
1067 if (!NILP (warnings))
1068 result = list2 (intern (":warnings"), 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 result = nconc2 (result, list2
1074 (intern (":certificate"),
1075 gnutls_certificate_details (XPROCESS (proc)->gnutls_certificate)));
1077 state = XPROCESS (proc)->gnutls_state;
1079 /* Diffie-Hellman prime bits. */
1081 int bits = gnutls_dh_get_prime_bits (state);
1082 check_memory_full (bits);
1083 if (bits > 0)
1084 result = nconc2 (result, list2 (intern (":diffie-hellman-prime-bits"),
1085 make_number (bits)));
1088 /* Key exchange. */
1089 result = nconc2
1090 (result, list2 (intern (":key-exchange"),
1091 build_string (gnutls_kx_get_name
1092 (gnutls_kx_get (state)))));
1094 /* Protocol name. */
1095 result = nconc2
1096 (result, list2 (intern (":protocol"),
1097 build_string (gnutls_protocol_get_name
1098 (gnutls_protocol_get_version (state)))));
1100 /* Cipher name. */
1101 result = nconc2
1102 (result, list2 (intern (":cipher"),
1103 build_string (gnutls_cipher_get_name
1104 (gnutls_cipher_get (state)))));
1106 /* MAC name. */
1107 result = nconc2
1108 (result, list2 (intern (":mac"),
1109 build_string (gnutls_mac_get_name
1110 (gnutls_mac_get (state)))));
1113 return result;
1116 /* Initialize global GnuTLS state to defaults.
1117 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1118 Return zero on success. */
1119 Lisp_Object
1120 emacs_gnutls_global_init (void)
1122 int ret = GNUTLS_E_SUCCESS;
1124 if (!gnutls_global_initialized)
1126 ret = gnutls_global_init ();
1127 if (ret == GNUTLS_E_SUCCESS)
1128 gnutls_global_initialized = 1;
1131 return gnutls_make_error (ret);
1134 static bool
1135 gnutls_ip_address_p (char *string)
1137 char c;
1139 while ((c = *string++) != 0)
1140 if (! ((c == '.' || c == ':' || (c >= '0' && c <= '9'))))
1141 return false;
1143 return true;
1146 #if 0
1147 /* Deinitialize global GnuTLS state.
1148 See also `gnutls-global-init'. */
1149 static Lisp_Object
1150 emacs_gnutls_global_deinit (void)
1152 if (gnutls_global_initialized)
1153 gnutls_global_deinit ();
1155 gnutls_global_initialized = 0;
1157 return gnutls_make_error (GNUTLS_E_SUCCESS);
1159 #endif
1161 static void ATTRIBUTE_FORMAT_PRINTF (2, 3)
1162 boot_error (struct Lisp_Process *p, const char *m, ...)
1164 va_list ap;
1165 va_start (ap, m);
1166 if (p->is_non_blocking_client)
1167 pset_status (p, list2 (Qfailed, vformat_string (m, ap)));
1168 else
1169 verror (m, ap);
1170 va_end (ap);
1173 Lisp_Object
1174 gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1176 int ret;
1177 struct Lisp_Process *p = XPROCESS (proc);
1178 gnutls_session_t state = p->gnutls_state;
1179 unsigned int peer_verification;
1180 Lisp_Object warnings;
1181 int max_log_level = p->gnutls_log_level;
1182 Lisp_Object hostname, verify_error;
1183 bool verify_error_all = false;
1184 char *c_hostname;
1186 if (NILP (proplist))
1187 proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters));
1189 verify_error = Fplist_get (proplist, QCverify_error);
1190 hostname = Fplist_get (proplist, QChostname);
1192 if (EQ (verify_error, Qt))
1193 verify_error_all = true;
1194 else if (NILP (Flistp (verify_error)))
1196 boot_error (p,
1197 "gnutls-boot: invalid :verify_error parameter (not a list)");
1198 return Qnil;
1201 if (!STRINGP (hostname))
1203 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1204 return Qnil;
1206 c_hostname = SSDATA (hostname);
1208 /* Now verify the peer, following
1209 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1210 The peer should present at least one certificate in the chain; do a
1211 check of the certificate's hostname with
1212 gnutls_x509_crt_check_hostname against :hostname. */
1214 ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
1215 if (ret < GNUTLS_E_SUCCESS)
1216 return gnutls_make_error (ret);
1218 XPROCESS (proc)->gnutls_peer_verification = peer_verification;
1220 warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
1221 if (!NILP (warnings))
1223 for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail))
1225 Lisp_Object warning = XCAR (tail);
1226 Lisp_Object message = Fgnutls_peer_status_warning_describe (warning);
1227 if (!NILP (message))
1228 GNUTLS_LOG2 (1, max_log_level, "verification:", SSDATA (message));
1232 if (peer_verification != 0)
1234 if (verify_error_all
1235 || !NILP (Fmember (QCtrustfiles, verify_error)))
1237 emacs_gnutls_deinit (proc);
1238 boot_error (p,
1239 "Certificate validation failed %s, verification code %x",
1240 c_hostname, peer_verification);
1241 return Qnil;
1243 else
1245 GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
1246 c_hostname);
1250 /* Up to here the process is the same for X.509 certificates and
1251 OpenPGP keys. From now on X.509 certificates are assumed. This
1252 can be easily extended to work with openpgp keys as well. */
1253 if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
1255 gnutls_x509_crt_t gnutls_verify_cert;
1256 const gnutls_datum_t *gnutls_verify_cert_list;
1257 unsigned int gnutls_verify_cert_list_size;
1259 ret = gnutls_x509_crt_init (&gnutls_verify_cert);
1260 if (ret < GNUTLS_E_SUCCESS)
1261 return gnutls_make_error (ret);
1263 gnutls_verify_cert_list
1264 = gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
1266 if (gnutls_verify_cert_list == NULL)
1268 gnutls_x509_crt_deinit (gnutls_verify_cert);
1269 emacs_gnutls_deinit (proc);
1270 boot_error (p, "No x509 certificate was found\n");
1271 return Qnil;
1274 /* Check only the first certificate in the given chain. */
1275 ret = gnutls_x509_crt_import (gnutls_verify_cert,
1276 &gnutls_verify_cert_list[0],
1277 GNUTLS_X509_FMT_DER);
1279 if (ret < GNUTLS_E_SUCCESS)
1281 gnutls_x509_crt_deinit (gnutls_verify_cert);
1282 return gnutls_make_error (ret);
1285 XPROCESS (proc)->gnutls_certificate = gnutls_verify_cert;
1287 int err = gnutls_x509_crt_check_hostname (gnutls_verify_cert,
1288 c_hostname);
1289 check_memory_full (err);
1290 if (!err)
1292 XPROCESS (proc)->gnutls_extra_peer_verification
1293 |= CERTIFICATE_NOT_MATCHING;
1294 if (verify_error_all
1295 || !NILP (Fmember (QChostname, verify_error)))
1297 gnutls_x509_crt_deinit (gnutls_verify_cert);
1298 emacs_gnutls_deinit (proc);
1299 boot_error (p, "The x509 certificate does not match \"%s\"",
1300 c_hostname);
1301 return Qnil;
1303 else
1304 GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
1305 c_hostname);
1309 /* Set this flag only if the whole initialization succeeded. */
1310 XPROCESS (proc)->gnutls_p = true;
1312 return gnutls_make_error (ret);
1315 DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1316 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1317 Currently only client mode is supported. Return a success/failure
1318 value you can check with `gnutls-errorp'.
1320 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
1321 PROPLIST is a property list with the following keys:
1323 :hostname is a string naming the remote host.
1325 :priority is a GnuTLS priority string, defaults to "NORMAL".
1327 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
1329 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
1331 :keylist is an alist of PEM-encoded key files and PEM-encoded
1332 certificates for `gnutls-x509pki'.
1334 :callbacks is an alist of callback functions, see below.
1336 :loglevel is the debug level requested from GnuTLS, try 4.
1338 :verify-flags is a bitset as per GnuTLS'
1339 gnutls_certificate_set_verify_flags.
1341 :verify-hostname-error is ignored. Pass :hostname in :verify-error
1342 instead.
1344 :verify-error is a list of symbols to express verification checks or
1345 t to do all checks. Currently it can contain `:trustfiles' and
1346 `:hostname' to verify the certificate or the hostname respectively.
1348 :min-prime-bits is the minimum accepted number of bits the client will
1349 accept in Diffie-Hellman key exchange.
1351 :complete-negotiation, if non-nil, will make negotiation complete
1352 before returning even on non-blocking sockets.
1354 The debug level will be set for this process AND globally for GnuTLS.
1355 So if you set it higher or lower at any point, it affects global
1356 debugging.
1358 Note that the priority is set on the client. The server does not use
1359 the protocols's priority except for disabling protocols that were not
1360 specified.
1362 Processes must be initialized with this function before other GnuTLS
1363 functions are used. This function allocates resources which can only
1364 be deallocated by calling `gnutls-deinit' or by calling it again.
1366 The callbacks alist can have a `verify' key, associated with a
1367 verification function (UNUSED).
1369 Each authentication type may need additional information in order to
1370 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
1371 one trustfile (usually a CA bundle). */)
1372 (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist)
1374 int ret = GNUTLS_E_SUCCESS;
1375 int max_log_level = 0;
1377 gnutls_session_t state;
1378 gnutls_certificate_credentials_t x509_cred = NULL;
1379 gnutls_anon_client_credentials_t anon_cred = NULL;
1380 Lisp_Object global_init;
1381 char const *priority_string_ptr = "NORMAL"; /* default priority string. */
1382 char *c_hostname;
1384 /* Placeholders for the property list elements. */
1385 Lisp_Object priority_string;
1386 Lisp_Object trustfiles;
1387 Lisp_Object crlfiles;
1388 Lisp_Object keylist;
1389 /* Lisp_Object callbacks; */
1390 Lisp_Object loglevel;
1391 Lisp_Object hostname;
1392 Lisp_Object prime_bits;
1393 struct Lisp_Process *p = XPROCESS (proc);
1395 CHECK_PROCESS (proc);
1396 CHECK_SYMBOL (type);
1397 CHECK_LIST (proplist);
1399 if (NILP (Fgnutls_available_p ()))
1401 boot_error (p, "GnuTLS not available");
1402 return Qnil;
1405 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon))
1407 boot_error (p, "Invalid GnuTLS credential type");
1408 return Qnil;
1411 hostname = Fplist_get (proplist, QChostname);
1412 priority_string = Fplist_get (proplist, QCpriority);
1413 trustfiles = Fplist_get (proplist, QCtrustfiles);
1414 keylist = Fplist_get (proplist, QCkeylist);
1415 crlfiles = Fplist_get (proplist, QCcrlfiles);
1416 loglevel = Fplist_get (proplist, QCloglevel);
1417 prime_bits = Fplist_get (proplist, QCmin_prime_bits);
1419 if (!STRINGP (hostname))
1421 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1422 return Qnil;
1424 c_hostname = SSDATA (hostname);
1426 state = XPROCESS (proc)->gnutls_state;
1428 if (TYPE_RANGED_INTEGERP (int, loglevel))
1430 gnutls_global_set_log_function (gnutls_log_function);
1431 #ifdef HAVE_GNUTLS3
1432 gnutls_global_set_audit_log_function (gnutls_audit_log_function);
1433 #endif
1434 gnutls_global_set_log_level (XINT (loglevel));
1435 max_log_level = XINT (loglevel);
1436 XPROCESS (proc)->gnutls_log_level = max_log_level;
1439 GNUTLS_LOG2 (1, max_log_level, "connecting to host:", c_hostname);
1441 /* Always initialize globals. */
1442 global_init = emacs_gnutls_global_init ();
1443 if (! NILP (Fgnutls_errorp (global_init)))
1444 return global_init;
1446 /* Before allocating new credentials, deallocate any credentials
1447 that PROC might already have. */
1448 emacs_gnutls_deinit (proc);
1450 /* Mark PROC as a GnuTLS process. */
1451 XPROCESS (proc)->gnutls_state = NULL;
1452 XPROCESS (proc)->gnutls_x509_cred = NULL;
1453 XPROCESS (proc)->gnutls_anon_cred = NULL;
1454 pset_gnutls_cred_type (XPROCESS (proc), type);
1455 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_EMPTY;
1457 GNUTLS_LOG (1, max_log_level, "allocating credentials");
1458 if (EQ (type, Qgnutls_x509pki))
1460 Lisp_Object verify_flags;
1461 unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1463 GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
1464 check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
1465 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1467 verify_flags = Fplist_get (proplist, QCverify_flags);
1468 if (NUMBERP (verify_flags))
1470 gnutls_verify_flags = XINT (verify_flags);
1471 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1473 else if (NILP (verify_flags))
1474 GNUTLS_LOG (2, max_log_level, "using default verification flags");
1475 else
1476 GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
1478 gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
1480 else /* Qgnutls_anon: */
1482 GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
1483 check_memory_full (gnutls_anon_allocate_client_credentials (&anon_cred));
1484 XPROCESS (proc)->gnutls_anon_cred = anon_cred;
1487 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_ALLOC;
1489 if (EQ (type, Qgnutls_x509pki))
1491 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
1492 int file_format = GNUTLS_X509_FMT_PEM;
1493 Lisp_Object tail;
1495 #if GNUTLS_VERSION_MAJOR + \
1496 (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
1497 ret = gnutls_certificate_set_x509_system_trust (x509_cred);
1498 if (ret < GNUTLS_E_SUCCESS)
1500 check_memory_full (ret);
1501 GNUTLS_LOG2i (4, max_log_level,
1502 "setting system trust failed with code ", ret);
1504 #endif
1506 for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
1508 Lisp_Object trustfile = XCAR (tail);
1509 if (STRINGP (trustfile))
1511 GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
1512 SSDATA (trustfile));
1513 trustfile = ENCODE_FILE (trustfile);
1514 #ifdef WINDOWSNT
1515 /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
1516 file names on Windows, we need to re-encode the file
1517 name using the current ANSI codepage. */
1518 trustfile = ansi_encode_filename (trustfile);
1519 #endif
1520 ret = gnutls_certificate_set_x509_trust_file
1521 (x509_cred,
1522 SSDATA (trustfile),
1523 file_format);
1525 if (ret < GNUTLS_E_SUCCESS)
1526 return gnutls_make_error (ret);
1528 else
1530 emacs_gnutls_deinit (proc);
1531 boot_error (p, "Invalid trustfile");
1532 return Qnil;
1536 for (tail = crlfiles; CONSP (tail); tail = XCDR (tail))
1538 Lisp_Object crlfile = XCAR (tail);
1539 if (STRINGP (crlfile))
1541 GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
1542 SSDATA (crlfile));
1543 crlfile = ENCODE_FILE (crlfile);
1544 #ifdef WINDOWSNT
1545 crlfile = ansi_encode_filename (crlfile);
1546 #endif
1547 ret = gnutls_certificate_set_x509_crl_file
1548 (x509_cred, SSDATA (crlfile), file_format);
1550 if (ret < GNUTLS_E_SUCCESS)
1551 return gnutls_make_error (ret);
1553 else
1555 emacs_gnutls_deinit (proc);
1556 boot_error (p, "Invalid CRL file");
1557 return Qnil;
1561 for (tail = keylist; CONSP (tail); tail = XCDR (tail))
1563 Lisp_Object keyfile = Fcar (XCAR (tail));
1564 Lisp_Object certfile = Fcar (Fcdr (XCAR (tail)));
1565 if (STRINGP (keyfile) && STRINGP (certfile))
1567 GNUTLS_LOG2 (1, max_log_level, "setting the client key file: ",
1568 SSDATA (keyfile));
1569 GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
1570 SSDATA (certfile));
1571 keyfile = ENCODE_FILE (keyfile);
1572 certfile = ENCODE_FILE (certfile);
1573 #ifdef WINDOWSNT
1574 keyfile = ansi_encode_filename (keyfile);
1575 certfile = ansi_encode_filename (certfile);
1576 #endif
1577 ret = gnutls_certificate_set_x509_key_file
1578 (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
1580 if (ret < GNUTLS_E_SUCCESS)
1581 return gnutls_make_error (ret);
1583 else
1585 emacs_gnutls_deinit (proc);
1586 boot_error (p, STRINGP (keyfile) ? "Invalid client cert file"
1587 : "Invalid client key file");
1588 return Qnil;
1593 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES;
1594 GNUTLS_LOG (1, max_log_level, "gnutls callbacks");
1595 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS;
1597 /* Call gnutls_init here: */
1599 GNUTLS_LOG (1, max_log_level, "gnutls_init");
1600 ret = gnutls_init (&state, GNUTLS_CLIENT);
1601 XPROCESS (proc)->gnutls_state = state;
1602 if (ret < GNUTLS_E_SUCCESS)
1603 return gnutls_make_error (ret);
1604 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT;
1606 if (STRINGP (priority_string))
1608 priority_string_ptr = SSDATA (priority_string);
1609 GNUTLS_LOG2 (1, max_log_level, "got non-default priority string:",
1610 priority_string_ptr);
1612 else
1614 GNUTLS_LOG2 (1, max_log_level, "using default priority string:",
1615 priority_string_ptr);
1618 GNUTLS_LOG (1, max_log_level, "setting the priority string");
1619 ret = gnutls_priority_set_direct (state, priority_string_ptr, NULL);
1620 if (ret < GNUTLS_E_SUCCESS)
1621 return gnutls_make_error (ret);
1623 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_PRIORITY;
1625 if (INTEGERP (prime_bits))
1626 gnutls_dh_set_prime_bits (state, XUINT (prime_bits));
1628 ret = EQ (type, Qgnutls_x509pki)
1629 ? gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred)
1630 : gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
1631 if (ret < GNUTLS_E_SUCCESS)
1632 return gnutls_make_error (ret);
1634 if (!gnutls_ip_address_p (c_hostname))
1636 ret = gnutls_server_name_set (state, GNUTLS_NAME_DNS, c_hostname,
1637 strlen (c_hostname));
1638 if (ret < GNUTLS_E_SUCCESS)
1639 return gnutls_make_error (ret);
1642 XPROCESS (proc)->gnutls_complete_negotiation_p =
1643 !NILP (Fplist_get (proplist, QCcomplete_negotiation));
1644 GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
1645 ret = emacs_gnutls_handshake (XPROCESS (proc));
1646 if (ret < GNUTLS_E_SUCCESS)
1647 return gnutls_make_error (ret);
1649 return gnutls_verify_boot (proc, proplist);
1652 DEFUN ("gnutls-bye", Fgnutls_bye,
1653 Sgnutls_bye, 2, 2, 0,
1654 doc: /* Terminate current GnuTLS connection for process PROC.
1655 The connection should have been initiated using `gnutls-handshake'.
1657 If CONT is not nil the TLS connection gets terminated and further
1658 receives and sends will be disallowed. If the return value is zero you
1659 may continue using the connection. If CONT is nil, GnuTLS actually
1660 sends an alert containing a close request and waits for the peer to
1661 reply with the same message. In order to reuse the connection you
1662 should wait for an EOF from the peer.
1664 This function may also return `gnutls-e-again', or
1665 `gnutls-e-interrupted'. */)
1666 (Lisp_Object proc, Lisp_Object cont)
1668 gnutls_session_t state;
1669 int ret;
1671 CHECK_PROCESS (proc);
1673 state = XPROCESS (proc)->gnutls_state;
1675 gnutls_x509_crt_deinit (XPROCESS (proc)->gnutls_certificate);
1677 ret = gnutls_bye (state, NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
1679 return gnutls_make_error (ret);
1682 #endif /* HAVE_GNUTLS */
1684 DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
1685 doc: /* Return t if GnuTLS is available in this instance of Emacs. */)
1686 (void)
1688 #ifdef HAVE_GNUTLS
1689 # ifdef WINDOWSNT
1690 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
1691 if (CONSP (found))
1692 return XCDR (found);
1693 else
1695 Lisp_Object status;
1696 status = init_gnutls_functions () ? Qt : Qnil;
1697 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
1698 return status;
1700 # else /* !WINDOWSNT */
1701 return Qt;
1702 # endif /* !WINDOWSNT */
1703 #else /* !HAVE_GNUTLS */
1704 return Qnil;
1705 #endif /* !HAVE_GNUTLS */
1708 void
1709 syms_of_gnutls (void)
1711 DEFSYM (Qlibgnutls_version, "libgnutls-version");
1712 Fset (Qlibgnutls_version,
1713 #ifdef HAVE_GNUTLS
1714 make_number (GNUTLS_VERSION_MAJOR * 10000
1715 + GNUTLS_VERSION_MINOR * 100
1716 + GNUTLS_VERSION_PATCH)
1717 #else
1718 make_number (-1)
1719 #endif
1721 #ifdef HAVE_GNUTLS
1722 gnutls_global_initialized = 0;
1724 DEFSYM (Qgnutls_code, "gnutls-code");
1725 DEFSYM (Qgnutls_anon, "gnutls-anon");
1726 DEFSYM (Qgnutls_x509pki, "gnutls-x509pki");
1728 /* The following are for the property list of 'gnutls-boot'. */
1729 DEFSYM (QChostname, ":hostname");
1730 DEFSYM (QCpriority, ":priority");
1731 DEFSYM (QCtrustfiles, ":trustfiles");
1732 DEFSYM (QCkeylist, ":keylist");
1733 DEFSYM (QCcrlfiles, ":crlfiles");
1734 DEFSYM (QCmin_prime_bits, ":min-prime-bits");
1735 DEFSYM (QCloglevel, ":loglevel");
1736 DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
1737 DEFSYM (QCverify_flags, ":verify-flags");
1738 DEFSYM (QCverify_error, ":verify-error");
1740 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
1741 Fput (Qgnutls_e_interrupted, Qgnutls_code,
1742 make_number (GNUTLS_E_INTERRUPTED));
1744 DEFSYM (Qgnutls_e_again, "gnutls-e-again");
1745 Fput (Qgnutls_e_again, Qgnutls_code,
1746 make_number (GNUTLS_E_AGAIN));
1748 DEFSYM (Qgnutls_e_invalid_session, "gnutls-e-invalid-session");
1749 Fput (Qgnutls_e_invalid_session, Qgnutls_code,
1750 make_number (GNUTLS_E_INVALID_SESSION));
1752 DEFSYM (Qgnutls_e_not_ready_for_handshake, "gnutls-e-not-ready-for-handshake");
1753 Fput (Qgnutls_e_not_ready_for_handshake, Qgnutls_code,
1754 make_number (GNUTLS_E_APPLICATION_ERROR_MIN));
1756 defsubr (&Sgnutls_get_initstage);
1757 defsubr (&Sgnutls_asynchronous_parameters);
1758 defsubr (&Sgnutls_errorp);
1759 defsubr (&Sgnutls_error_fatalp);
1760 defsubr (&Sgnutls_error_string);
1761 defsubr (&Sgnutls_boot);
1762 defsubr (&Sgnutls_deinit);
1763 defsubr (&Sgnutls_bye);
1764 defsubr (&Sgnutls_peer_status);
1765 defsubr (&Sgnutls_peer_status_warning_describe);
1767 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
1768 doc: /* Logging level used by the GnuTLS functions.
1769 Set this larger than 0 to get debug output in the *Messages* buffer.
1770 1 is for important messages, 2 is for debug data, and higher numbers
1771 are as per the GnuTLS logging conventions. */);
1772 global_gnutls_log_level = 0;
1774 #endif /* HAVE_GNUTLS */
1776 defsubr (&Sgnutls_available_p);