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 Lisp_Object Qgnutls_log_level
;
38 Lisp_Object Qgnutls_code
;
39 Lisp_Object Qgnutls_anon
, Qgnutls_x509pki
;
40 Lisp_Object Qgnutls_e_interrupted
, Qgnutls_e_again
,
41 Qgnutls_e_invalid_session
, Qgnutls_e_not_ready_for_handshake
;
42 int gnutls_global_initialized
;
44 /* The following are for the property list of `gnutls-boot'. */
45 Lisp_Object Qgnutls_bootprop_priority
;
46 Lisp_Object Qgnutls_bootprop_trustfiles
;
47 Lisp_Object Qgnutls_bootprop_keyfiles
;
48 Lisp_Object Qgnutls_bootprop_callbacks
;
49 Lisp_Object Qgnutls_bootprop_loglevel
;
50 Lisp_Object Qgnutls_bootprop_hostname
;
51 Lisp_Object Qgnutls_bootprop_verify_flags
;
52 Lisp_Object Qgnutls_bootprop_verify_error
;
53 Lisp_Object Qgnutls_bootprop_verify_hostname_error
;
55 /* Callback keys for `gnutls-boot'. Unused currently. */
56 Lisp_Object Qgnutls_bootprop_callbacks_verify
;
59 gnutls_log_function (int level
, const char* string
)
61 message ("gnutls.c: [%d] %s", level
, string
);
65 gnutls_log_function2 (int level
, const char* string
, const char* extra
)
67 message ("gnutls.c: [%d] %s %s", level
, string
, extra
);
71 emacs_gnutls_handshake (struct Lisp_Process
*proc
)
73 gnutls_session_t state
= proc
->gnutls_state
;
76 if (proc
->gnutls_initstage
< GNUTLS_STAGE_HANDSHAKE_CANDO
)
79 if (proc
->gnutls_initstage
< GNUTLS_STAGE_TRANSPORT_POINTERS_SET
)
82 /* On W32 we cannot transfer socket handles between different runtime
83 libraries, so we tell GnuTLS to use our special push/pull
85 gnutls_transport_set_ptr2 (state
,
86 (gnutls_transport_ptr_t
) proc
,
87 (gnutls_transport_ptr_t
) proc
);
88 gnutls_transport_set_push_function (state
, &emacs_gnutls_push
);
89 gnutls_transport_set_pull_function (state
, &emacs_gnutls_pull
);
91 /* For non blocking sockets or other custom made pull/push
92 functions the gnutls_transport_set_lowat must be called, with
93 a zero low water mark value. (GnuTLS 2.10.4 documentation)
95 (Note: this is probably not strictly necessary as the lowat
96 value is only used when no custom pull/push functions are
98 gnutls_transport_set_lowat (state
, 0);
100 /* This is how GnuTLS takes sockets: as file descriptors passed
101 in. For an Emacs process socket, infd and outfd are the
102 same but we use this two-argument version for clarity. */
103 gnutls_transport_set_ptr2 (state
,
104 (gnutls_transport_ptr_t
) (long) proc
->infd
,
105 (gnutls_transport_ptr_t
) (long) proc
->outfd
);
108 proc
->gnutls_initstage
= GNUTLS_STAGE_TRANSPORT_POINTERS_SET
;
113 ret
= gnutls_handshake (state
);
114 emacs_gnutls_handle_error (state
, ret
);
116 while (ret
< 0 && gnutls_error_is_fatal (ret
) == 0);
118 proc
->gnutls_initstage
= GNUTLS_STAGE_HANDSHAKE_TRIED
;
120 if (ret
== GNUTLS_E_SUCCESS
)
122 /* Here we're finally done. */
123 proc
->gnutls_initstage
= GNUTLS_STAGE_READY
;
127 gnutls_alert_send_appropriate (state
, ret
);
133 emacs_gnutls_write (int fildes
, struct Lisp_Process
*proc
, const char *buf
,
137 EMACS_INT bytes_written
;
138 gnutls_session_t state
= proc
->gnutls_state
;
140 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
) {
154 rtnval
= gnutls_write (state
, buf
, nbyte
);
158 if (rtnval
== GNUTLS_E_AGAIN
|| rtnval
== GNUTLS_E_INTERRUPTED
)
166 bytes_written
+= rtnval
;
169 emacs_gnutls_handle_error (state
, rtnval
);
170 return (bytes_written
);
174 emacs_gnutls_read (int fildes
, struct Lisp_Process
*proc
, char *buf
,
178 gnutls_session_t state
= proc
->gnutls_state
;
180 if (proc
->gnutls_initstage
!= GNUTLS_STAGE_READY
)
182 emacs_gnutls_handshake (proc
);
185 rtnval
= gnutls_read (state
, buf
, nbyte
);
188 else if (emacs_gnutls_handle_error (state
, rtnval
) == 0)
189 /* non-fatal error */
192 /* a fatal error occured */
197 /* report a GnuTLS error to the user.
198 Returns zero if the error code was successfully handled. */
200 emacs_gnutls_handle_error (gnutls_session_t session
, int err
)
202 Lisp_Object gnutls_log_level
= Fsymbol_value (Qgnutls_log_level
);
203 int max_log_level
= 0;
208 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
212 if (NUMBERP (gnutls_log_level
))
213 max_log_level
= XINT (gnutls_log_level
);
215 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
217 str
= gnutls_strerror (err
);
221 if (gnutls_error_is_fatal (err
))
224 GNUTLS_LOG2 (0, max_log_level
, "fatal error:", str
);
229 GNUTLS_LOG2 (1, max_log_level
, "non-fatal error:", str
);
230 /* TODO: EAGAIN AKA Qgnutls_e_again should be level 2. */
233 if (err
== GNUTLS_E_WARNING_ALERT_RECEIVED
234 || err
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
236 int alert
= gnutls_alert_get (session
);
237 int level
= (err
== GNUTLS_E_FATAL_ALERT_RECEIVED
) ? 0 : 1;
238 str
= gnutls_alert_get_name (alert
);
242 GNUTLS_LOG2 (level
, max_log_level
, "Received alert: ", str
);
247 /* convert an integer error to a Lisp_Object; it will be either a
248 known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
249 simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
252 gnutls_make_error (int error
)
256 case GNUTLS_E_SUCCESS
:
259 return Qgnutls_e_again
;
260 case GNUTLS_E_INTERRUPTED
:
261 return Qgnutls_e_interrupted
;
262 case GNUTLS_E_INVALID_SESSION
:
263 return Qgnutls_e_invalid_session
;
266 return make_number (error
);
269 DEFUN ("gnutls-get-initstage", Fgnutls_get_initstage
, Sgnutls_get_initstage
, 1, 1, 0,
270 doc
: /* Return the GnuTLS init stage of process PROC.
271 See also `gnutls-boot'. */)
274 CHECK_PROCESS (proc
);
276 return make_number (GNUTLS_INITSTAGE (proc
));
279 DEFUN ("gnutls-errorp", Fgnutls_errorp
, Sgnutls_errorp
, 1, 1, 0,
280 doc
: /* Return t if ERROR indicates a GnuTLS problem.
281 ERROR is an integer or a symbol with an integer `gnutls-code' property.
282 usage: (gnutls-errorp ERROR) */)
285 if (EQ (err
, Qt
)) return Qnil
;
290 DEFUN ("gnutls-error-fatalp", Fgnutls_error_fatalp
, Sgnutls_error_fatalp
, 1, 1, 0,
291 doc
: /* Check if ERROR is fatal.
292 ERROR is an integer or a symbol with an integer `gnutls-code' property.
293 usage: (gnutls-error-fatalp ERROR) */)
298 if (EQ (err
, Qt
)) return Qnil
;
302 code
= Fget (err
, Qgnutls_code
);
309 error ("Symbol has no numeric gnutls-code property");
314 error ("Not an error symbol or code");
316 if (0 == gnutls_error_is_fatal (XINT (err
)))
322 DEFUN ("gnutls-error-string", Fgnutls_error_string
, Sgnutls_error_string
, 1, 1, 0,
323 doc
: /* Return a description of ERROR.
324 ERROR is an integer or a symbol with an integer `gnutls-code' property.
325 usage: (gnutls-error-string ERROR) */)
330 if (EQ (err
, Qt
)) return build_string ("Not an error");
334 code
= Fget (err
, Qgnutls_code
);
341 return build_string ("Symbol has no numeric gnutls-code property");
346 return build_string ("Not an error symbol or code");
348 return build_string (gnutls_strerror (XINT (err
)));
351 DEFUN ("gnutls-deinit", Fgnutls_deinit
, Sgnutls_deinit
, 1, 1, 0,
352 doc
: /* Deallocate GnuTLS resources associated with process PROC.
353 See also `gnutls-init'. */)
356 gnutls_session_t state
;
358 CHECK_PROCESS (proc
);
359 state
= XPROCESS (proc
)->gnutls_state
;
361 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_INIT
)
363 gnutls_deinit (state
);
364 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
- 1;
370 /* Initializes global GnuTLS state to defaults.
371 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
372 Returns zero on success. */
374 emacs_gnutls_global_init (void)
376 int ret
= GNUTLS_E_SUCCESS
;
378 if (!gnutls_global_initialized
)
379 ret
= gnutls_global_init ();
381 gnutls_global_initialized
= 1;
383 return gnutls_make_error (ret
);
386 /* Deinitializes global GnuTLS state.
387 See also `gnutls-global-init'. */
389 emacs_gnutls_global_deinit (void)
391 if (gnutls_global_initialized
)
392 gnutls_global_deinit ();
394 gnutls_global_initialized
= 0;
396 return gnutls_make_error (GNUTLS_E_SUCCESS
);
399 DEFUN ("gnutls-boot", Fgnutls_boot
, Sgnutls_boot
, 3, 3, 0,
400 doc
: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
401 Currently only client mode is supported. Returns a success/failure
402 value you can check with `gnutls-errorp'.
404 TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
405 PROPLIST is a property list with the following keys:
407 :hostname is a string naming the remote host.
409 :priority is a GnuTLS priority string, defaults to "NORMAL".
411 :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
413 :keyfiles is a list of PEM-encoded key files for `gnutls-x509pki'.
415 :callbacks is an alist of callback functions, see below.
417 :loglevel is the debug level requested from GnuTLS, try 4.
419 :verify-flags is a bitset as per GnuTLS'
420 gnutls_certificate_set_verify_flags.
422 :verify-error, if non-nil, makes failure of the certificate validation
423 an error. Otherwise it will be just a series of warnings.
425 :verify-hostname-error, if non-nil, makes a hostname mismatch an
426 error. Otherwise it will be just a warning.
428 The debug level will be set for this process AND globally for GnuTLS.
429 So if you set it higher or lower at any point, it affects global
432 Note that the priority is set on the client. The server does not use
433 the protocols's priority except for disabling protocols that were not
436 Processes must be initialized with this function before other GnuTLS
437 functions are used. This function allocates resources which can only
438 be deallocated by calling `gnutls-deinit' or by calling it again.
440 The callbacks alist can have a `verify' key, associated with a
441 verification function (UNUSED).
443 Each authentication type may need additional information in order to
444 work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
445 one trustfile (usually a CA bundle). */)
446 (Lisp_Object proc
, Lisp_Object type
, Lisp_Object proplist
)
448 int ret
= GNUTLS_E_SUCCESS
;
450 int max_log_level
= 0;
452 /* TODO: GNUTLS_X509_FMT_DER is also an option. */
453 int file_format
= GNUTLS_X509_FMT_PEM
;
455 unsigned int gnutls_verify_flags
= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
;
456 gnutls_x509_crt_t gnutls_verify_cert
;
457 unsigned int gnutls_verify_cert_list_size
;
458 const gnutls_datum_t
*gnutls_verify_cert_list
;
460 gnutls_session_t state
;
461 gnutls_certificate_credentials_t x509_cred
;
462 gnutls_anon_client_credentials_t anon_cred
;
463 Lisp_Object global_init
;
464 char* priority_string_ptr
= "NORMAL"; /* default priority string. */
466 int peer_verification
;
469 /* Placeholders for the property list elements. */
470 Lisp_Object priority_string
;
471 Lisp_Object trustfiles
;
472 Lisp_Object keyfiles
;
473 Lisp_Object callbacks
;
474 Lisp_Object loglevel
;
475 Lisp_Object hostname
;
476 Lisp_Object verify_flags
;
477 Lisp_Object verify_error
;
478 Lisp_Object verify_hostname_error
;
480 CHECK_PROCESS (proc
);
482 CHECK_LIST (proplist
);
484 hostname
= Fplist_get (proplist
, Qgnutls_bootprop_hostname
);
485 priority_string
= Fplist_get (proplist
, Qgnutls_bootprop_priority
);
486 trustfiles
= Fplist_get (proplist
, Qgnutls_bootprop_trustfiles
);
487 keyfiles
= Fplist_get (proplist
, Qgnutls_bootprop_keyfiles
);
488 callbacks
= Fplist_get (proplist
, Qgnutls_bootprop_callbacks
);
489 loglevel
= Fplist_get (proplist
, Qgnutls_bootprop_loglevel
);
490 verify_flags
= Fplist_get (proplist
, Qgnutls_bootprop_verify_flags
);
491 verify_error
= Fplist_get (proplist
, Qgnutls_bootprop_verify_error
);
492 verify_hostname_error
= Fplist_get (proplist
, Qgnutls_bootprop_verify_hostname_error
);
494 if (!STRINGP (hostname
))
495 error ("gnutls-boot: invalid :hostname parameter");
497 c_hostname
= SSDATA (hostname
);
499 state
= XPROCESS (proc
)->gnutls_state
;
500 XPROCESS (proc
)->gnutls_p
= 1;
502 if (NUMBERP (loglevel
))
504 gnutls_global_set_log_function (gnutls_log_function
);
505 gnutls_global_set_log_level (XINT (loglevel
));
506 max_log_level
= XINT (loglevel
);
507 XPROCESS (proc
)->gnutls_log_level
= max_log_level
;
510 /* always initialize globals. */
511 global_init
= emacs_gnutls_global_init ();
512 if (! NILP (Fgnutls_errorp (global_init
)))
515 /* deinit and free resources. */
516 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_CRED_ALLOC
)
518 GNUTLS_LOG (1, max_log_level
, "deallocating credentials");
520 if (EQ (type
, Qgnutls_x509pki
))
522 GNUTLS_LOG (2, max_log_level
, "deallocating x509 credentials");
523 x509_cred
= XPROCESS (proc
)->gnutls_x509_cred
;
524 gnutls_certificate_free_credentials (x509_cred
);
526 else if (EQ (type
, Qgnutls_anon
))
528 GNUTLS_LOG (2, max_log_level
, "deallocating anon credentials");
529 anon_cred
= XPROCESS (proc
)->gnutls_anon_cred
;
530 gnutls_anon_free_client_credentials (anon_cred
);
534 error ("unknown credential type");
535 ret
= GNUTLS_EMACS_ERROR_INVALID_TYPE
;
538 if (GNUTLS_INITSTAGE (proc
) >= GNUTLS_STAGE_INIT
)
540 GNUTLS_LOG (1, max_log_level
, "deallocating x509 credentials");
541 Fgnutls_deinit (proc
);
545 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_EMPTY
;
547 GNUTLS_LOG (1, max_log_level
, "allocating credentials");
549 if (EQ (type
, Qgnutls_x509pki
))
551 GNUTLS_LOG (2, max_log_level
, "allocating x509 credentials");
552 x509_cred
= XPROCESS (proc
)->gnutls_x509_cred
;
553 if (gnutls_certificate_allocate_credentials (&x509_cred
) < 0)
556 if (NUMBERP (verify_flags
))
558 gnutls_verify_flags
= XINT (verify_flags
);
559 GNUTLS_LOG (2, max_log_level
, "setting verification flags");
561 else if (NILP (verify_flags
))
563 /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
564 GNUTLS_LOG (2, max_log_level
, "using default verification flags");
568 /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
569 GNUTLS_LOG (2, max_log_level
, "ignoring invalid verify-flags");
571 gnutls_certificate_set_verify_flags (x509_cred
, gnutls_verify_flags
);
573 else if (EQ (type
, Qgnutls_anon
))
575 GNUTLS_LOG (2, max_log_level
, "allocating anon credentials");
576 anon_cred
= XPROCESS (proc
)->gnutls_anon_cred
;
577 if (gnutls_anon_allocate_client_credentials (&anon_cred
) < 0)
582 error ("unknown credential type");
583 ret
= GNUTLS_EMACS_ERROR_INVALID_TYPE
;
586 if (ret
< GNUTLS_E_SUCCESS
)
587 return gnutls_make_error (ret
);
589 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_ALLOC
;
591 if (EQ (type
, Qgnutls_x509pki
))
593 for (tail
= trustfiles
; !NILP (tail
); tail
= Fcdr (tail
))
595 Lisp_Object trustfile
= Fcar (tail
);
596 if (STRINGP (trustfile
))
598 GNUTLS_LOG2 (1, max_log_level
, "setting the trustfile: ",
600 ret
= gnutls_certificate_set_x509_trust_file
605 if (ret
< GNUTLS_E_SUCCESS
)
606 return gnutls_make_error (ret
);
610 error ("Sorry, GnuTLS can't use non-string trustfile %s",
615 for (tail
= keyfiles
; !NILP (tail
); tail
= Fcdr (tail
))
617 Lisp_Object keyfile
= Fcar (tail
);
618 if (STRINGP (keyfile
))
620 GNUTLS_LOG2 (1, max_log_level
, "setting the keyfile: ",
622 ret
= gnutls_certificate_set_x509_crl_file
627 if (ret
< GNUTLS_E_SUCCESS
)
628 return gnutls_make_error (ret
);
632 error ("Sorry, GnuTLS can't use non-string keyfile %s",
638 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_FILES
;
640 GNUTLS_LOG (1, max_log_level
, "gnutls callbacks");
642 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CALLBACKS
;
644 #ifdef HAVE_GNUTLS_CALLBACK_CERTIFICATE_VERIFY
648 GNUTLS_LOG (1, max_log_level
, "gnutls_init");
650 ret
= gnutls_init (&state
, GNUTLS_CLIENT
);
652 if (ret
< GNUTLS_E_SUCCESS
)
653 return gnutls_make_error (ret
);
655 XPROCESS (proc
)->gnutls_state
= state
;
657 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_INIT
;
659 if (STRINGP (priority_string
))
661 priority_string_ptr
= SSDATA (priority_string
);
662 GNUTLS_LOG2 (1, max_log_level
, "got non-default priority string:",
663 priority_string_ptr
);
667 GNUTLS_LOG2 (1, max_log_level
, "using default priority string:",
668 priority_string_ptr
);
671 GNUTLS_LOG (1, max_log_level
, "setting the priority string");
673 ret
= gnutls_priority_set_direct (state
,
677 if (ret
< GNUTLS_E_SUCCESS
)
678 return gnutls_make_error (ret
);
680 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_PRIORITY
;
682 if (EQ (type
, Qgnutls_x509pki
))
684 ret
= gnutls_cred_set (state
, GNUTLS_CRD_CERTIFICATE
, x509_cred
);
686 else if (EQ (type
, Qgnutls_anon
))
688 ret
= gnutls_cred_set (state
, GNUTLS_CRD_ANON
, anon_cred
);
692 error ("unknown credential type");
693 ret
= GNUTLS_EMACS_ERROR_INVALID_TYPE
;
696 if (ret
< GNUTLS_E_SUCCESS
)
697 return gnutls_make_error (ret
);
699 XPROCESS (proc
)->gnutls_anon_cred
= anon_cred
;
700 XPROCESS (proc
)->gnutls_x509_cred
= x509_cred
;
701 XPROCESS (proc
)->gnutls_cred_type
= type
;
703 GNUTLS_INITSTAGE (proc
) = GNUTLS_STAGE_CRED_SET
;
705 ret
= emacs_gnutls_handshake (XPROCESS (proc
));
707 if (ret
< GNUTLS_E_SUCCESS
)
708 return gnutls_make_error (ret
);
710 /* Now verify the peer, following
711 http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
712 The peer should present at least one certificate in the chain; do a
713 check of the certificate's hostname with
714 gnutls_x509_crt_check_hostname() against :hostname. */
716 ret
= gnutls_certificate_verify_peers2 (state
, &peer_verification
);
718 if (ret
< GNUTLS_E_SUCCESS
)
719 return gnutls_make_error (ret
);
721 if (XINT (loglevel
) > 0 && peer_verification
& GNUTLS_CERT_INVALID
)
722 message ("%s certificate could not be verified.",
725 if (peer_verification
& GNUTLS_CERT_REVOKED
)
726 GNUTLS_LOG2 (1, max_log_level
, "certificate was revoked (CRL):",
729 if (peer_verification
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
730 GNUTLS_LOG2 (1, max_log_level
, "certificate signer was not found:",
733 if (peer_verification
& GNUTLS_CERT_SIGNER_NOT_CA
)
734 GNUTLS_LOG2 (1, max_log_level
, "certificate signer is not a CA:",
737 if (peer_verification
& GNUTLS_CERT_INSECURE_ALGORITHM
)
738 GNUTLS_LOG2 (1, max_log_level
,
739 "certificate was signed with an insecure algorithm:",
742 if (peer_verification
& GNUTLS_CERT_NOT_ACTIVATED
)
743 GNUTLS_LOG2 (1, max_log_level
, "certificate is not yet activated:",
746 if (peer_verification
& GNUTLS_CERT_EXPIRED
)
747 GNUTLS_LOG2 (1, max_log_level
, "certificate has expired:",
750 if (peer_verification
!= 0)
752 if (NILP (verify_hostname_error
))
754 GNUTLS_LOG2 (1, max_log_level
, "certificate validation failed:",
759 error ("Certificate validation failed %s, verification code %d",
760 c_hostname
, peer_verification
);
764 /* Up to here the process is the same for X.509 certificates and
765 OpenPGP keys. From now on X.509 certificates are assumed. This
766 can be easily extended to work with openpgp keys as well. */
767 if (gnutls_certificate_type_get (state
) == GNUTLS_CRT_X509
)
769 ret
= gnutls_x509_crt_init (&gnutls_verify_cert
);
771 if (ret
< GNUTLS_E_SUCCESS
)
772 return gnutls_make_error (ret
);
774 gnutls_verify_cert_list
=
775 gnutls_certificate_get_peers (state
, &gnutls_verify_cert_list_size
);
777 if (NULL
== gnutls_verify_cert_list
)
779 error ("No x509 certificate was found!\n");
782 /* We only check the first certificate in the given chain. */
783 ret
= gnutls_x509_crt_import (gnutls_verify_cert
,
784 &gnutls_verify_cert_list
[0],
785 GNUTLS_X509_FMT_DER
);
787 if (ret
< GNUTLS_E_SUCCESS
)
789 gnutls_x509_crt_deinit (gnutls_verify_cert
);
790 return gnutls_make_error (ret
);
793 if (!gnutls_x509_crt_check_hostname (gnutls_verify_cert
, c_hostname
))
795 if (NILP (verify_hostname_error
))
797 GNUTLS_LOG2 (1, max_log_level
, "x509 certificate does not match:",
802 gnutls_x509_crt_deinit (gnutls_verify_cert
);
803 error ("The x509 certificate does not match \"%s\"",
808 gnutls_x509_crt_deinit (gnutls_verify_cert
);
811 return gnutls_make_error (ret
);
814 DEFUN ("gnutls-bye", Fgnutls_bye
,
815 Sgnutls_bye
, 2, 2, 0,
816 doc
: /* Terminate current GnuTLS connection for process PROC.
817 The connection should have been initiated using `gnutls-handshake'.
819 If CONT is not nil the TLS connection gets terminated and further
820 receives and sends will be disallowed. If the return value is zero you
821 may continue using the connection. If CONT is nil, GnuTLS actually
822 sends an alert containing a close request and waits for the peer to
823 reply with the same message. In order to reuse the connection you
824 should wait for an EOF from the peer.
826 This function may also return `gnutls-e-again', or
827 `gnutls-e-interrupted'. */)
828 (Lisp_Object proc
, Lisp_Object cont
)
830 gnutls_session_t state
;
833 CHECK_PROCESS (proc
);
835 state
= XPROCESS (proc
)->gnutls_state
;
837 ret
= gnutls_bye (state
,
838 NILP (cont
) ? GNUTLS_SHUT_RDWR
: GNUTLS_SHUT_WR
);
840 return gnutls_make_error (ret
);
844 syms_of_gnutls (void)
846 gnutls_global_initialized
= 0;
848 Qgnutls_log_level
= intern_c_string ("gnutls-log-level");
849 staticpro (&Qgnutls_log_level
);
851 Qgnutls_code
= intern_c_string ("gnutls-code");
852 staticpro (&Qgnutls_code
);
854 Qgnutls_anon
= intern_c_string ("gnutls-anon");
855 staticpro (&Qgnutls_anon
);
857 Qgnutls_x509pki
= intern_c_string ("gnutls-x509pki");
858 staticpro (&Qgnutls_x509pki
);
860 Qgnutls_bootprop_hostname
= intern_c_string (":hostname");
861 staticpro (&Qgnutls_bootprop_hostname
);
863 Qgnutls_bootprop_priority
= intern_c_string (":priority");
864 staticpro (&Qgnutls_bootprop_priority
);
866 Qgnutls_bootprop_trustfiles
= intern_c_string (":trustfiles");
867 staticpro (&Qgnutls_bootprop_trustfiles
);
869 Qgnutls_bootprop_keyfiles
= intern_c_string (":keyfiles");
870 staticpro (&Qgnutls_bootprop_keyfiles
);
872 Qgnutls_bootprop_callbacks
= intern_c_string (":callbacks");
873 staticpro (&Qgnutls_bootprop_callbacks
);
875 Qgnutls_bootprop_callbacks_verify
= intern_c_string ("verify");
876 staticpro (&Qgnutls_bootprop_callbacks_verify
);
878 Qgnutls_bootprop_loglevel
= intern_c_string (":loglevel");
879 staticpro (&Qgnutls_bootprop_loglevel
);
881 Qgnutls_bootprop_verify_flags
= intern_c_string (":verify-flags");
882 staticpro (&Qgnutls_bootprop_verify_flags
);
884 Qgnutls_bootprop_verify_hostname_error
= intern_c_string (":verify-error");
885 staticpro (&Qgnutls_bootprop_verify_error
);
887 Qgnutls_bootprop_verify_hostname_error
= intern_c_string (":verify-hostname-error");
888 staticpro (&Qgnutls_bootprop_verify_hostname_error
);
890 Qgnutls_e_interrupted
= intern_c_string ("gnutls-e-interrupted");
891 staticpro (&Qgnutls_e_interrupted
);
892 Fput (Qgnutls_e_interrupted
, Qgnutls_code
,
893 make_number (GNUTLS_E_INTERRUPTED
));
895 Qgnutls_e_again
= intern_c_string ("gnutls-e-again");
896 staticpro (&Qgnutls_e_again
);
897 Fput (Qgnutls_e_again
, Qgnutls_code
,
898 make_number (GNUTLS_E_AGAIN
));
900 Qgnutls_e_invalid_session
= intern_c_string ("gnutls-e-invalid-session");
901 staticpro (&Qgnutls_e_invalid_session
);
902 Fput (Qgnutls_e_invalid_session
, Qgnutls_code
,
903 make_number (GNUTLS_E_INVALID_SESSION
));
905 Qgnutls_e_not_ready_for_handshake
=
906 intern_c_string ("gnutls-e-not-ready-for-handshake");
907 staticpro (&Qgnutls_e_not_ready_for_handshake
);
908 Fput (Qgnutls_e_not_ready_for_handshake
, Qgnutls_code
,
909 make_number (GNUTLS_E_APPLICATION_ERROR_MIN
));
911 defsubr (&Sgnutls_get_initstage
);
912 defsubr (&Sgnutls_errorp
);
913 defsubr (&Sgnutls_error_fatalp
);
914 defsubr (&Sgnutls_error_string
);
915 defsubr (&Sgnutls_boot
);
916 defsubr (&Sgnutls_deinit
);
917 defsubr (&Sgnutls_bye
);