|
|
1db854 |
From 59fd52bfdd7e4a763b5d950ee2213b3bb1e69916 Mon Sep 17 00:00:00 2001
|
|
|
1db854 |
From: Jan Synacek <jsynacek@redhat.com>
|
|
|
1db854 |
Date: Tue, 11 Sep 2018 13:03:56 +0200
|
|
|
1db854 |
Subject: [PATCH 1/2] New verify-error GnuTLS interface for certificate
|
|
|
1db854 |
validation
|
|
|
1db854 |
|
|
|
1db854 |
* net/gnutls.el (gnutls-verify-error): New defcustom to control
|
|
|
1db854 |
the behavior when a certificate fails validation. Defaults to
|
|
|
1db854 |
old behavior: never abort, just warn.
|
|
|
1db854 |
(gnutls-negotiate): Use it.
|
|
|
1db854 |
|
|
|
1db854 |
* gnutls.c: Replace `:verify_hostname_error' with `:verify_error',
|
|
|
1db854 |
now a list of certificate validation checks that will abort a
|
|
|
1db854 |
connection with an error.
|
|
|
1db854 |
(Fgnutls_boot): Document it and use it.
|
|
|
1db854 |
|
|
|
1db854 |
(cherry-picked from commit 31b4827ea9ba8d22deb17c0593f0f555a33e1fa4)
|
|
|
1db854 |
|
|
|
1db854 |
jsynacek: gnutls-verify-error defaults to t in RHEL-7.
|
|
|
1db854 |
|
|
|
1db854 |
Resolves: #1403643
|
|
|
1db854 |
---
|
|
|
1db854 |
lisp/net/gnutls.el | 67 ++++++++++++++++++++++++++++++++++++++++------------
|
|
|
1db854 |
src/bootstrap-emacs | Bin 25556936 -> 0 bytes
|
|
|
1db854 |
src/emacs | Bin 25556936 -> 0 bytes
|
|
|
1db854 |
src/fns.c | 22 ++++++++++++++++-
|
|
|
1db854 |
src/gnutls.c | 48 +++++++++++++++++++++++--------------
|
|
|
1db854 |
src/temacs | Bin 15992560 -> 0 bytes
|
|
|
1db854 |
6 files changed, 103 insertions(+), 34 deletions(-)
|
|
|
1db854 |
delete mode 100755 src/bootstrap-emacs
|
|
|
1db854 |
delete mode 100755 src/emacs
|
|
|
1db854 |
delete mode 100755 src/temacs
|
|
|
1db854 |
|
|
|
1db854 |
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
|
|
|
1db854 |
index 243c64e..2585f48 100644
|
|
|
1db854 |
--- a/lisp/net/gnutls.el
|
|
|
1db854 |
+++ b/lisp/net/gnutls.el
|
|
|
1db854 |
@@ -51,6 +51,19 @@ set this variable to \"normal:-dhe-rsa\"."
|
|
|
1db854 |
:type '(choice (const nil)
|
|
|
1db854 |
string))
|
|
|
1db854 |
|
|
|
1db854 |
+(defcustom gnutls-verify-error t
|
|
|
1db854 |
+ "If non-nil, this should be a list of checks per hostname regex or t."
|
|
|
1db854 |
+ :group 'gnutls
|
|
|
1db854 |
+ :type '(choice
|
|
|
1db854 |
+ (const t)
|
|
|
1db854 |
+ (repeat :tag "List of hostname regexps with flags for each"
|
|
|
1db854 |
+ (list
|
|
|
1db854 |
+ (choice :tag "Hostname"
|
|
|
1db854 |
+ (const ".*" :tag "Any hostname")
|
|
|
1db854 |
+ regexp)
|
|
|
1db854 |
+ (set (const :trustfiles)
|
|
|
1db854 |
+ (const :hostname))))))
|
|
|
1db854 |
+
|
|
|
1db854 |
(defcustom gnutls-trustfiles
|
|
|
1db854 |
'(
|
|
|
1db854 |
"/etc/ssl/certs/ca-certificates.crt" ; Debian, Ubuntu, Gentoo and Arch Linux
|
|
|
1db854 |
@@ -141,19 +154,25 @@ MIN-PRIME-BITS is the minimum acceptable size of Diffie-Hellman keys
|
|
|
1db854 |
\(see `gnutls-min-prime-bits' for more information). Use nil for the
|
|
|
1db854 |
default.
|
|
|
1db854 |
|
|
|
1db854 |
-When VERIFY-HOSTNAME-ERROR is not nil, an error will be raised
|
|
|
1db854 |
-when the hostname does not match the presented certificate's host
|
|
|
1db854 |
-name. The exact verification algorithm is a basic implementation
|
|
|
1db854 |
-of the matching described in RFC2818 (HTTPS), which takes into
|
|
|
1db854 |
-account wildcards, and the DNSName/IPAddress subject alternative
|
|
|
1db854 |
-name PKIX extension. See GnuTLS' gnutls_x509_crt_check_hostname
|
|
|
1db854 |
-for details. When VERIFY-HOSTNAME-ERROR is nil, only a warning
|
|
|
1db854 |
-will be issued.
|
|
|
1db854 |
+VERIFY-HOSTNAME-ERROR is a backwards compatibility option for
|
|
|
1db854 |
+putting `:hostname' in VERIFY-ERROR.
|
|
|
1db854 |
+
|
|
|
1db854 |
+When VERIFY-ERROR is t or a list containing `:trustfiles', an
|
|
|
1db854 |
+error will be raised when the peer certificate verification fails
|
|
|
1db854 |
+as per GnuTLS' gnutls_certificate_verify_peers2. Otherwise, only
|
|
|
1db854 |
+warnings will be shown about the verification failure.
|
|
|
1db854 |
|
|
|
1db854 |
-When VERIFY-ERROR is not nil, an error will be raised when the
|
|
|
1db854 |
-peer certificate verification fails as per GnuTLS'
|
|
|
1db854 |
-gnutls_certificate_verify_peers2. Otherwise, only warnings will
|
|
|
1db854 |
-be shown about the verification failure.
|
|
|
1db854 |
+When VERIFY-ERROR is t or a list containing `:hostname', an error
|
|
|
1db854 |
+will be raised when the hostname does not match the presented
|
|
|
1db854 |
+certificate's host name. The exact verification algorithm is a
|
|
|
1db854 |
+basic implementation of the matching described in
|
|
|
1db854 |
+RFC2818 (HTTPS), which takes into account wildcards, and the
|
|
|
1db854 |
+DNSName/IPAddress subject alternative name PKIX extension. See
|
|
|
1db854 |
+GnuTLS' gnutls_x509_crt_check_hostname for details. Otherwise,
|
|
|
1db854 |
+only a warning will be issued.
|
|
|
1db854 |
+
|
|
|
1db854 |
+Note that the list in `gnutls-verify-error', matched against the
|
|
|
1db854 |
+HOSTNAME, is the default VERIFY-ERROR.
|
|
|
1db854 |
|
|
|
1db854 |
VERIFY-FLAGS is a numeric OR of verification flags only for
|
|
|
1db854 |
`gnutls-x509pki' connections. See GnuTLS' x509.h for details;
|
|
|
1db854 |
@@ -186,8 +205,28 @@ defaults to GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT."
|
|
|
1db854 |
(if gnutls-algorithm-priority
|
|
|
1db854 |
(upcase gnutls-algorithm-priority)
|
|
|
1db854 |
"NORMAL")))))
|
|
|
1db854 |
+ (verify-error (or verify-error
|
|
|
1db854 |
+ ;; this uses the value of `gnutls-verify-error'
|
|
|
1db854 |
+ (cond
|
|
|
1db854 |
+ ;; if t, pass it on
|
|
|
1db854 |
+ ((eq gnutls-verify-error t)
|
|
|
1db854 |
+ t)
|
|
|
1db854 |
+ ;; if a list, look for hostname matches
|
|
|
1db854 |
+ ((listp gnutls-verify-error)
|
|
|
1db854 |
+ (mapcan
|
|
|
1db854 |
+ (lambda (check)
|
|
|
1db854 |
+ (when (string-match (car check) hostname)
|
|
|
1db854 |
+ (cdr check)))
|
|
|
1db854 |
+ gnutls-verify-error))
|
|
|
1db854 |
+ ;; else it's nil
|
|
|
1db854 |
+ (t nil))))
|
|
|
1db854 |
(min-prime-bits (or min-prime-bits gnutls-min-prime-bits))
|
|
|
1db854 |
- (params `(:priority ,priority-string
|
|
|
1db854 |
+ params ret)
|
|
|
1db854 |
+
|
|
|
1db854 |
+ (when verify-hostname-error
|
|
|
1db854 |
+ (push :hostname verify-error))
|
|
|
1db854 |
+
|
|
|
1db854 |
+ (setq params `(:priority ,priority-string
|
|
|
1db854 |
:hostname ,hostname
|
|
|
1db854 |
:loglevel ,gnutls-log-level
|
|
|
1db854 |
:min-prime-bits ,min-prime-bits
|
|
|
1db854 |
@@ -196,9 +235,7 @@ defaults to GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT."
|
|
|
1db854 |
:keylist ,keylist
|
|
|
1db854 |
:verify-flags ,verify-flags
|
|
|
1db854 |
:verify-error ,verify-error
|
|
|
1db854 |
- :verify-hostname-error ,verify-hostname-error
|
|
|
1db854 |
:callbacks nil))
|
|
|
1db854 |
- ret)
|
|
|
1db854 |
|
|
|
1db854 |
(gnutls-message-maybe
|
|
|
1db854 |
(setq ret (gnutls-boot process type params))
|
|
|
1db854 |
diff --git a/src/fns.c b/src/fns.c
|
|
|
1db854 |
index fbb3fb5..2a417ff 100644
|
|
|
1db854 |
--- a/src/fns.c
|
|
|
1db854 |
+++ b/src/fns.c
|
|
|
1db854 |
@@ -2252,7 +2252,7 @@ usage: (nconc &rest LISTS) */)
|
|
|
1db854 |
storing the results into elements of VALS, a C vector of Lisp_Objects.
|
|
|
1db854 |
LENI is the length of VALS, which should also be the length of SEQ. */
|
|
|
1db854 |
|
|
|
1db854 |
-static void
|
|
|
1db854 |
+static EMACS_INT
|
|
|
1db854 |
mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
|
|
|
1db854 |
{
|
|
|
1db854 |
register Lisp_Object tail;
|
|
|
1db854 |
@@ -2326,6 +2326,7 @@ mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
|
|
|
1db854 |
}
|
|
|
1db854 |
|
|
|
1db854 |
UNGCPRO;
|
|
|
1db854 |
+ return leni;
|
|
|
1db854 |
}
|
|
|
1db854 |
|
|
|
1db854 |
DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
|
|
|
1db854 |
@@ -2411,6 +2412,24 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string. */)
|
|
|
1db854 |
|
|
|
1db854 |
return sequence;
|
|
|
1db854 |
}
|
|
|
1db854 |
+
|
|
|
1db854 |
+DEFUN ("mapcan", Fmapcan, Smapcan, 2, 2, 0,
|
|
|
1db854 |
+ doc: /* Apply FUNCTION to each element of SEQUENCE, and concatenate
|
|
|
1db854 |
+the results by altering them (using `nconc').
|
|
|
1db854 |
+SEQUENCE may be a list, a vector, a bool-vector, or a string. */)
|
|
|
1db854 |
+ (Lisp_Object function, Lisp_Object sequence)
|
|
|
1db854 |
+{
|
|
|
1db854 |
+ USE_SAFE_ALLOCA;
|
|
|
1db854 |
+ EMACS_INT leni = XFASTINT (Flength (sequence));
|
|
|
1db854 |
+ if (CHAR_TABLE_P (sequence))
|
|
|
1db854 |
+ wrong_type_argument (Qlistp, sequence);
|
|
|
1db854 |
+ Lisp_Object *args;
|
|
|
1db854 |
+ SAFE_ALLOCA_LISP (args, leni);
|
|
|
1db854 |
+ ptrdiff_t nmapped = mapcar1 (leni, args, function, sequence);
|
|
|
1db854 |
+ Lisp_Object ret = Fnconc (nmapped, args);
|
|
|
1db854 |
+ SAFE_FREE ();
|
|
|
1db854 |
+ return ret;
|
|
|
1db854 |
+}
|
|
|
1db854 |
|
|
|
1db854 |
/* This is how C code calls `yes-or-no-p' and allows the user
|
|
|
1db854 |
to redefined it.
|
|
|
1db854 |
@@ -4984,6 +5003,7 @@ this variable. */);
|
|
|
1db854 |
defsubr (&Snconc);
|
|
|
1db854 |
defsubr (&Smapcar);
|
|
|
1db854 |
defsubr (&Smapc);
|
|
|
1db854 |
+ defsubr (&Smapcan);
|
|
|
1db854 |
defsubr (&Smapconcat);
|
|
|
1db854 |
defsubr (&Syes_or_no_p);
|
|
|
1db854 |
defsubr (&Sload_average);
|
|
|
1db854 |
diff --git a/src/gnutls.c b/src/gnutls.c
|
|
|
1db854 |
index 57d9e17..0c4d10b 100644
|
|
|
1db854 |
--- a/src/gnutls.c
|
|
|
1db854 |
+++ b/src/gnutls.c
|
|
|
1db854 |
@@ -49,7 +49,7 @@ static Lisp_Object QCgnutls_bootprop_loglevel;
|
|
|
1db854 |
static Lisp_Object QCgnutls_bootprop_hostname;
|
|
|
1db854 |
static Lisp_Object QCgnutls_bootprop_min_prime_bits;
|
|
|
1db854 |
static Lisp_Object QCgnutls_bootprop_verify_flags;
|
|
|
1db854 |
-static Lisp_Object QCgnutls_bootprop_verify_hostname_error;
|
|
|
1db854 |
+static Lisp_Object QCgnutls_bootprop_verify_error;
|
|
|
1db854 |
|
|
|
1db854 |
/* Callback keys for `gnutls-boot'. Unused currently. */
|
|
|
1db854 |
static Lisp_Object QCgnutls_bootprop_callbacks_verify;
|
|
|
1db854 |
@@ -729,8 +729,12 @@ certificates for `gnutls-x509pki'.
|
|
|
1db854 |
:verify-flags is a bitset as per GnuTLS'
|
|
|
1db854 |
gnutls_certificate_set_verify_flags.
|
|
|
1db854 |
|
|
|
1db854 |
-:verify-hostname-error, if non-nil, makes a hostname mismatch an
|
|
|
1db854 |
-error. Otherwise it will be just a warning.
|
|
|
1db854 |
+:verify-hostname-error is ignored. Pass :hostname in :verify-error
|
|
|
1db854 |
+instead.
|
|
|
1db854 |
+
|
|
|
1db854 |
+:verify-error is a list of symbols to express verification checks or
|
|
|
1db854 |
+`t' to do all checks. Currently it can contain `:trustfiles' and
|
|
|
1db854 |
+`:hostname' to verify the certificate or the hostname respectively.
|
|
|
1db854 |
|
|
|
1db854 |
:min-prime-bits is the minimum accepted number of bits the client will
|
|
|
1db854 |
accept in Diffie-Hellman key exchange.
|
|
|
1db854 |
@@ -774,8 +778,7 @@ one trustfile (usually a CA bundle). */)
|
|
|
1db854 |
/* Lisp_Object callbacks; */
|
|
|
1db854 |
Lisp_Object loglevel;
|
|
|
1db854 |
Lisp_Object hostname;
|
|
|
1db854 |
- /* Lisp_Object verify_error; */
|
|
|
1db854 |
- Lisp_Object verify_hostname_error;
|
|
|
1db854 |
+ Lisp_Object verify_error;
|
|
|
1db854 |
Lisp_Object prime_bits;
|
|
|
1db854 |
|
|
|
1db854 |
CHECK_PROCESS (proc);
|
|
|
1db854 |
@@ -800,11 +803,14 @@ one trustfile (usually a CA bundle). */)
|
|
|
1db854 |
keylist = Fplist_get (proplist, QCgnutls_bootprop_keylist);
|
|
|
1db854 |
crlfiles = Fplist_get (proplist, QCgnutls_bootprop_crlfiles);
|
|
|
1db854 |
loglevel = Fplist_get (proplist, QCgnutls_bootprop_loglevel);
|
|
|
1db854 |
- verify_hostname_error = Fplist_get (proplist, QCgnutls_bootprop_verify_hostname_error);
|
|
|
1db854 |
+ verify_error = Fplist_get (proplist, QCgnutls_bootprop_verify_error);
|
|
|
1db854 |
prime_bits = Fplist_get (proplist, QCgnutls_bootprop_min_prime_bits);
|
|
|
1db854 |
|
|
|
1db854 |
+ if (!Flistp (verify_error))
|
|
|
1db854 |
+ error ("gnutls-boot: invalid :verify_error parameter (not a list)");
|
|
|
1db854 |
+
|
|
|
1db854 |
if (!STRINGP (hostname))
|
|
|
1db854 |
- error ("gnutls-boot: invalid :hostname parameter");
|
|
|
1db854 |
+ error ("gnutls-boot: invalid :hostname parameter (not a string)");
|
|
|
1db854 |
c_hostname = SSDATA (hostname);
|
|
|
1db854 |
|
|
|
1db854 |
state = XPROCESS (proc)->gnutls_state;
|
|
|
1db854 |
@@ -1033,14 +1039,17 @@ one trustfile (usually a CA bundle). */)
|
|
|
1db854 |
|
|
|
1db854 |
if (peer_verification != 0)
|
|
|
1db854 |
{
|
|
|
1db854 |
- if (NILP (verify_hostname_error))
|
|
|
1db854 |
- GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
|
|
|
1db854 |
- c_hostname);
|
|
|
1db854 |
- else
|
|
|
1db854 |
- {
|
|
|
1db854 |
+ if (EQ (verify_error, Qt)
|
|
|
1db854 |
+ || !NILP (Fmember (QCgnutls_bootprop_trustfiles, verify_error)))
|
|
|
1db854 |
+ {
|
|
|
1db854 |
emacs_gnutls_deinit (proc);
|
|
|
1db854 |
error ("Certificate validation failed %s, verification code %d",
|
|
|
1db854 |
c_hostname, peer_verification);
|
|
|
1db854 |
+ }
|
|
|
1db854 |
+ else
|
|
|
1db854 |
+ {
|
|
|
1db854 |
+ GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
|
|
|
1db854 |
+ c_hostname);
|
|
|
1db854 |
}
|
|
|
1db854 |
}
|
|
|
1db854 |
|
|
|
1db854 |
@@ -1080,14 +1089,17 @@ one trustfile (usually a CA bundle). */)
|
|
|
1db854 |
|
|
|
1db854 |
if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
|
|
|
1db854 |
{
|
|
|
1db854 |
- if (NILP (verify_hostname_error))
|
|
|
1db854 |
- GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
|
|
|
1db854 |
- c_hostname);
|
|
|
1db854 |
- else
|
|
|
1db854 |
- {
|
|
|
1db854 |
+ if (EQ (verify_error, Qt)
|
|
|
1db854 |
+ || !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error)))
|
|
|
1db854 |
+ {
|
|
|
1db854 |
fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
|
|
|
1db854 |
emacs_gnutls_deinit (proc);
|
|
|
1db854 |
error ("The x509 certificate does not match \"%s\"", c_hostname);
|
|
|
1db854 |
+ }
|
|
|
1db854 |
+ else
|
|
|
1db854 |
+ {
|
|
|
1db854 |
+ GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
|
|
|
1db854 |
+ c_hostname);
|
|
|
1db854 |
}
|
|
|
1db854 |
}
|
|
|
1db854 |
fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
|
|
|
1db854 |
@@ -1144,7 +1156,7 @@ syms_of_gnutls (void)
|
|
|
1db854 |
DEFSYM (QCgnutls_bootprop_min_prime_bits, ":min-prime-bits");
|
|
|
1db854 |
DEFSYM (QCgnutls_bootprop_loglevel, ":loglevel");
|
|
|
1db854 |
DEFSYM (QCgnutls_bootprop_verify_flags, ":verify-flags");
|
|
|
1db854 |
- DEFSYM (QCgnutls_bootprop_verify_hostname_error, ":verify-hostname-error");
|
|
|
1db854 |
+ DEFSYM (QCgnutls_bootprop_verify_error, ":verify-error");
|
|
|
1db854 |
|
|
|
1db854 |
DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
|
|
|
1db854 |
Fput (Qgnutls_e_interrupted, Qgnutls_code,
|
|
|
1db854 |
|