Make Electric Pair mode smarter/more useful:
[bpt/emacs.git] / src / gnutls.c
index 5a29616..a20665a 100644 (file)
@@ -21,6 +21,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "lisp.h"
 #include "process.h"
+#include "coding.h"
 
 #ifdef HAVE_GNUTLS
 #include <gnutls/gnutls.h>
@@ -49,7 +50,7 @@ static Lisp_Object QCgnutls_bootprop_loglevel;
 static Lisp_Object QCgnutls_bootprop_hostname;
 static Lisp_Object QCgnutls_bootprop_min_prime_bits;
 static Lisp_Object QCgnutls_bootprop_verify_flags;
-static Lisp_Object QCgnutls_bootprop_verify_hostname_error;
+static Lisp_Object QCgnutls_bootprop_verify_error;
 
 /* Callback keys for `gnutls-boot'.  Unused currently.  */
 static Lisp_Object QCgnutls_bootprop_callbacks_verify;
@@ -364,7 +365,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
   return ret;
 }
 
-int
+ptrdiff_t
 emacs_gnutls_record_check_pending (gnutls_session_t state)
 {
   return fn_gnutls_record_check_pending (state);
@@ -753,8 +754,12 @@ certificates for `gnutls-x509pki'.
 :verify-flags is a bitset as per GnuTLS'
 gnutls_certificate_set_verify_flags.
 
-:verify-hostname-error, if non-nil, makes a hostname mismatch an
-error.  Otherwise it will be just a warning.
+:verify-hostname-error is ignored.  Pass :hostname in :verify-error
+instead.
+
+:verify-error is a list of symbols to express verification checks or
+`t' to do all checks.  Currently it can contain `:trustfiles' and
+`:hostname' to verify the certificate or the hostname respectively.
 
 :min-prime-bits is the minimum accepted number of bits the client will
 accept in Diffie-Hellman key exchange.
@@ -798,8 +803,7 @@ one trustfile (usually a CA bundle).  */)
   /* Lisp_Object callbacks; */
   Lisp_Object loglevel;
   Lisp_Object hostname;
-  /* Lisp_Object verify_error; */
-  Lisp_Object verify_hostname_error;
+  Lisp_Object verify_error;
   Lisp_Object prime_bits;
 
   CHECK_PROCESS (proc);
@@ -818,11 +822,14 @@ one trustfile (usually a CA bundle).  */)
   keylist               = Fplist_get (proplist, QCgnutls_bootprop_keylist);
   crlfiles              = Fplist_get (proplist, QCgnutls_bootprop_crlfiles);
   loglevel              = Fplist_get (proplist, QCgnutls_bootprop_loglevel);
-  verify_hostname_error = Fplist_get (proplist, QCgnutls_bootprop_verify_hostname_error);
+  verify_error          = Fplist_get (proplist, QCgnutls_bootprop_verify_error);
   prime_bits            = Fplist_get (proplist, QCgnutls_bootprop_min_prime_bits);
 
+  if (NILP (Flistp (verify_error)))
+    error ("gnutls-boot: invalid :verify_error parameter (not a list)");
+
   if (!STRINGP (hostname))
-    error ("gnutls-boot: invalid :hostname parameter");
+    error ("gnutls-boot: invalid :hostname parameter (not a string)");
   c_hostname = SSDATA (hostname);
 
   state = XPROCESS (proc)->gnutls_state;
@@ -899,6 +906,13 @@ one trustfile (usually a CA bundle).  */)
            {
              GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
                           SSDATA (trustfile));
+             trustfile = ENCODE_FILE (trustfile);
+#ifdef WINDOWSNT
+             /* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
+                file names on Windows, we need to re-encode the file
+                name using the current ANSI codepage.  */
+             trustfile = ansi_encode_filename (trustfile);
+#endif
              ret = fn_gnutls_certificate_set_x509_trust_file
                (x509_cred,
                 SSDATA (trustfile),
@@ -921,6 +935,10 @@ one trustfile (usually a CA bundle).  */)
            {
              GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
                           SSDATA (crlfile));
+             crlfile = ENCODE_FILE (crlfile);
+#ifdef WINDOWSNT
+             crlfile = ansi_encode_filename (crlfile);
+#endif
              ret = fn_gnutls_certificate_set_x509_crl_file
                (x509_cred, SSDATA (crlfile), file_format);
 
@@ -944,6 +962,12 @@ one trustfile (usually a CA bundle).  */)
                           SSDATA (keyfile));
              GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
                           SSDATA (certfile));
+             keyfile = ENCODE_FILE (keyfile);
+             certfile = ENCODE_FILE (certfile);
+#ifdef WINDOWSNT
+             keyfile = ansi_encode_filename (keyfile);
+             certfile = ansi_encode_filename (certfile);
+#endif
              ret = fn_gnutls_certificate_set_x509_key_file
                (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
 
@@ -1047,14 +1071,16 @@ one trustfile (usually a CA bundle).  */)
 
   if (peer_verification != 0)
     {
-      if (NILP (verify_hostname_error))
-       GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
-                    c_hostname);
-      else
-       {
+      if (!NILP (Fmember (QCgnutls_bootprop_trustfiles, verify_error)))
+        {
          emacs_gnutls_deinit (proc);
          error ("Certificate validation failed %s, verification code %d",
                 c_hostname, peer_verification);
+        }
+      else
+       {
+          GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
+                       c_hostname);
        }
     }
 
@@ -1094,14 +1120,16 @@ one trustfile (usually a CA bundle).  */)
 
       if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
        {
-         if (NILP (verify_hostname_error))
-           GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
-                        c_hostname);
-         else
-           {
+          if (!NILP (Fmember (QCgnutls_bootprop_hostname, verify_error)))
+            {
              fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
              emacs_gnutls_deinit (proc);
              error ("The x509 certificate does not match \"%s\"", c_hostname);
+            }
+         else
+           {
+              GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
+                           c_hostname);
            }
        }
       fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
@@ -1161,7 +1189,7 @@ syms_of_gnutls (void)
   DEFSYM (QCgnutls_bootprop_min_prime_bits, ":min-prime-bits");
   DEFSYM (QCgnutls_bootprop_loglevel, ":loglevel");
   DEFSYM (QCgnutls_bootprop_verify_flags, ":verify-flags");
-  DEFSYM (QCgnutls_bootprop_verify_hostname_error, ":verify-hostname-error");
+  DEFSYM (QCgnutls_bootprop_verify_error, ":verify-error");
 
   DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
   Fput (Qgnutls_e_interrupted, Qgnutls_code,