1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2013 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
26 #include <gnutls/gnutls.h>
33 static bool emacs_gnutls_handle_error (gnutls_session_t
, int);
35 static Lisp_Object Qgnutls_dll
;
36 static Lisp_Object Qgnutls_code
;
37 static Lisp_Object Qgnutls_anon
, Qgnutls_x509pki
;
38 static Lisp_Object Qgnutls_e_interrupted
, Qgnutls_e_again
,
39 Qgnutls_e_invalid_session
, Qgnutls_e_not_ready_for_handshake
;
40 static bool gnutls_global_initialized
;
42 /* The following are for the property list of `gnutls-boot'. */
43 static Lisp_Object QCgnutls_bootprop_priority
;
44 static Lisp_Object QCgnutls_bootprop_trustfiles
;
45 static Lisp_Object QCgnutls_bootprop_keylist
;
46 static Lisp_Object QCgnutls_bootprop_crlfiles
;
47 static Lisp_Object QCgnutls_bootprop_callbacks
;
48 static Lisp_Object QCgnutls_bootprop_loglevel
;
49 static Lisp_Object QCgnutls_bootprop_hostname
;
50 static Lisp_Object QCgnutls_bootprop_min_prime_bits
;
51 static Lisp_Object QCgnutls_bootprop_verify_flags
;
52 static Lisp_Object QCgnutls_bootprop_verify_hostname_error
;
54 /* Callback keys for `gnutls-boot'. Unused currently. */
55 static Lisp_Object QCgnutls_bootprop_callbacks_verify
;
57 static void gnutls_log_function (int, const char *);
58 static void gnutls_log_function2 (int, const char*, const char*);
60 static void gnutls_audit_log_function (gnutls_session_t
, const char *);
66 /* Macro for defining functions that will be loaded from the GnuTLS DLL. */
67 #define DEF_GNUTLS_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
69 /* Macro for loading GnuTLS functions from the library. */
70 #define LOAD_GNUTLS_FN(lib,func) { \
71 fn_##func = (void *) GetProcAddress (lib, #func); \
72 if (!fn_##func) return 0; \
75 DEF_GNUTLS_FN (gnutls_alert_description_t
, gnutls_alert_get
,
77 DEF_GNUTLS_FN (const char *, gnutls_alert_get_name
,
78 (gnutls_alert_description_t
));
79 DEF_GNUTLS_FN (int, gnutls_alert_send_appropriate
, (gnutls_session_t
, int));
80 DEF_GNUTLS_FN (int, gnutls_anon_allocate_client_credentials
,
81 (gnutls_anon_client_credentials_t
*));
82 DEF_GNUTLS_FN (void, gnutls_anon_free_client_credentials
,
83 (gnutls_anon_client_credentials_t
));
84 DEF_GNUTLS_FN (int, gnutls_bye
, (gnutls_session_t
, gnutls_close_request_t
));
85 DEF_GNUTLS_FN (int, gnutls_certificate_allocate_credentials
,
86 (gnutls_certificate_credentials_t
*));
87 DEF_GNUTLS_FN (void, gnutls_certificate_free_credentials
,
88 (gnutls_certificate_credentials_t
));
89 DEF_GNUTLS_FN (const gnutls_datum_t
*, gnutls_certificate_get_peers
,
90 (gnutls_session_t
, unsigned int *));
91 DEF_GNUTLS_FN (void, gnutls_certificate_set_verify_flags
,
92 (gnutls_certificate_credentials_t
, unsigned int));
93 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_crl_file
,
94 (gnutls_certificate_credentials_t
, const char *,
95 gnutls_x509_crt_fmt_t
));
96 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_key_file
,
97 (gnutls_certificate_credentials_t
, const char *, const char *,
98 gnutls_x509_crt_fmt_t
));
99 DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_trust_file
,
100 (gnutls_certificate_credentials_t
, const char *,
101 gnutls_x509_crt_fmt_t
));
102 DEF_GNUTLS_FN (gnutls_certificate_type_t
, gnutls_certificate_type_get
,
104 DEF_GNUTLS_FN (int, gnutls_certificate_verify_peers2
,
105 (gnutls_session_t
, unsigned int *));
106 DEF_GNUTLS_FN (int, gnutls_credentials_set
,
107 (gnutls_session_t
, gnutls_credentials_type_t
, void *));
108 DEF_GNUTLS_FN (void, gnutls_deinit
, (gnutls_session_t
));
109 DEF_GNUTLS_FN (void, gnutls_dh_set_prime_bits
,
110 (gnutls_session_t
, unsigned int));
111 DEF_GNUTLS_FN (int, gnutls_error_is_fatal
, (int));
112 DEF_GNUTLS_FN (int, gnutls_global_init
, (void));
113 DEF_GNUTLS_FN (void, gnutls_global_set_log_function
, (gnutls_log_func
));
115 DEF_GNUTLS_FN (void, gnutls_global_set_audit_log_function
, (gnutls_audit_log_func
));
117 DEF_GNUTLS_FN (void, gnutls_global_set_log_level
, (int));
118 DEF_GNUTLS_FN (void, gnutls_global_set_mem_functions
,
119 (gnutls_alloc_function
, gnutls_alloc_function
,
120 gnutls_is_secure_function
, gnutls_realloc_function
,
121 gnutls_free_function
));
122 DEF_GNUTLS_FN (int, gnutls_handshake
, (gnutls_session_t
));
123 DEF_GNUTLS_FN (int, gnutls_init
, (gnutls_session_t
*, gnutls_connection_end_t
));
124 DEF_GNUTLS_FN (int, gnutls_priority_set_direct
,
125 (gnutls_session_t
, const char *, const char **));
126 DEF_GNUTLS_FN (size_t, gnutls_record_check_pending
, (gnutls_session_t
));
127 DEF_GNUTLS_FN (ssize_t
, gnutls_record_recv
, (gnutls_session_t
, void *, size_t));
128 DEF_GNUTLS_FN (ssize_t
, gnutls_record_send
,
129 (gnutls_session_t
, const void *, size_t));
130 DEF_GNUTLS_FN (const char *, gnutls_strerror
, (int));
131 DEF_GNUTLS_FN (void, gnutls_transport_set_errno
, (gnutls_session_t
, int));
132 DEF_GNUTLS_FN (const char *, gnutls_check_version
, (const char *));
133 DEF_GNUTLS_FN (void, gnutls_transport_set_lowat
, (gnutls_session_t
, int));
134 DEF_GNUTLS_FN (void, gnutls_transport_set_ptr2
,
135 (gnutls_session_t
, gnutls_transport_ptr_t
,
136 gnutls_transport_ptr_t
));
137 DEF_GNUTLS_FN (void, gnutls_transport_set_pull_function
,
138 (gnutls_session_t
, gnutls_pull_func
));
139 DEF_GNUTLS_FN (void, gnutls_transport_set_push_function
,
140 (gnutls_session_t
, gnutls_push_func
));
141 DEF_GNUTLS_FN (int, gnutls_x509_crt_check_hostname
,
142 (gnutls_x509_crt_t
, const char *));
143 DEF_GNUTLS_FN (void, gnutls_x509_crt_deinit
, (gnutls_x509_crt_t
));
144 DEF_GNUTLS_FN (int, gnutls_x509_crt_import
,
145 (gnutls_x509_crt_t
, const gnutls_datum_t
*,
146 gnutls_x509_crt_fmt_t
));
147 DEF_GNUTLS_FN (int, gnutls_x509_crt_init
, (gnutls_x509_crt_t
*));
150 init_gnutls_functions (void)
153 int max_log_level
= 1;
155 if (!(library
= w32_delayed_load (Qgnutls_dll
)))
157 GNUTLS_LOG (1, max_log_level
, "GnuTLS library not found");
161 LOAD_GNUTLS_FN (library
, gnutls_alert_get
);
162 LOAD_GNUTLS_FN (library
, gnutls_alert_get_name
);
163 LOAD_GNUTLS_FN (library
, gnutls_alert_send_appropriate
);
164 LOAD_GNUTLS_FN (library
, gnutls_anon_allocate_client_credentials
);
165 LOAD_GNUTLS_FN (library
, gnutls_anon_free_client_credentials
);
166 LOAD_GNUTLS_FN (library
, gnutls_bye
);
167 LOAD_GNUTLS_FN (library
, gnutls_certificate_allocate_credentials
);
168 LOAD_GNUTLS_FN (library
, gnutls_certificate_free_credentials
);
169 LOAD_GNUTLS_FN (library
, gnutls_certificate_get_peers
);
170 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_verify_flags
);
171 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_crl_file
);
172 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_key_file
);
173 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_trust_file
);
174 LOAD_GNUTLS_FN (library
, gnutls_certificate_type_get
);
175 LOAD_GNUTLS_FN (library
, gnutls_certificate_verify_peers2
);
176 LOAD_GNUTLS_FN (library
, gnutls_credentials_set
);
177 LOAD_GNUTLS_FN (library
, gnutls_deinit
);
178 LOAD_GNUTLS_FN (library
, gnutls_dh_set_prime_bits
);
179 LOAD_GNUTLS_FN (library
, gnutls_error_is_fatal
);
180 LOAD_GNUTLS_FN (library
, gnutls_global_init
);
181 LOAD_GNUTLS_FN (library
, gnutls_global_set_log_function
);
183 LOAD_GNUTLS_FN (library
, gnutls_global_set_audit_log_function
);
185 LOAD_GNUTLS_FN (library
, gnutls_global_set_log_level
);
186 LOAD_GNUTLS_FN (library
, gnutls_global_set_mem_functions
);
187 LOAD_GNUTLS_FN (library
, gnutls_handshake
);
188 LOAD_GNUTLS_FN (library
, gnutls_init
);
189 LOAD_GNUTLS_FN (library
, gnutls_priority_set_direct
);
190 LOAD_GNUTLS_FN (library
, gnutls_record_check_pending
);
191 LOAD_GNUTLS_FN (library
, gnutls_record_recv
);
192 LOAD_GNUTLS_FN (library
, gnutls_record_send
);
193 LOAD_GNUTLS_FN (library
, gnutls_strerror
);
194 LOAD_GNUTLS_FN (library
, gnutls_transport_set_errno
);
195 LOAD_GNUTLS_FN (library
, gnutls_check_version
);
196 /* We don't need to call gnutls_transport_set_lowat in GnuTLS 2.11.1
197 and later, and the function was removed entirely in 3.0.0. */
198 if (!fn_gnutls_check_version ("2.11.1"))
199 LOAD_GNUTLS_FN (library
, gnutls_transport_set_lowat
);
200 LOAD_GNUTLS_FN (library
, gnutls_transport_set_ptr2
);
201 LOAD_GNUTLS_FN (library
, gnutls_transport_set_pull_function
);
202 LOAD_GNUTLS_FN (library
, gnutls_transport_set_push_function
);
203 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_check_hostname
);
204 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_deinit
);
205 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_import
);
206 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_init
);
208 max_log_level
= global_gnutls_log_level
;
211 Lisp_Object name
= CAR_SAFE (Fget (Qgnutls_dll
, QCloaded_from
));
212 GNUTLS_LOG2 (1, max_log_level
, "GnuTLS library loaded:",
213 STRINGP (name
) ? (const char *) SDATA (name
) : "unknown");
219 #else /* !WINDOWSNT */
221 #define fn_gnutls_alert_get gnutls_alert_get
222 #define fn_gnutls_alert_get_name gnutls_alert_get_name
223 #define fn_gnutls_alert_send_appropriate gnutls_alert_send_appropriate
224 #define fn_gnutls_anon_allocate_client_credentials gnutls_anon_allocate_client_credentials
225 #define fn_gnutls_anon_free_client_credentials gnutls_anon_free_client_credentials
226 #define fn_gnutls_bye gnutls_bye
227 #define fn_gnutls_certificate_allocate_credentials gnutls_certificate_allocate_credentials
228 #define fn_gnutls_certificate_free_credentials gnutls_certificate_free_credentials
229 #define fn_gnutls_certificate_get_peers gnutls_certificate_get_peers
230 #define fn_gnutls_certificate_set_verify_flags gnutls_certificate_set_verify_flags
231 #define fn_gnutls_certificate_set_x509_crl_file gnutls_certificate_set_x509_crl_file
232 #define fn_gnutls_certificate_set_x509_key_file gnutls_certificate_set_x509_key_file
233 #define fn_gnutls_certificate_set_x509_trust_file gnutls_certificate_set_x509_trust_file
234 #define fn_gnutls_certificate_type_get gnutls_certificate_type_get
235 #define fn_gnutls_certificate_verify_peers2 gnutls_certificate_verify_peers2
236 #define fn_gnutls_credentials_set gnutls_credentials_set
237 #define fn_gnutls_deinit gnutls_deinit
238 #define fn_gnutls_dh_set_prime_bits gnutls_dh_set_prime_bits
239 #define fn_gnutls_error_is_fatal gnutls_error_is_fatal
240 #define fn_gnutls_global_init gnutls_global_init
241 #define fn_gnutls_global_set_log_function gnutls_global_set_log_function
243 #define fn_gnutls_global_set_audit_log_function gnutls_global_set_audit_log_function
245 #define fn_gnutls_global_set_log_level gnutls_global_set_log_level
246 #define fn_gnutls_global_set_mem_functions gnutls_global_set_mem_functions
247 #define fn_gnutls_handshake gnutls_handshake
248 #define fn_gnutls_init gnutls_init
249 #define fn_gnutls_priority_set_direct gnutls_priority_set_direct
250 #define fn_gnutls_record_check_pending gnutls_record_check_pending
251 #define fn_gnutls_record_recv gnutls_record_recv
252 #define fn_gnutls_record_send gnutls_record_send
253 #define fn_gnutls_strerror gnutls_strerror
255 #define fn_gnutls_transport_set_errno gnutls_transport_set_errno
257 #define fn_gnutls_transport_set_ptr2 gnutls_transport_set_ptr2
258 #define fn_gnutls_x509_crt_check_hostname gnutls_x509_crt_check_hostname
259 #define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit
260 #define fn_gnutls_x509_crt_import gnutls_x509_crt_import
261 #define fn_gnutls_x509_crt_init gnutls_x509_crt_init
263 #endif /* !WINDOWSNT */
267 /* Function to log a simple audit message. */
269 gnutls_audit_log_function (gnutls_session_t session
, const char* string
)
271 if (global_gnutls_log_level
>= 1)
273 message ("gnutls.c: [audit] %s", string
);
278 /* Function to log a simple message. */
280 gnutls_log_function (int level
, const char* string
)
282 message ("gnutls.c: [%d] %s", level
, string
);
285 /* Function to log a message and a string. */
287 gnutls_log_function2 (int level
, const char* string
, const char* extra
)
289 message ("gnutls.c: [%d] %s %s", level
, string
, extra
);
292 /* Function to log a message and an integer. */
294 gnutls_log_function2i (int level
, const char* string
, int extra
)
296 message ("gnutls.c: [%d] %s %d", level
, string
, extra
);
300 emacs_gnutls_handshake (struct Lisp_Process
*proc
)
302 gnutls_session_t state
= proc
->gnutls_state
;
305 if (proc
->gnutls_initstage
< GNUTLS_STAGE_HANDSHAKE_CANDO
)
308 if (proc
->gnutls_initstage
< GNUTLS_STAGE_TRANSPORT_POINTERS_SET
)
311 /* On W32 we cannot transfer socket handles between different runtime
312 libraries, so we tell GnuTLS to use our special push/pull
314 fn_gnutls_transport_set_ptr2 (state
,
315 (gnutls_transport_ptr_t
) proc
,
316 (gnutls_transport_ptr_t
) proc
);
317 fn_gnutls_transport_set_push_function (state
, &emacs_gnutls_push
);
318 fn_gnutls_transport_set_pull_function (state
, &emacs_gnutls_pull
);
320 /* For non blocking sockets or other custom made pull/push
321 functions the gnutls_transport_set_lowat must be called, with
322 a zero low water mark value. (GnuTLS 2.10.4 documentation)
324 (Note: this is probably not strictly necessary as the lowat
325 value is only used when no custom pull/push functions are
327 /* According to GnuTLS NEWS file, lowat level has been set to
328 zero by default in version 2.11.1, and the function
329 gnutls_transport_set_lowat was removed from the library in
331 if (!fn_gnutls_check_version ("2.11.1"))
332 fn_gnutls_transport_set_lowat (state
, 0);
334 /* This is how GnuTLS takes sockets: as file descriptors passed
335 in. For an Emacs process socket, infd and outfd are the
336 same but we use this two-argument version for clarity. */
337 fn_gnutls_transport_set_ptr2 (state
,
338 (gnutls_transport_ptr_t
) (long) proc
->infd
,
339 (gnutls_transport_ptr_t
) (long) proc
->outfd
);
342 proc
->gnutls_initstage
= GNUTLS_STAGE_TRANSPORT_POINTERS_SET
;
347 ret
= fn_gnutls_handshake (state
);
348 emacs_gnutls_handle_error (state
, ret
);
351 while (ret
< 0 && fn_gnutls_error_is_fatal (ret
) == 0);
353 proc
->gnutls_initstage
= GNUTLS_STAGE_HANDSHAKE_TRIED
;
355 if (ret
== GNUTLS_E_SUCCESS
)
357 /* Here we're finally done. */
358 proc
->gnutls_initstage
= GNUTLS_STAGE_READY
;
362 fn_gnutls_alert_send_appropriate (state
, ret
);
368 emacs_gnutls_record_check_pending (gnutls_session_t state
)
370 return fn_gnutls_record_check_pending (state
);
375 emacs_gnutls_transport_set_errno (gnutls_session_t state
, int err
)
377 fn_gnutls_transport_set_errno (state
, err
);
382 emacs_gnutls_write (struct Lisp_Process
*proc
, const char *buf
, ptrdiff_t nbyte
)
385 ptrdiff_t bytes_written
;
386 gnutls_session_t state
= proc
->gnutls_state
;
388 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
)
398 rtnval
= fn_gnutls_record_send (state
, buf
, nbyte
);
402 if (rtnval
== GNUTLS_E_INTERRUPTED
)
406 /* If we get GNUTLS_E_AGAIN, then set errno
407 appropriately so that send_process retries the
408 correct way instead of erroring out. */
409 if (rtnval
== GNUTLS_E_AGAIN
)
417 bytes_written
+= rtnval
;
420 emacs_gnutls_handle_error (state
, rtnval
);
421 return (bytes_written
);
425 emacs_gnutls_read (struct Lisp_Process
*proc
, char *buf
, ptrdiff_t nbyte
)
428 gnutls_session_t state
= proc
->gnutls_state
;
430 int log_level
= proc
->gnutls_log_level
;
432 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
)
434 /* If the handshake count is under the limit, try the handshake
435 again and increment the handshake count. This count is kept
436 per process (connection), not globally. */
437 if (proc
->gnutls_handshakes_tried
< GNUTLS_EMACS_HANDSHAKES_LIMIT
)
439 proc
->gnutls_handshakes_tried
++;
440 emacs_gnutls_handshake (proc
);
441 GNUTLS_LOG2i (5, log_level
, "Retried handshake",
442 proc
->gnutls_handshakes_tried
);
446 GNUTLS_LOG (2, log_level
, "Giving up on handshake; resetting retries");
447 proc
->gnutls_handshakes_tried
= 0;
450 rtnval
= fn_gnutls_record_recv (state
, buf
, nbyte
);
453 else if (rtnval
== GNUTLS_E_UNEXPECTED_PACKET_LENGTH
)
454 /* The peer closed the connection. */
456 else if (emacs_gnutls_handle_error (state
, rtnval
))
457 /* non-fatal error */
460 /* a fatal error occurred */
465 /* Report a GnuTLS error to the user.
466 Return true if the error code was successfully handled. */
468 emacs_gnutls_handle_error (gnutls_session_t session
, int err
)
470 int max_log_level
= 0;
475 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
479 max_log_level
= global_gnutls_log_level
;
481 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
483 str
= fn_gnutls_strerror (err
);
487 if (fn_gnutls_error_is_fatal (err
))
490 GNUTLS_LOG2 (0, max_log_level
, "fatal error:", str
);
511 if (err
== GNUTLS_E_WARNING_ALERT_RECEIVED
512 || err
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
514 int alert
= fn_gnutls_alert_get (session
);
515 int level
= (err
== GNUTLS_E_FATAL_ALERT_RECEIVED
) ? 0 : 1;
516 str
= fn_gnutls_alert_get_name (alert
);
520 GNUTLS_LOG2 (level
, max_log_level
, "Received alert: ", str
);
525 /* convert an integer error to a Lisp_Object; it will be either a
526 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
527 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
530 gnutls_make_error (int err
)
534 case GNUTLS_E_SUCCESS
:
537 return Qgnutls_e_again
;
538 case GNUTLS_E_INTERRUPTED
:
539 return Qgnutls_e_interrupted
;
540 case GNUTLS_E_INVALID_SESSION
:
541 return Qgnutls_e_invalid_session
;
544 return make_number (err
);
548 emacs_gnutls_deinit (Lisp_Object proc
)
552 CHECK_PROCESS (proc
);
554 if (XPROCESS (proc
)->gnutls_p
== 0)
557 log_level
= XPROCESS (proc
)->gnutls_log_level
;
559 if (XPROCESS (proc
)->gnutls_x509_cred
)
561 GNUTLS_LOG (2, log_level
, "Deallocating x509 credentials");
562 fn_gnutls_certificate_free_credentials (XPROCESS (proc
)->gnutls_x509_cred
);
563 XPROCESS (proc
)->gnutls_x509_cred
= NULL
;
566 if (XPROCESS (proc
)->gnutls_anon_cred
)
568 GNUTLS_LOG (2, log_level
, "Deallocating anon credentials");
569 fn_gnutls_anon_free_client_credentials (XPROCESS (proc
)->gnutls_anon_cred
);
570 XPROCESS (proc
)->gnutls_anon_cred
= NULL
;
573 if (XPROCESS (proc
)->gnutls_state
)
575 fn_gnutls_deinit (XPROCESS (proc
)->gnutls_state
);
576 XPROCESS (proc
)->gnutls_state
= NULL
;
577 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_INIT
)
578 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
- 1;
581 XPROCESS (proc
)->gnutls_p
= 0;
585 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage
, Sgnutls_get_initstage
, 1, 1, 0,
586 doc
: /* Return the GnuTLS init stage of process PROC.
587 See also `gnutls-boot'. */)
590 CHECK_PROCESS (proc
);
592 return make_number (GNUTLS_INITSTAGE (proc
));
595 DEFUN ("gnutls-errorp", Fgnutls_errorp
, Sgnutls_errorp
, 1, 1, 0,
596 doc
: /* Return t if ERROR indicates a GnuTLS problem.
597 ERROR is an integer or a symbol with an integer `gnutls-code' property.
598 usage: (gnutls-errorp ERROR) */)
601 if (EQ (err
, Qt
)) return Qnil
;
606 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp
, Sgnutls_error_fatalp
, 1, 1, 0,
607 doc
: /* Check if ERROR is fatal.
608 ERROR is an integer or a symbol with an integer `gnutls-code' property.
609 usage: (gnutls-error-fatalp ERROR) */)
614 if (EQ (err
, Qt
)) return Qnil
;
618 code
= Fget (err
, Qgnutls_code
);
625 error ("Symbol has no numeric gnutls-code property");
629 if (! TYPE_RANGED_INTEGERP (int, err
))
630 error ("Not an error symbol or code");
632 if (0 == fn_gnutls_error_is_fatal (XINT (err
)))
638 DEFUN ("gnutls-error-string", Fgnutls_error_string
, Sgnutls_error_string
, 1, 1, 0,
639 doc
: /* Return a description of ERROR.
640 ERROR is an integer or a symbol with an integer `gnutls-code' property.
641 usage: (gnutls-error-string ERROR) */)
646 if (EQ (err
, Qt
)) return build_string ("Not an error");
650 code
= Fget (err
, Qgnutls_code
);
657 return build_string ("Symbol has no numeric gnutls-code property");
661 if (! TYPE_RANGED_INTEGERP (int, err
))
662 return build_string ("Not an error symbol or code");
664 return build_string (fn_gnutls_strerror (XINT (err
)));
667 DEFUN ("gnutls-deinit", Fgnutls_deinit
, Sgnutls_deinit
, 1, 1, 0,
668 doc
: /* Deallocate GnuTLS resources associated with process PROC.
669 See also `gnutls-init'. */)
672 return emacs_gnutls_deinit (proc
);
675 DEFUN ("gnutls-available-p", Fgnutls_available_p
, Sgnutls_available_p
, 0, 0, 0,
676 doc
: /* Return t if GnuTLS is available in this instance of Emacs. */)
680 Lisp_Object found
= Fassq (Qgnutls_dll
, Vlibrary_cache
);
686 status
= init_gnutls_functions () ? Qt
: Qnil
;
687 Vlibrary_cache
= Fcons (Fcons (Qgnutls_dll
, status
), Vlibrary_cache
);
696 /* Initializes global GnuTLS state to defaults.
697 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
698 Returns zero on success. */
700 emacs_gnutls_global_init (void)
702 int ret
= GNUTLS_E_SUCCESS
;
704 if (!gnutls_global_initialized
)
706 fn_gnutls_global_set_mem_functions (xmalloc
, xmalloc
, NULL
,
708 ret
= fn_gnutls_global_init ();
710 gnutls_global_initialized
= 1;
712 return gnutls_make_error (ret
);
716 /* Deinitializes global GnuTLS state.
717 See also `gnutls-global-init'. */
719 emacs_gnutls_global_deinit (void)
721 if (gnutls_global_initialized
)
722 gnutls_global_deinit ();
724 gnutls_global_initialized
= 0;
726 return gnutls_make_error (GNUTLS_E_SUCCESS
);
730 DEFUN ("gnutls-boot", Fgnutls_boot
, Sgnutls_boot
, 3, 3, 0,
731 doc
: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
732 Currently only client mode is supported. Return a success/failure
733 value you can check with `gnutls-errorp'.
735 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
736 PROPLIST is a property list with the following keys:
738 :hostname is a string naming the remote host.
740 :priority is a GnuTLS priority string, defaults to "NORMAL".
742 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
744 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
746 :keylist is an alist of PEM-encoded key files and PEM-encoded
747 certificates for `gnutls-x509pki'.
749 :callbacks is an alist of callback functions, see below.
751 :loglevel is the debug level requested from GnuTLS, try 4.
753 :verify-flags is a bitset as per GnuTLS'
754 gnutls_certificate_set_verify_flags.
756 :verify-hostname-error, if non-nil, makes a hostname mismatch an
757 error. Otherwise it will be just a warning.
759 :min-prime-bits is the minimum accepted number of bits the client will
760 accept in Diffie-Hellman key exchange.
762 The debug level will be set for this process AND globally for GnuTLS.
763 So if you set it higher or lower at any point, it affects global
766 Note that the priority is set on the client. The server does not use
767 the protocols's priority except for disabling protocols that were not
770 Processes must be initialized with this function before other GnuTLS
771 functions are used. This function allocates resources which can only
772 be deallocated by calling `gnutls-deinit' or by calling it again.
774 The callbacks alist can have a `verify' key, associated with a
775 verification function (UNUSED).
777 Each authentication type may need additional information in order to
778 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
779 one trustfile (usually a CA bundle). */)
780 (Lisp_Object proc
, Lisp_Object type
, Lisp_Object proplist
)
782 int ret
= GNUTLS_E_SUCCESS
;
783 int max_log_level
= 0;
785 gnutls_session_t state
;
786 gnutls_certificate_credentials_t x509_cred
= NULL
;
787 gnutls_anon_client_credentials_t anon_cred
= NULL
;
788 Lisp_Object global_init
;
789 char const *priority_string_ptr
= "NORMAL"; /* default priority string. */
790 unsigned int peer_verification
;
793 /* Placeholders for the property list elements. */
794 Lisp_Object priority_string
;
795 Lisp_Object trustfiles
;
796 Lisp_Object crlfiles
;
798 /* Lisp_Object callbacks; */
799 Lisp_Object loglevel
;
800 Lisp_Object hostname
;
801 /* Lisp_Object verify_error; */
802 Lisp_Object verify_hostname_error
;
803 Lisp_Object prime_bits
;
805 CHECK_PROCESS (proc
);
807 CHECK_LIST (proplist
);
809 if (NILP (Fgnutls_available_p ()))
810 error ("GnuTLS not available");
812 if (!EQ (type
, Qgnutls_x509pki
) && !EQ (type
, Qgnutls_anon
))
813 error ("Invalid GnuTLS credential type");
815 hostname
= Fplist_get (proplist
, QCgnutls_bootprop_hostname
);
816 priority_string
= Fplist_get (proplist
, QCgnutls_bootprop_priority
);
817 trustfiles
= Fplist_get (proplist
, QCgnutls_bootprop_trustfiles
);
818 keylist
= Fplist_get (proplist
, QCgnutls_bootprop_keylist
);
819 crlfiles
= Fplist_get (proplist
, QCgnutls_bootprop_crlfiles
);
820 loglevel
= Fplist_get (proplist
, QCgnutls_bootprop_loglevel
);
821 verify_hostname_error
= Fplist_get (proplist
, QCgnutls_bootprop_verify_hostname_error
);
822 prime_bits
= Fplist_get (proplist
, QCgnutls_bootprop_min_prime_bits
);
824 if (!STRINGP (hostname
))
825 error ("gnutls-boot: invalid :hostname parameter");
826 c_hostname
= SSDATA (hostname
);
828 state
= XPROCESS (proc
)->gnutls_state
;
830 if (TYPE_RANGED_INTEGERP (int, loglevel
))
832 fn_gnutls_global_set_log_function (gnutls_log_function
);
834 fn_gnutls_global_set_audit_log_function (gnutls_audit_log_function
);
836 fn_gnutls_global_set_log_level (XINT (loglevel
));
837 max_log_level
= XINT (loglevel
);
838 XPROCESS (proc
)->gnutls_log_level
= max_log_level
;
841 /* always initialize globals. */
842 global_init
= emacs_gnutls_global_init ();
843 if (! NILP (Fgnutls_errorp (global_init
)))
846 /* Before allocating new credentials, deallocate any credentials
847 that PROC might already have. */
848 emacs_gnutls_deinit (proc
);
850 /* Mark PROC as a GnuTLS process. */
851 XPROCESS (proc
)->gnutls_state
= NULL
;
852 XPROCESS (proc
)->gnutls_x509_cred
= NULL
;
853 XPROCESS (proc
)->gnutls_anon_cred
= NULL
;
854 pset_gnutls_cred_type (XPROCESS (proc
), type
);
855 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_EMPTY
;
857 GNUTLS_LOG (1, max_log_level
, "allocating credentials");
858 if (EQ (type
, Qgnutls_x509pki
))
860 Lisp_Object verify_flags
;
861 unsigned int gnutls_verify_flags
= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
;
863 GNUTLS_LOG (2, max_log_level
, "allocating x509 credentials");
864 fn_gnutls_certificate_allocate_credentials (&x509_cred
);
865 XPROCESS (proc
)->gnutls_x509_cred
= x509_cred
;
867 verify_flags
= Fplist_get (proplist
, QCgnutls_bootprop_verify_flags
);
868 if (NUMBERP (verify_flags
))
870 gnutls_verify_flags
= XINT (verify_flags
);
871 GNUTLS_LOG (2, max_log_level
, "setting verification flags");
873 else if (NILP (verify_flags
))
874 GNUTLS_LOG (2, max_log_level
, "using default verification flags");
876 GNUTLS_LOG (2, max_log_level
, "ignoring invalid verify-flags");
878 fn_gnutls_certificate_set_verify_flags (x509_cred
, gnutls_verify_flags
);
880 else /* Qgnutls_anon: */
882 GNUTLS_LOG (2, max_log_level
, "allocating anon credentials");
883 fn_gnutls_anon_allocate_client_credentials (&anon_cred
);
884 XPROCESS (proc
)->gnutls_anon_cred
= anon_cred
;
887 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_ALLOC
;
889 if (EQ (type
, Qgnutls_x509pki
))
891 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
892 int file_format
= GNUTLS_X509_FMT_PEM
;
895 for (tail
= trustfiles
; CONSP (tail
); tail
= XCDR (tail
))
897 Lisp_Object trustfile
= XCAR (tail
);
898 if (STRINGP (trustfile
))
900 GNUTLS_LOG2 (1, max_log_level
, "setting the trustfile: ",
902 ret
= fn_gnutls_certificate_set_x509_trust_file
907 if (ret
< GNUTLS_E_SUCCESS
)
908 return gnutls_make_error (ret
);
912 emacs_gnutls_deinit (proc
);
913 error ("Invalid trustfile");
917 for (tail
= crlfiles
; CONSP (tail
); tail
= XCDR (tail
))
919 Lisp_Object crlfile
= XCAR (tail
);
920 if (STRINGP (crlfile
))
922 GNUTLS_LOG2 (1, max_log_level
, "setting the CRL file: ",
924 ret
= fn_gnutls_certificate_set_x509_crl_file
925 (x509_cred
, SSDATA (crlfile
), file_format
);
927 if (ret
< GNUTLS_E_SUCCESS
)
928 return gnutls_make_error (ret
);
932 emacs_gnutls_deinit (proc
);
933 error ("Invalid CRL file");
937 for (tail
= keylist
; CONSP (tail
); tail
= XCDR (tail
))
939 Lisp_Object keyfile
= Fcar (XCAR (tail
));
940 Lisp_Object certfile
= Fcar (Fcdr (XCAR (tail
)));
941 if (STRINGP (keyfile
) && STRINGP (certfile
))
943 GNUTLS_LOG2 (1, max_log_level
, "setting the client key file: ",
945 GNUTLS_LOG2 (1, max_log_level
, "setting the client cert file: ",
947 ret
= fn_gnutls_certificate_set_x509_key_file
948 (x509_cred
, SSDATA (certfile
), SSDATA (keyfile
), file_format
);
950 if (ret
< GNUTLS_E_SUCCESS
)
951 return gnutls_make_error (ret
);
955 emacs_gnutls_deinit (proc
);
956 error (STRINGP (keyfile
) ? "Invalid client cert file"
957 : "Invalid client key file");
962 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_FILES
;
963 GNUTLS_LOG (1, max_log_level
, "gnutls callbacks");
964 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CALLBACKS
;
966 /* Call gnutls_init here: */
968 GNUTLS_LOG (1, max_log_level
, "gnutls_init");
969 ret
= fn_gnutls_init (&state
, GNUTLS_CLIENT
);
970 XPROCESS (proc
)->gnutls_state
= state
;
971 if (ret
< GNUTLS_E_SUCCESS
)
972 return gnutls_make_error (ret
);
973 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
;
975 if (STRINGP (priority_string
))
977 priority_string_ptr
= SSDATA (priority_string
);
978 GNUTLS_LOG2 (1, max_log_level
, "got non-default priority string:",
979 priority_string_ptr
);
983 GNUTLS_LOG2 (1, max_log_level
, "using default priority string:",
984 priority_string_ptr
);
987 GNUTLS_LOG (1, max_log_level
, "setting the priority string");
988 ret
= fn_gnutls_priority_set_direct (state
,
991 if (ret
< GNUTLS_E_SUCCESS
)
992 return gnutls_make_error (ret
);
994 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_PRIORITY
;
996 if (INTEGERP (prime_bits
))
997 fn_gnutls_dh_set_prime_bits (state
, XUINT (prime_bits
));
999 ret
= EQ (type
, Qgnutls_x509pki
)
1000 ? fn_gnutls_credentials_set (state
, GNUTLS_CRD_CERTIFICATE
, x509_cred
)
1001 : fn_gnutls_credentials_set (state
, GNUTLS_CRD_ANON
, anon_cred
);
1002 if (ret
< GNUTLS_E_SUCCESS
)
1003 return gnutls_make_error (ret
);
1005 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_SET
;
1006 ret
= emacs_gnutls_handshake (XPROCESS (proc
));
1007 if (ret
< GNUTLS_E_SUCCESS
)
1008 return gnutls_make_error (ret
);
1010 /* Now verify the peer, following
1011 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
1012 The peer should present at least one certificate in the chain; do a
1013 check of the certificate's hostname with
1014 gnutls_x509_crt_check_hostname() against :hostname. */
1016 ret
= fn_gnutls_certificate_verify_peers2 (state
, &peer_verification
);
1017 if (ret
< GNUTLS_E_SUCCESS
)
1018 return gnutls_make_error (ret
);
1020 if (XINT (loglevel
) > 0 && peer_verification
& GNUTLS_CERT_INVALID
)
1021 message ("%s certificate could not be verified.", c_hostname
);
1023 if (peer_verification
& GNUTLS_CERT_REVOKED
)
1024 GNUTLS_LOG2 (1, max_log_level
, "certificate was revoked (CRL):",
1027 if (peer_verification
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
1028 GNUTLS_LOG2 (1, max_log_level
, "certificate signer was not found:",
1031 if (peer_verification
& GNUTLS_CERT_SIGNER_NOT_CA
)
1032 GNUTLS_LOG2 (1, max_log_level
, "certificate signer is not a CA:",
1035 if (peer_verification
& GNUTLS_CERT_INSECURE_ALGORITHM
)
1036 GNUTLS_LOG2 (1, max_log_level
,
1037 "certificate was signed with an insecure algorithm:",
1040 if (peer_verification
& GNUTLS_CERT_NOT_ACTIVATED
)
1041 GNUTLS_LOG2 (1, max_log_level
, "certificate is not yet activated:",
1044 if (peer_verification
& GNUTLS_CERT_EXPIRED
)
1045 GNUTLS_LOG2 (1, max_log_level
, "certificate has expired:",
1048 if (peer_verification
!= 0)
1050 if (NILP (verify_hostname_error
))
1051 GNUTLS_LOG2 (1, max_log_level
, "certificate validation failed:",
1055 emacs_gnutls_deinit (proc
);
1056 error ("Certificate validation failed %s, verification code %d",
1057 c_hostname
, peer_verification
);
1061 /* Up to here the process is the same for X.509 certificates and
1062 OpenPGP keys. From now on X.509 certificates are assumed. This
1063 can be easily extended to work with openpgp keys as well. */
1064 if (fn_gnutls_certificate_type_get (state
) == GNUTLS_CRT_X509
)
1066 gnutls_x509_crt_t gnutls_verify_cert
;
1067 const gnutls_datum_t
*gnutls_verify_cert_list
;
1068 unsigned int gnutls_verify_cert_list_size
;
1070 ret
= fn_gnutls_x509_crt_init (&gnutls_verify_cert
);
1071 if (ret
< GNUTLS_E_SUCCESS
)
1072 return gnutls_make_error (ret
);
1074 gnutls_verify_cert_list
=
1075 fn_gnutls_certificate_get_peers (state
, &gnutls_verify_cert_list_size
);
1077 if (gnutls_verify_cert_list
== NULL
)
1079 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1080 emacs_gnutls_deinit (proc
);
1081 error ("No x509 certificate was found\n");
1084 /* We only check the first certificate in the given chain. */
1085 ret
= fn_gnutls_x509_crt_import (gnutls_verify_cert
,
1086 &gnutls_verify_cert_list
[0],
1087 GNUTLS_X509_FMT_DER
);
1089 if (ret
< GNUTLS_E_SUCCESS
)
1091 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1092 return gnutls_make_error (ret
);
1095 if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert
, c_hostname
))
1097 if (NILP (verify_hostname_error
))
1098 GNUTLS_LOG2 (1, max_log_level
, "x509 certificate does not match:",
1102 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1103 emacs_gnutls_deinit (proc
);
1104 error ("The x509 certificate does not match \"%s\"", c_hostname
);
1107 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1110 /* Set this flag only if the whole initialization succeeded. */
1111 XPROCESS (proc
)->gnutls_p
= 1;
1113 return gnutls_make_error (ret
);
1116 DEFUN ("gnutls-bye", Fgnutls_bye
,
1117 Sgnutls_bye
, 2, 2, 0,
1118 doc
: /* Terminate current GnuTLS connection for process PROC.
1119 The connection should have been initiated using `gnutls-handshake'.
1121 If CONT is not nil the TLS connection gets terminated and further
1122 receives and sends will be disallowed. If the return value is zero you
1123 may continue using the connection. If CONT is nil, GnuTLS actually
1124 sends an alert containing a close request and waits for the peer to
1125 reply with the same message. In order to reuse the connection you
1126 should wait for an EOF from the peer.
1128 This function may also return `gnutls-e-again', or
1129 `gnutls-e-interrupted'. */)
1130 (Lisp_Object proc
, Lisp_Object cont
)
1132 gnutls_session_t state
;
1135 CHECK_PROCESS (proc
);
1137 state
= XPROCESS (proc
)->gnutls_state
;
1139 ret
= fn_gnutls_bye (state
,
1140 NILP (cont
) ? GNUTLS_SHUT_RDWR
: GNUTLS_SHUT_WR
);
1142 return gnutls_make_error (ret
);
1146 syms_of_gnutls (void)
1148 gnutls_global_initialized
= 0;
1150 DEFSYM (Qgnutls_dll
, "gnutls");
1151 DEFSYM (Qgnutls_code
, "gnutls-code");
1152 DEFSYM (Qgnutls_anon
, "gnutls-anon");
1153 DEFSYM (Qgnutls_x509pki
, "gnutls-x509pki");
1154 DEFSYM (QCgnutls_bootprop_hostname
, ":hostname");
1155 DEFSYM (QCgnutls_bootprop_priority
, ":priority");
1156 DEFSYM (QCgnutls_bootprop_trustfiles
, ":trustfiles");
1157 DEFSYM (QCgnutls_bootprop_keylist
, ":keylist");
1158 DEFSYM (QCgnutls_bootprop_crlfiles
, ":crlfiles");
1159 DEFSYM (QCgnutls_bootprop_callbacks
, ":callbacks");
1160 DEFSYM (QCgnutls_bootprop_callbacks_verify
, "verify");
1161 DEFSYM (QCgnutls_bootprop_min_prime_bits
, ":min-prime-bits");
1162 DEFSYM (QCgnutls_bootprop_loglevel
, ":loglevel");
1163 DEFSYM (QCgnutls_bootprop_verify_flags
, ":verify-flags");
1164 DEFSYM (QCgnutls_bootprop_verify_hostname_error
, ":verify-hostname-error");
1166 DEFSYM (Qgnutls_e_interrupted
, "gnutls-e-interrupted");
1167 Fput (Qgnutls_e_interrupted
, Qgnutls_code
,
1168 make_number (GNUTLS_E_INTERRUPTED
));
1170 DEFSYM (Qgnutls_e_again
, "gnutls-e-again");
1171 Fput (Qgnutls_e_again
, Qgnutls_code
,
1172 make_number (GNUTLS_E_AGAIN
));
1174 DEFSYM (Qgnutls_e_invalid_session
, "gnutls-e-invalid-session");
1175 Fput (Qgnutls_e_invalid_session
, Qgnutls_code
,
1176 make_number (GNUTLS_E_INVALID_SESSION
));
1178 DEFSYM (Qgnutls_e_not_ready_for_handshake
, "gnutls-e-not-ready-for-handshake");
1179 Fput (Qgnutls_e_not_ready_for_handshake
, Qgnutls_code
,
1180 make_number (GNUTLS_E_APPLICATION_ERROR_MIN
));
1182 defsubr (&Sgnutls_get_initstage
);
1183 defsubr (&Sgnutls_errorp
);
1184 defsubr (&Sgnutls_error_fatalp
);
1185 defsubr (&Sgnutls_error_string
);
1186 defsubr (&Sgnutls_boot
);
1187 defsubr (&Sgnutls_deinit
);
1188 defsubr (&Sgnutls_bye
);
1189 defsubr (&Sgnutls_available_p
);
1191 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level
,
1192 doc
: /* Logging level used by the GnuTLS functions.
1193 Set this larger than 0 to get debug output in the *Messages* buffer.
1194 1 is for important messages, 2 is for debug data, and higher numbers
1195 are as per the GnuTLS logging conventions. */);
1196 global_gnutls_log_level
= 0;
1199 #endif /* HAVE_GNUTLS */