1 /* GnuTLS glue for GNU Emacs.
2 Copyright (C) 2010-2011 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/>. */
27 #include <gnutls/gnutls.h>
35 emacs_gnutls_handle_error (gnutls_session_t
, int err
);
37 static Lisp_Object Qgnutls_dll
;
38 static Lisp_Object Qgnutls_log_level
;
39 static Lisp_Object Qgnutls_code
;
40 static Lisp_Object Qgnutls_anon
, Qgnutls_x509pki
;
41 static Lisp_Object Qgnutls_e_interrupted
, Qgnutls_e_again
,
42 Qgnutls_e_invalid_session
, Qgnutls_e_not_ready_for_handshake
;
43 static int gnutls_global_initialized
;
45 /* The following are for the property list of `gnutls-boot'. */
46 static Lisp_Object Qgnutls_bootprop_priority
;
47 static Lisp_Object Qgnutls_bootprop_trustfiles
;
48 static Lisp_Object Qgnutls_bootprop_keylist
;
49 static Lisp_Object Qgnutls_bootprop_crlfiles
;
50 static Lisp_Object Qgnutls_bootprop_callbacks
;
51 static Lisp_Object Qgnutls_bootprop_loglevel
;
52 static Lisp_Object Qgnutls_bootprop_hostname
;
53 static Lisp_Object Qgnutls_bootprop_verify_flags
;
54 static Lisp_Object Qgnutls_bootprop_verify_error
;
55 static Lisp_Object Qgnutls_bootprop_verify_hostname_error
;
57 /* Callback keys for `gnutls-boot'. Unused currently. */
58 static Lisp_Object Qgnutls_bootprop_callbacks_verify
;
60 static void gnutls_log_function (int, const char *);
61 static void gnutls_log_function2 (int, const char*, 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 (int, gnutls_error_is_fatal
, (int));
110 DEF_GNUTLS_FN (int, gnutls_global_init
, (void));
111 DEF_GNUTLS_FN (void, gnutls_global_set_log_function
, (gnutls_log_func
));
112 DEF_GNUTLS_FN (void, gnutls_global_set_log_level
, (int));
113 DEF_GNUTLS_FN (int, gnutls_handshake
, (gnutls_session_t
));
114 DEF_GNUTLS_FN (int, gnutls_init
, (gnutls_session_t
*, gnutls_connection_end_t
));
115 DEF_GNUTLS_FN (int, gnutls_priority_set_direct
,
116 (gnutls_session_t
, const char *, const char **));
117 DEF_GNUTLS_FN (size_t, gnutls_record_check_pending
, (gnutls_session_t
));
118 DEF_GNUTLS_FN (ssize_t
, gnutls_record_recv
, (gnutls_session_t
, void *, size_t));
119 DEF_GNUTLS_FN (ssize_t
, gnutls_record_send
,
120 (gnutls_session_t
, const void *, size_t));
121 DEF_GNUTLS_FN (const char *, gnutls_strerror
, (int));
122 DEF_GNUTLS_FN (void, gnutls_transport_set_errno
, (gnutls_session_t
, int));
123 DEF_GNUTLS_FN (void, gnutls_transport_set_lowat
, (gnutls_session_t
, int));
124 DEF_GNUTLS_FN (void, gnutls_transport_set_ptr2
,
125 (gnutls_session_t
, gnutls_transport_ptr_t
,
126 gnutls_transport_ptr_t
));
127 DEF_GNUTLS_FN (void, gnutls_transport_set_pull_function
,
128 (gnutls_session_t
, gnutls_pull_func
));
129 DEF_GNUTLS_FN (void, gnutls_transport_set_push_function
,
130 (gnutls_session_t
, gnutls_push_func
));
131 DEF_GNUTLS_FN (int, gnutls_x509_crt_check_hostname
,
132 (gnutls_x509_crt_t
, const char *));
133 DEF_GNUTLS_FN (void, gnutls_x509_crt_deinit
, (gnutls_x509_crt_t
));
134 DEF_GNUTLS_FN (int, gnutls_x509_crt_import
,
135 (gnutls_x509_crt_t
, const gnutls_datum_t
*,
136 gnutls_x509_crt_fmt_t
));
137 DEF_GNUTLS_FN (int, gnutls_x509_crt_init
, (gnutls_x509_crt_t
*));
140 init_gnutls_functions (Lisp_Object libraries
)
144 if (!(library
= w32_delayed_load (libraries
, Qgnutls_dll
)))
146 GNUTLS_LOG (1, 1, "GnuTLS library not found");
150 LOAD_GNUTLS_FN (library
, gnutls_alert_get
);
151 LOAD_GNUTLS_FN (library
, gnutls_alert_get_name
);
152 LOAD_GNUTLS_FN (library
, gnutls_alert_send_appropriate
);
153 LOAD_GNUTLS_FN (library
, gnutls_anon_allocate_client_credentials
);
154 LOAD_GNUTLS_FN (library
, gnutls_anon_free_client_credentials
);
155 LOAD_GNUTLS_FN (library
, gnutls_bye
);
156 LOAD_GNUTLS_FN (library
, gnutls_certificate_allocate_credentials
);
157 LOAD_GNUTLS_FN (library
, gnutls_certificate_free_credentials
);
158 LOAD_GNUTLS_FN (library
, gnutls_certificate_get_peers
);
159 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_verify_flags
);
160 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_crl_file
);
161 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_key_file
);
162 LOAD_GNUTLS_FN (library
, gnutls_certificate_set_x509_trust_file
);
163 LOAD_GNUTLS_FN (library
, gnutls_certificate_type_get
);
164 LOAD_GNUTLS_FN (library
, gnutls_certificate_verify_peers2
);
165 LOAD_GNUTLS_FN (library
, gnutls_credentials_set
);
166 LOAD_GNUTLS_FN (library
, gnutls_deinit
);
167 LOAD_GNUTLS_FN (library
, gnutls_error_is_fatal
);
168 LOAD_GNUTLS_FN (library
, gnutls_global_init
);
169 LOAD_GNUTLS_FN (library
, gnutls_global_set_log_function
);
170 LOAD_GNUTLS_FN (library
, gnutls_global_set_log_level
);
171 LOAD_GNUTLS_FN (library
, gnutls_handshake
);
172 LOAD_GNUTLS_FN (library
, gnutls_init
);
173 LOAD_GNUTLS_FN (library
, gnutls_priority_set_direct
);
174 LOAD_GNUTLS_FN (library
, gnutls_record_check_pending
);
175 LOAD_GNUTLS_FN (library
, gnutls_record_recv
);
176 LOAD_GNUTLS_FN (library
, gnutls_record_send
);
177 LOAD_GNUTLS_FN (library
, gnutls_strerror
);
178 LOAD_GNUTLS_FN (library
, gnutls_transport_set_errno
);
179 LOAD_GNUTLS_FN (library
, gnutls_transport_set_lowat
);
180 LOAD_GNUTLS_FN (library
, gnutls_transport_set_ptr2
);
181 LOAD_GNUTLS_FN (library
, gnutls_transport_set_pull_function
);
182 LOAD_GNUTLS_FN (library
, gnutls_transport_set_push_function
);
183 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_check_hostname
);
184 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_deinit
);
185 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_import
);
186 LOAD_GNUTLS_FN (library
, gnutls_x509_crt_init
);
188 GNUTLS_LOG2 (1, 1, "GnuTLS library loaded:",
189 SDATA (Fget (Qgnutls_dll
, QCloaded_from
)));
193 #else /* !WINDOWSNT */
195 #define fn_gnutls_alert_get gnutls_alert_get
196 #define fn_gnutls_alert_get_name gnutls_alert_get_name
197 #define fn_gnutls_alert_send_appropriate gnutls_alert_send_appropriate
198 #define fn_gnutls_anon_allocate_client_credentials gnutls_anon_allocate_client_credentials
199 #define fn_gnutls_anon_free_client_credentials gnutls_anon_free_client_credentials
200 #define fn_gnutls_bye gnutls_bye
201 #define fn_gnutls_certificate_allocate_credentials gnutls_certificate_allocate_credentials
202 #define fn_gnutls_certificate_free_credentials gnutls_certificate_free_credentials
203 #define fn_gnutls_certificate_get_peers gnutls_certificate_get_peers
204 #define fn_gnutls_certificate_set_verify_flags gnutls_certificate_set_verify_flags
205 #define fn_gnutls_certificate_set_x509_crl_file gnutls_certificate_set_x509_crl_file
206 #define fn_gnutls_certificate_set_x509_key_file gnutls_certificate_set_x509_key_file
207 #define fn_gnutls_certificate_set_x509_trust_file gnutls_certificate_set_x509_trust_file
208 #define fn_gnutls_certificate_type_get gnutls_certificate_type_get
209 #define fn_gnutls_certificate_verify_peers2 gnutls_certificate_verify_peers2
210 #define fn_gnutls_credentials_set gnutls_credentials_set
211 #define fn_gnutls_deinit gnutls_deinit
212 #define fn_gnutls_error_is_fatal gnutls_error_is_fatal
213 #define fn_gnutls_global_init gnutls_global_init
214 #define fn_gnutls_global_set_log_function gnutls_global_set_log_function
215 #define fn_gnutls_global_set_log_level gnutls_global_set_log_level
216 #define fn_gnutls_handshake gnutls_handshake
217 #define fn_gnutls_init gnutls_init
218 #define fn_gnutls_priority_set_direct gnutls_priority_set_direct
219 #define fn_gnutls_record_check_pending gnutls_record_check_pending
220 #define fn_gnutls_record_recv gnutls_record_recv
221 #define fn_gnutls_record_send gnutls_record_send
222 #define fn_gnutls_strerror gnutls_strerror
223 #define fn_gnutls_transport_set_errno gnutls_transport_set_errno
224 #define fn_gnutls_transport_set_ptr2 gnutls_transport_set_ptr2
225 #define fn_gnutls_x509_crt_check_hostname gnutls_x509_crt_check_hostname
226 #define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit
227 #define fn_gnutls_x509_crt_import gnutls_x509_crt_import
228 #define fn_gnutls_x509_crt_init gnutls_x509_crt_init
230 #endif /* !WINDOWSNT */
234 gnutls_log_function (int level
, const char* string
)
236 message ("gnutls.c: [%d] %s", level
, string
);
240 gnutls_log_function2 (int level
, const char* string
, const char* extra
)
242 message ("gnutls.c: [%d] %s %s", level
, string
, extra
);
246 emacs_gnutls_handshake (struct Lisp_Process
*proc
)
248 gnutls_session_t state
= proc
->gnutls_state
;
251 if (proc
->gnutls_initstage
< GNUTLS_STAGE_HANDSHAKE_CANDO
)
254 if (proc
->gnutls_initstage
< GNUTLS_STAGE_TRANSPORT_POINTERS_SET
)
257 /* On W32 we cannot transfer socket handles between different runtime
258 libraries, so we tell GnuTLS to use our special push/pull
260 fn_gnutls_transport_set_ptr2 (state
,
261 (gnutls_transport_ptr_t
) proc
,
262 (gnutls_transport_ptr_t
) proc
);
263 fn_gnutls_transport_set_push_function (state
, &emacs_gnutls_push
);
264 fn_gnutls_transport_set_pull_function (state
, &emacs_gnutls_pull
);
266 /* For non blocking sockets or other custom made pull/push
267 functions the gnutls_transport_set_lowat must be called, with
268 a zero low water mark value. (GnuTLS 2.10.4 documentation)
270 (Note: this is probably not strictly necessary as the lowat
271 value is only used when no custom pull/push functions are
273 fn_gnutls_transport_set_lowat (state
, 0);
275 /* This is how GnuTLS takes sockets: as file descriptors passed
276 in. For an Emacs process socket, infd and outfd are the
277 same but we use this two-argument version for clarity. */
278 fn_gnutls_transport_set_ptr2 (state
,
279 (gnutls_transport_ptr_t
) (long) proc
->infd
,
280 (gnutls_transport_ptr_t
) (long) proc
->outfd
);
283 proc
->gnutls_initstage
= GNUTLS_STAGE_TRANSPORT_POINTERS_SET
;
288 ret
= fn_gnutls_handshake (state
);
289 emacs_gnutls_handle_error (state
, ret
);
291 while (ret
< 0 && fn_gnutls_error_is_fatal (ret
) == 0);
293 proc
->gnutls_initstage
= GNUTLS_STAGE_HANDSHAKE_TRIED
;
295 if (ret
== GNUTLS_E_SUCCESS
)
297 /* Here we're finally done. */
298 proc
->gnutls_initstage
= GNUTLS_STAGE_READY
;
302 fn_gnutls_alert_send_appropriate (state
, ret
);
308 emacs_gnutls_record_check_pending (gnutls_session_t state
)
310 return fn_gnutls_record_check_pending (state
);
314 emacs_gnutls_transport_set_errno (gnutls_session_t state
, int err
)
316 fn_gnutls_transport_set_errno (state
, err
);
320 emacs_gnutls_write (struct Lisp_Process
*proc
, const char *buf
, EMACS_INT nbyte
)
323 EMACS_INT bytes_written
;
324 gnutls_session_t state
= proc
->gnutls_state
;
326 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
) {
340 rtnval
= fn_gnutls_record_send (state
, buf
, nbyte
);
344 if (rtnval
== GNUTLS_E_AGAIN
|| rtnval
== GNUTLS_E_INTERRUPTED
)
352 bytes_written
+= rtnval
;
355 emacs_gnutls_handle_error (state
, rtnval
);
356 return (bytes_written
);
360 emacs_gnutls_read (struct Lisp_Process
*proc
, char *buf
, EMACS_INT nbyte
)
363 gnutls_session_t state
= proc
->gnutls_state
;
365 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
)
367 emacs_gnutls_handshake (proc
);
370 rtnval
= fn_gnutls_record_recv (state
, buf
, nbyte
);
373 else if (emacs_gnutls_handle_error (state
, rtnval
) == 0)
374 /* non-fatal error */
377 /* a fatal error occured */
382 /* report a GnuTLS error to the user.
383 Returns zero if the error code was successfully handled. */
385 emacs_gnutls_handle_error (gnutls_session_t session
, int err
)
387 Lisp_Object gnutls_log_level
= Fsymbol_value (Qgnutls_log_level
);
388 int max_log_level
= 0;
393 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
397 if (NUMBERP (gnutls_log_level
))
398 max_log_level
= XINT (gnutls_log_level
);
400 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
402 str
= fn_gnutls_strerror (err
);
406 if (fn_gnutls_error_is_fatal (err
))
409 GNUTLS_LOG2 (0, max_log_level
, "fatal error:", str
);
414 GNUTLS_LOG2 (1, max_log_level
, "non-fatal error:", str
);
415 /* TODO: EAGAIN AKA Qgnutls_e_again should be level 2. */
418 if (err
== GNUTLS_E_WARNING_ALERT_RECEIVED
419 || err
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
421 int alert
= fn_gnutls_alert_get (session
);
422 int level
= (err
== GNUTLS_E_FATAL_ALERT_RECEIVED
) ? 0 : 1;
423 str
= fn_gnutls_alert_get_name (alert
);
427 GNUTLS_LOG2 (level
, max_log_level
, "Received alert: ", str
);
432 /* convert an integer error to a Lisp_Object; it will be either a
433 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
434 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
437 gnutls_make_error (int err
)
441 case GNUTLS_E_SUCCESS
:
444 return Qgnutls_e_again
;
445 case GNUTLS_E_INTERRUPTED
:
446 return Qgnutls_e_interrupted
;
447 case GNUTLS_E_INVALID_SESSION
:
448 return Qgnutls_e_invalid_session
;
451 return make_number (err
);
454 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage
, Sgnutls_get_initstage
, 1, 1, 0,
455 doc
: /* Return the GnuTLS init stage of process PROC.
456 See also `gnutls-boot'. */)
459 CHECK_PROCESS (proc
);
461 return make_number (GNUTLS_INITSTAGE (proc
));
464 DEFUN ("gnutls-errorp", Fgnutls_errorp
, Sgnutls_errorp
, 1, 1, 0,
465 doc
: /* Return t if ERROR indicates a GnuTLS problem.
466 ERROR is an integer or a symbol with an integer `gnutls-code' property.
467 usage: (gnutls-errorp ERROR) */)
470 if (EQ (err
, Qt
)) return Qnil
;
475 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp
, Sgnutls_error_fatalp
, 1, 1, 0,
476 doc
: /* Check if ERROR is fatal.
477 ERROR is an integer or a symbol with an integer `gnutls-code' property.
478 usage: (gnutls-error-fatalp ERROR) */)
483 if (EQ (err
, Qt
)) return Qnil
;
487 code
= Fget (err
, Qgnutls_code
);
494 error ("Symbol has no numeric gnutls-code property");
499 error ("Not an error symbol or code");
501 if (0 == fn_gnutls_error_is_fatal (XINT (err
)))
507 DEFUN ("gnutls-error-string", Fgnutls_error_string
, Sgnutls_error_string
, 1, 1, 0,
508 doc
: /* Return a description of ERROR.
509 ERROR is an integer or a symbol with an integer `gnutls-code' property.
510 usage: (gnutls-error-string ERROR) */)
515 if (EQ (err
, Qt
)) return build_string ("Not an error");
519 code
= Fget (err
, Qgnutls_code
);
526 return build_string ("Symbol has no numeric gnutls-code property");
531 return build_string ("Not an error symbol or code");
533 return build_string (fn_gnutls_strerror (XINT (err
)));
536 DEFUN ("gnutls-deinit", Fgnutls_deinit
, Sgnutls_deinit
, 1, 1, 0,
537 doc
: /* Deallocate GnuTLS resources associated with process PROC.
538 See also `gnutls-init'. */)
541 gnutls_session_t state
;
543 CHECK_PROCESS (proc
);
544 state
= XPROCESS (proc
)->gnutls_state
;
546 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_INIT
)
548 fn_gnutls_deinit (state
);
549 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
- 1;
555 DEFUN ("gnutls-available-p", Fgnutls_available_p
, Sgnutls_available_p
, 0, 0, 0,
556 doc
: /* Return t if GnuTLS is available in this instance of Emacs. */)
560 Lisp_Object found
= Fassq (Qgnutls_dll
, Vlibrary_cache
);
566 status
= init_gnutls_functions (Vdynamic_library_alist
) ? Qt
: Qnil
;
567 Vlibrary_cache
= Fcons (Fcons (Qgnutls_dll
, status
), Vlibrary_cache
);
576 /* Initializes global GnuTLS state to defaults.
577 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
578 Returns zero on success. */
580 emacs_gnutls_global_init (void)
582 int ret
= GNUTLS_E_SUCCESS
;
584 if (!gnutls_global_initialized
)
585 ret
= fn_gnutls_global_init ();
586 gnutls_global_initialized
= 1;
588 return gnutls_make_error (ret
);
592 /* Deinitializes global GnuTLS state.
593 See also `gnutls-global-init'. */
595 emacs_gnutls_global_deinit (void)
597 if (gnutls_global_initialized
)
598 gnutls_global_deinit ();
600 gnutls_global_initialized
= 0;
602 return gnutls_make_error (GNUTLS_E_SUCCESS
);
606 DEFUN ("gnutls-boot", Fgnutls_boot
, Sgnutls_boot
, 3, 3, 0,
607 doc
: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
608 Currently only client mode is supported. Returns a success/failure
609 value you can check with `gnutls-errorp'.
611 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
612 PROPLIST is a property list with the following keys:
614 :hostname is a string naming the remote host.
616 :priority is a GnuTLS priority string, defaults to "NORMAL".
618 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
620 :crlfiles is a list of PEM-encoded CRL lists for `gnutls-x509pki'.
622 :keylist is an alist of PEM-encoded key files and PEM-encoded
623 certificates for `gnutls-x509pki'.
625 :callbacks is an alist of callback functions, see below.
627 :loglevel is the debug level requested from GnuTLS, try 4.
629 :verify-flags is a bitset as per GnuTLS'
630 gnutls_certificate_set_verify_flags.
632 :verify-error, if non-nil, makes failure of the certificate validation
633 an error. Otherwise it will be just a series of warnings.
635 :verify-hostname-error, if non-nil, makes a hostname mismatch an
636 error. Otherwise it will be just a warning.
638 The debug level will be set for this process AND globally for GnuTLS.
639 So if you set it higher or lower at any point, it affects global
642 Note that the priority is set on the client. The server does not use
643 the protocols's priority except for disabling protocols that were not
646 Processes must be initialized with this function before other GnuTLS
647 functions are used. This function allocates resources which can only
648 be deallocated by calling `gnutls-deinit' or by calling it again.
650 The callbacks alist can have a `verify' key, associated with a
651 verification function (UNUSED).
653 Each authentication type may need additional information in order to
654 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
655 one trustfile (usually a CA bundle). */)
656 (Lisp_Object proc
, Lisp_Object type
, Lisp_Object proplist
)
658 int ret
= GNUTLS_E_SUCCESS
;
660 int max_log_level
= 0;
662 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
663 int file_format
= GNUTLS_X509_FMT_PEM
;
665 unsigned int gnutls_verify_flags
= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
;
666 gnutls_x509_crt_t gnutls_verify_cert
;
667 unsigned int gnutls_verify_cert_list_size
;
668 const gnutls_datum_t
*gnutls_verify_cert_list
;
670 gnutls_session_t state
;
671 gnutls_certificate_credentials_t x509_cred
;
672 gnutls_anon_client_credentials_t anon_cred
;
673 Lisp_Object global_init
;
674 char const *priority_string_ptr
= "NORMAL"; /* default priority string. */
676 unsigned int peer_verification
;
679 /* Placeholders for the property list elements. */
680 Lisp_Object priority_string
;
681 Lisp_Object trustfiles
;
682 Lisp_Object crlfiles
;
684 /* Lisp_Object callbacks; */
685 Lisp_Object loglevel
;
686 Lisp_Object hostname
;
687 Lisp_Object verify_flags
;
688 /* Lisp_Object verify_error; */
689 Lisp_Object verify_hostname_error
;
691 CHECK_PROCESS (proc
);
693 CHECK_LIST (proplist
);
695 if (NILP (Fgnutls_available_p ()))
697 error ("GnuTLS not available");
698 return gnutls_make_error (GNUTLS_EMACS_ERROR_NOT_LOADED
);
701 hostname
= Fplist_get (proplist
, Qgnutls_bootprop_hostname
);
702 priority_string
= Fplist_get (proplist
, Qgnutls_bootprop_priority
);
703 trustfiles
= Fplist_get (proplist
, Qgnutls_bootprop_trustfiles
);
704 keylist
= Fplist_get (proplist
, Qgnutls_bootprop_keylist
);
705 crlfiles
= Fplist_get (proplist
, Qgnutls_bootprop_crlfiles
);
706 /* callbacks = Fplist_get (proplist, Qgnutls_bootprop_callbacks); */
707 loglevel
= Fplist_get (proplist
, Qgnutls_bootprop_loglevel
);
708 verify_flags
= Fplist_get (proplist
, Qgnutls_bootprop_verify_flags
);
709 /* verify_error = Fplist_get (proplist, Qgnutls_bootprop_verify_error); */
710 verify_hostname_error
= Fplist_get (proplist
, Qgnutls_bootprop_verify_hostname_error
);
712 if (!STRINGP (hostname
))
713 error ("gnutls-boot: invalid :hostname parameter");
715 c_hostname
= SSDATA (hostname
);
717 state
= XPROCESS (proc
)->gnutls_state
;
718 XPROCESS (proc
)->gnutls_p
= 1;
720 if (NUMBERP (loglevel
))
722 fn_gnutls_global_set_log_function (gnutls_log_function
);
723 fn_gnutls_global_set_log_level (XINT (loglevel
));
724 max_log_level
= XINT (loglevel
);
725 XPROCESS (proc
)->gnutls_log_level
= max_log_level
;
728 /* always initialize globals. */
729 global_init
= emacs_gnutls_global_init ();
730 if (! NILP (Fgnutls_errorp (global_init
)))
733 /* deinit and free resources. */
734 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_CRED_ALLOC
)
736 GNUTLS_LOG (1, max_log_level
, "deallocating credentials");
738 if (EQ (type
, Qgnutls_x509pki
))
740 GNUTLS_LOG (2, max_log_level
, "deallocating x509 credentials");
741 x509_cred
= XPROCESS (proc
)->gnutls_x509_cred
;
742 fn_gnutls_certificate_free_credentials (x509_cred
);
744 else if (EQ (type
, Qgnutls_anon
))
746 GNUTLS_LOG (2, max_log_level
, "deallocating anon credentials");
747 anon_cred
= XPROCESS (proc
)->gnutls_anon_cred
;
748 fn_gnutls_anon_free_client_credentials (anon_cred
);
752 error ("unknown credential type");
753 ret
= GNUTLS_EMACS_ERROR_INVALID_TYPE
;
756 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_INIT
)
758 GNUTLS_LOG (1, max_log_level
, "deallocating x509 credentials");
759 Fgnutls_deinit (proc
);
763 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_EMPTY
;
765 GNUTLS_LOG (1, max_log_level
, "allocating credentials");
767 if (EQ (type
, Qgnutls_x509pki
))
769 GNUTLS_LOG (2, max_log_level
, "allocating x509 credentials");
770 x509_cred
= XPROCESS (proc
)->gnutls_x509_cred
;
771 if (fn_gnutls_certificate_allocate_credentials (&x509_cred
) < 0)
774 if (NUMBERP (verify_flags
))
776 gnutls_verify_flags
= XINT (verify_flags
);
777 GNUTLS_LOG (2, max_log_level
, "setting verification flags");
779 else if (NILP (verify_flags
))
781 /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
782 GNUTLS_LOG (2, max_log_level
, "using default verification flags");
786 /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
787 GNUTLS_LOG (2, max_log_level
, "ignoring invalid verify-flags");
789 fn_gnutls_certificate_set_verify_flags (x509_cred
, gnutls_verify_flags
);
791 else if (EQ (type
, Qgnutls_anon
))
793 GNUTLS_LOG (2, max_log_level
, "allocating anon credentials");
794 anon_cred
= XPROCESS (proc
)->gnutls_anon_cred
;
795 if (fn_gnutls_anon_allocate_client_credentials (&anon_cred
) < 0)
800 error ("unknown credential type");
801 ret
= GNUTLS_EMACS_ERROR_INVALID_TYPE
;
804 if (ret
< GNUTLS_E_SUCCESS
)
805 return gnutls_make_error (ret
);
807 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_ALLOC
;
809 if (EQ (type
, Qgnutls_x509pki
))
811 for (tail
= trustfiles
; !NILP (tail
); tail
= Fcdr (tail
))
813 Lisp_Object trustfile
= Fcar (tail
);
814 if (STRINGP (trustfile
))
816 GNUTLS_LOG2 (1, max_log_level
, "setting the trustfile: ",
818 ret
= fn_gnutls_certificate_set_x509_trust_file
823 if (ret
< GNUTLS_E_SUCCESS
)
824 return gnutls_make_error (ret
);
828 error ("Sorry, GnuTLS can't use non-string trustfile %s",
833 for (tail
= crlfiles
; !NILP (tail
); tail
= Fcdr (tail
))
835 Lisp_Object crlfile
= Fcar (tail
);
836 if (STRINGP (crlfile
))
838 GNUTLS_LOG2 (1, max_log_level
, "setting the CRL file: ",
840 ret
= fn_gnutls_certificate_set_x509_crl_file
845 if (ret
< GNUTLS_E_SUCCESS
)
846 return gnutls_make_error (ret
);
850 error ("Sorry, GnuTLS can't use non-string CRL file %s",
855 for (tail
= keylist
; !NILP (tail
); tail
= Fcdr (tail
))
857 Lisp_Object keyfile
= Fcar (Fcar (tail
));
858 Lisp_Object certfile
= Fcar (Fcdr (tail
));
859 if (STRINGP (keyfile
) && STRINGP (certfile
))
861 GNUTLS_LOG2 (1, max_log_level
, "setting the client key file: ",
863 GNUTLS_LOG2 (1, max_log_level
, "setting the client cert file: ",
865 ret
= fn_gnutls_certificate_set_x509_key_file
871 if (ret
< GNUTLS_E_SUCCESS
)
872 return gnutls_make_error (ret
);
876 if (STRINGP (keyfile
))
877 error ("Sorry, GnuTLS can't use non-string client cert file %s",
880 error ("Sorry, GnuTLS can't use non-string client key file %s",
886 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_FILES
;
888 GNUTLS_LOG (1, max_log_level
, "gnutls callbacks");
890 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CALLBACKS
;
892 #ifdef HAVE_GNUTLS_CALLBACK_CERTIFICATE_VERIFY
896 GNUTLS_LOG (1, max_log_level
, "gnutls_init");
898 ret
= fn_gnutls_init (&state
, GNUTLS_CLIENT
);
900 if (ret
< GNUTLS_E_SUCCESS
)
901 return gnutls_make_error (ret
);
903 XPROCESS (proc
)->gnutls_state
= state
;
905 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
;
907 if (STRINGP (priority_string
))
909 priority_string_ptr
= SSDATA (priority_string
);
910 GNUTLS_LOG2 (1, max_log_level
, "got non-default priority string:",
911 priority_string_ptr
);
915 GNUTLS_LOG2 (1, max_log_level
, "using default priority string:",
916 priority_string_ptr
);
919 GNUTLS_LOG (1, max_log_level
, "setting the priority string");
921 ret
= fn_gnutls_priority_set_direct (state
,
925 if (ret
< GNUTLS_E_SUCCESS
)
926 return gnutls_make_error (ret
);
928 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_PRIORITY
;
930 if (EQ (type
, Qgnutls_x509pki
))
932 ret
= fn_gnutls_credentials_set (state
, GNUTLS_CRD_CERTIFICATE
, x509_cred
);
934 else if (EQ (type
, Qgnutls_anon
))
936 ret
= fn_gnutls_credentials_set (state
, GNUTLS_CRD_ANON
, anon_cred
);
940 error ("unknown credential type");
941 ret
= GNUTLS_EMACS_ERROR_INVALID_TYPE
;
944 if (ret
< GNUTLS_E_SUCCESS
)
945 return gnutls_make_error (ret
);
947 XPROCESS (proc
)->gnutls_anon_cred
= anon_cred
;
948 XPROCESS (proc
)->gnutls_x509_cred
= x509_cred
;
949 XPROCESS (proc
)->gnutls_cred_type
= type
;
951 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_SET
;
953 ret
= emacs_gnutls_handshake (XPROCESS (proc
));
955 if (ret
< GNUTLS_E_SUCCESS
)
956 return gnutls_make_error (ret
);
958 /* Now verify the peer, following
959 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
960 The peer should present at least one certificate in the chain; do a
961 check of the certificate's hostname with
962 gnutls_x509_crt_check_hostname() against :hostname. */
964 ret
= fn_gnutls_certificate_verify_peers2 (state
, &peer_verification
);
966 if (ret
< GNUTLS_E_SUCCESS
)
967 return gnutls_make_error (ret
);
969 if (XINT (loglevel
) > 0 && peer_verification
& GNUTLS_CERT_INVALID
)
970 message ("%s certificate could not be verified.",
973 if (peer_verification
& GNUTLS_CERT_REVOKED
)
974 GNUTLS_LOG2 (1, max_log_level
, "certificate was revoked (CRL):",
977 if (peer_verification
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
978 GNUTLS_LOG2 (1, max_log_level
, "certificate signer was not found:",
981 if (peer_verification
& GNUTLS_CERT_SIGNER_NOT_CA
)
982 GNUTLS_LOG2 (1, max_log_level
, "certificate signer is not a CA:",
985 if (peer_verification
& GNUTLS_CERT_INSECURE_ALGORITHM
)
986 GNUTLS_LOG2 (1, max_log_level
,
987 "certificate was signed with an insecure algorithm:",
990 if (peer_verification
& GNUTLS_CERT_NOT_ACTIVATED
)
991 GNUTLS_LOG2 (1, max_log_level
, "certificate is not yet activated:",
994 if (peer_verification
& GNUTLS_CERT_EXPIRED
)
995 GNUTLS_LOG2 (1, max_log_level
, "certificate has expired:",
998 if (peer_verification
!= 0)
1000 if (NILP (verify_hostname_error
))
1002 GNUTLS_LOG2 (1, max_log_level
, "certificate validation failed:",
1007 error ("Certificate validation failed %s, verification code %d",
1008 c_hostname
, peer_verification
);
1012 /* Up to here the process is the same for X.509 certificates and
1013 OpenPGP keys. From now on X.509 certificates are assumed. This
1014 can be easily extended to work with openpgp keys as well. */
1015 if (fn_gnutls_certificate_type_get (state
) == GNUTLS_CRT_X509
)
1017 ret
= fn_gnutls_x509_crt_init (&gnutls_verify_cert
);
1019 if (ret
< GNUTLS_E_SUCCESS
)
1020 return gnutls_make_error (ret
);
1022 gnutls_verify_cert_list
=
1023 fn_gnutls_certificate_get_peers (state
, &gnutls_verify_cert_list_size
);
1025 if (NULL
== gnutls_verify_cert_list
)
1027 error ("No x509 certificate was found!\n");
1030 /* We only check the first certificate in the given chain. */
1031 ret
= fn_gnutls_x509_crt_import (gnutls_verify_cert
,
1032 &gnutls_verify_cert_list
[0],
1033 GNUTLS_X509_FMT_DER
);
1035 if (ret
< GNUTLS_E_SUCCESS
)
1037 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1038 return gnutls_make_error (ret
);
1041 if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert
, c_hostname
))
1043 if (NILP (verify_hostname_error
))
1045 GNUTLS_LOG2 (1, max_log_level
, "x509 certificate does not match:",
1050 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1051 error ("The x509 certificate does not match \"%s\"",
1056 fn_gnutls_x509_crt_deinit (gnutls_verify_cert
);
1059 return gnutls_make_error (ret
);
1062 DEFUN ("gnutls-bye", Fgnutls_bye
,
1063 Sgnutls_bye
, 2, 2, 0,
1064 doc
: /* Terminate current GnuTLS connection for process PROC.
1065 The connection should have been initiated using `gnutls-handshake'.
1067 If CONT is not nil the TLS connection gets terminated and further
1068 receives and sends will be disallowed. If the return value is zero you
1069 may continue using the connection. If CONT is nil, GnuTLS actually
1070 sends an alert containing a close request and waits for the peer to
1071 reply with the same message. In order to reuse the connection you
1072 should wait for an EOF from the peer.
1074 This function may also return `gnutls-e-again', or
1075 `gnutls-e-interrupted'. */)
1076 (Lisp_Object proc
, Lisp_Object cont
)
1078 gnutls_session_t state
;
1081 CHECK_PROCESS (proc
);
1083 state
= XPROCESS (proc
)->gnutls_state
;
1085 ret
= fn_gnutls_bye (state
,
1086 NILP (cont
) ? GNUTLS_SHUT_RDWR
: GNUTLS_SHUT_WR
);
1088 return gnutls_make_error (ret
);
1092 syms_of_gnutls (void)
1094 gnutls_global_initialized
= 0;
1096 Qgnutls_dll
= intern_c_string ("gnutls");
1097 staticpro (&Qgnutls_dll
);
1099 Qgnutls_log_level
= intern_c_string ("gnutls-log-level");
1100 staticpro (&Qgnutls_log_level
);
1102 Qgnutls_code
= intern_c_string ("gnutls-code");
1103 staticpro (&Qgnutls_code
);
1105 Qgnutls_anon
= intern_c_string ("gnutls-anon");
1106 staticpro (&Qgnutls_anon
);
1108 Qgnutls_x509pki
= intern_c_string ("gnutls-x509pki");
1109 staticpro (&Qgnutls_x509pki
);
1111 Qgnutls_bootprop_hostname
= intern_c_string (":hostname");
1112 staticpro (&Qgnutls_bootprop_hostname
);
1114 Qgnutls_bootprop_priority
= intern_c_string (":priority");
1115 staticpro (&Qgnutls_bootprop_priority
);
1117 Qgnutls_bootprop_trustfiles
= intern_c_string (":trustfiles");
1118 staticpro (&Qgnutls_bootprop_trustfiles
);
1120 Qgnutls_bootprop_keylist
= intern_c_string (":keylist");
1121 staticpro (&Qgnutls_bootprop_keylist
);
1123 Qgnutls_bootprop_crlfiles
= intern_c_string (":crlfiles");
1124 staticpro (&Qgnutls_bootprop_crlfiles
);
1126 Qgnutls_bootprop_callbacks
= intern_c_string (":callbacks");
1127 staticpro (&Qgnutls_bootprop_callbacks
);
1129 Qgnutls_bootprop_callbacks_verify
= intern_c_string ("verify");
1130 staticpro (&Qgnutls_bootprop_callbacks_verify
);
1132 Qgnutls_bootprop_loglevel
= intern_c_string (":loglevel");
1133 staticpro (&Qgnutls_bootprop_loglevel
);
1135 Qgnutls_bootprop_verify_flags
= intern_c_string (":verify-flags");
1136 staticpro (&Qgnutls_bootprop_verify_flags
);
1138 Qgnutls_bootprop_verify_hostname_error
= intern_c_string (":verify-error");
1139 staticpro (&Qgnutls_bootprop_verify_error
);
1141 Qgnutls_bootprop_verify_hostname_error
= intern_c_string (":verify-hostname-error");
1142 staticpro (&Qgnutls_bootprop_verify_hostname_error
);
1144 Qgnutls_e_interrupted
= intern_c_string ("gnutls-e-interrupted");
1145 staticpro (&Qgnutls_e_interrupted
);
1146 Fput (Qgnutls_e_interrupted
, Qgnutls_code
,
1147 make_number (GNUTLS_E_INTERRUPTED
));
1149 Qgnutls_e_again
= intern_c_string ("gnutls-e-again");
1150 staticpro (&Qgnutls_e_again
);
1151 Fput (Qgnutls_e_again
, Qgnutls_code
,
1152 make_number (GNUTLS_E_AGAIN
));
1154 Qgnutls_e_invalid_session
= intern_c_string ("gnutls-e-invalid-session");
1155 staticpro (&Qgnutls_e_invalid_session
);
1156 Fput (Qgnutls_e_invalid_session
, Qgnutls_code
,
1157 make_number (GNUTLS_E_INVALID_SESSION
));
1159 Qgnutls_e_not_ready_for_handshake
=
1160 intern_c_string ("gnutls-e-not-ready-for-handshake");
1161 staticpro (&Qgnutls_e_not_ready_for_handshake
);
1162 Fput (Qgnutls_e_not_ready_for_handshake
, Qgnutls_code
,
1163 make_number (GNUTLS_E_APPLICATION_ERROR_MIN
));
1165 defsubr (&Sgnutls_get_initstage
);
1166 defsubr (&Sgnutls_errorp
);
1167 defsubr (&Sgnutls_error_fatalp
);
1168 defsubr (&Sgnutls_error_string
);
1169 defsubr (&Sgnutls_boot
);
1170 defsubr (&Sgnutls_deinit
);
1171 defsubr (&Sgnutls_bye
);
1172 defsubr (&Sgnutls_available_p
);
1175 #endif /* HAVE_GNUTLS */