6

After reading this post I decided to harder the security of Emacs. However, after setting everything and doing the test, Emacs is still ill-configured. Everything is done in a GNU/Linux distribution.

Installing certifi

As said the in the blog post above, we install certifi

pip3 install -U --user certifi

I check that the module have been installed correctly

python3 -m certifi

Which it was!

/home/jorge/.local/lib/python3.5/site-packages/certifi/cacert.pem

Configuring Emacs

I little modified version of the elisp snippet from the blog post above.

(let ((trustfile
       (replace-regexp-in-string
        "\\\\" "/"
        (replace-regexp-in-string
         "\n" ""
         (shell-command-to-string "python3 -m certifi")))))
  (setf tls-program
        (list
         (format "gnutls-cli%s --x509cafile %s -p %%p %%h"
                 (if (eq window-system 'w32) ".exe" "") trustfile)))
  (setf tls-checktrust t)
  (setf gnutls-verify-error t)
  (setf gnutls-trustfiles (list trustfile)))

Testing the configuration

Again, another snippet of elisp slightly modified by me.

(let ((bad-hosts
       (loop for bad
             in `("https://wrong.host.badssl.com/"
                  "https://self-signed.badssl.com/")
             if (condition-case e
                    (url-retrieve
                     bad (lambda (retrieved) t))
                  (error nil))
             collect bad)))
  (if bad-hosts
      (print (format "tls misconfigured; retrieved %s ok"
                     bad-hosts))
    (url-retrieve "https://badssl.com"
                  (lambda (retrieved) t))))

After running that snippet, I get this output:

"tls misconfigured; retrieved (https://self-signed.badssl.com/) ok"

What am I doing wrong?


Edit

Setting gnutls-log-level to 2 output this:

Evaluate this emacs-lisp code block on your system? (y or n) y
executing Emacs-Lisp code block...
Contacting host: wrong.host.badssl.com:443
gnutls.c: [1] (Emacs) allocating credentials
gnutls.c: [2] (Emacs) allocating x509 credentials
gnutls.c: [2] (Emacs) using default verification flags
gnutls.c: [1] (Emacs) setting the trustfile:  /home/jorge/.local/lib/python3.5/site-packages/certifi/cacert.pem
gnutls.c: [1] (Emacs) gnutls callbacks
gnutls.c: [1] (Emacs) gnutls_init
gnutls.c: [1] (Emacs) got non-default priority string: NORMAL
gnutls.c: [1] (Emacs) setting the priority string
gnutls.c: [audit] Note that the security level of the Diffie-Hellman key exchange has been lowered to 256 bits and this may allow decryption of the session data

gnutls.c: [1] (Emacs) non-fatal error: Resource temporarily unavailable, try again. [4822 times]
Contacting host: self-signed.badssl.com:443
gnutls.c: [1] (Emacs) allocating credentials
gnutls.c: [2] (Emacs) allocating x509 credentials
gnutls.c: [2] (Emacs) using default verification flags
gnutls.c: [1] (Emacs) setting the trustfile:  /home/jorge/.local/lib/python3.5/site-packages/certifi/cacert.pem
gnutls.c: [1] (Emacs) gnutls callbacks
gnutls.c: [1] (Emacs) gnutls_init
gnutls.c: [1] (Emacs) got non-default priority string: NORMAL
gnutls.c: [1] (Emacs) setting the priority string
gnutls.c: [audit] Note that the security level of the Diffie-Hellman key exchange has been lowered to 256 bits and this may allow decryption of the session data

gnutls.c: [1] (Emacs) non-fatal error: Resource temporarily unavailable, try again. [3737 times]
Code block evaluation complete.

EDIT 2

I decided to try fetching another website, a website which such SSL certificate bothers Firefox/Iceweasel:

(url-retrieve "https://parabola.nu/" (lambda (retrieved) t))

Then, I got this sweet error:

Debugger entered--Lisp error: (error "Certificate validation failed parabola.nu, verification code 66")
gnutls-boot(#<process parabola.nu> gnutls-x509pki (:priority "NORMAL" :hostname "parabola.nu" :loglevel 0 :min-prime-bits 256 :trustfiles ("/home/jorge/.local/lib/python3.5/site-packages/certifi/cacert.pem") :crlfiles nil :keylist nil :verify-flags nil :verify-error t :callbacks nil))
gnutls-negotiate(:process #<process parabola.nu> :type gnutls-x509pki :hostname "parabola.nu")
open-gnutls-stream("parabola.nu" #<buffer  *url-http-temp*> "parabola.nu" 443)
network-stream-open-tls("parabola.nu" #<buffer  *url-http-temp*> "parabola.nu" 443 (:type tls :nowait t))
open-network-stream("parabola.nu" #<buffer  *url-http-temp*> "parabola.nu" 443 :type tls :nowait t)
byte-code("\306\211\n\307>\203$\n\310=\203\311\312\f
\313\n\314\315\316\317\"&\202Y\n\320=\2034\321\f
$\202Y\n\322=\203D\323\f
$\202Y\n\324=\203T\325\f
$\202Y\326\327\"*\306\207" [coding-system-for-write coding-system-for-read gw-method name buffer host binary (tls ssl native) native plain open-network-stream :type :nowait featurep make-network-process (:nowait t) socks socks-open-network-stream telnet url-open-telnet rlogin url-open-rlogin error "Bad setting of url-gateway-method: %s" service url-gateway-method conn] 11)
url-open-stream("parabola.nu" #<buffer  *url-http-temp*> "parabola.nu" 443)
url-http-find-free-connection("parabola.nu" 443)
url-http([cl-struct-url "https" nil nil "parabola.nu" nil "/" nil nil t nil t] (lambda (retrieved) t) (nil))
url-https([cl-struct-url "https" nil nil "parabola.nu" nil "/" nil nil t nil t] (lambda (retrieved) t) (nil))
url-retrieve-internal("https://parabola.nu/" (lambda (retrieved) t) (nil) nil nil)
url-retrieve("https://parabola.nu/" (lambda (retrieved) t))
eval((url-retrieve "https://parabola.nu/" (function (lambda (retrieved) t))) nil)
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)

So, so far I can say the changes made to my Emacs configuration are working.

  • 1
    It'd help if you did not shadow the original error in your last snippet. Please get rid of the condition-case, try the script again, and show the actual error that you receive. Also, please set gnutls-verify-error to nil. That makes Emacs show a popup with certificate information if verification fails. – lunaryorn Nov 13 '15 at 22:53
  • 1
    Can you set gnutls-log-level to 2 or higher to see in more detail what gnutls is doing? That may help identify why it accepts a self-signed certificate. – Kirill Nov 13 '15 at 23:05
  • @Kirill I have updated the question with more information – shackra Nov 14 '15 at 3:36
  • 1
    Another thing that bothers me is that url-retrieve is asynchronous, so its return value will likely be a (empty) buffer (gnu.org/software/emacs/manual/html_node/url/…), and the error will not necessarily be caught by the condition-case. Maybe try url-retrieve-synchronously instead? – Kirill Nov 16 '15 at 21:35
  • 1
    Check this reddit comment. It states that the problem is the emacs built-in TLS isn't working. Adding those two lines of code worked for me. – Choma Dec 3 '15 at 15:33
3

I found this reddit comment, which states that the problem is Emacs built-in TLS doesn't reject bad certificates. It proposes using external TLS like this:

(if (fboundp 'gnutls-available-p)
    (fmakunbound 'gnutls-available-p))

NOTE: if you still have issues trying to connect to marmalde repo, it seems to be a different problem. See this github issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.