diff mbox

WIP Java certificates

Message ID 87eg7yy34f.fsf@mdc-berlin.de
State New
Headers show

Commit Message

Ricardo Wurmus June 15, 2016, 1:48 p.m. UTC
Hi Guix,

I noticed that IcedTea/OpenJDK does not actually generate a certificate
store at build time — the store at “$out/lib/security/cacerts” is
empty.  As a result, accessing websites via HTTPS fails.

I’m now attempting to write a package that provides such a keystore by
automatically importing all certificates from the nss-certs package.
This appears to work as far as I can tell from experiments in the REPL,
but I’ve run into a problem preventing me from actually building the
package.

As soon as I add

     #:use-module (gnu packages certs)

to the module definition of “(gnu packages java)” Guix complains with
errors that are usually indicative of a module loop.  Attached is a
patch to master.

Here are the errors I get when trying to build the package:

~~~~~~~~~~~~~~~~~~~~~~~
./pre-inst-env guix build java-nss-certs-keystore
guix build: warning: failed to load '(gnu packages abiword)':
ERROR: In procedure module-lookup: Unbound variable: nss
guix build: warning: failed to load '(gnu packages avr)':
ERROR: In procedure module-lookup: Unbound variable: gnu-make
guix build: warning: failed to load '(gnu packages bioinformatics)':
ERROR: In procedure module-lookup: Unbound variable: perl-libwww
guix build: warning: failed to load '(gnu packages make-bootstrap)':
ERROR: no binding `%final-inputs' in module (gnu packages commencement)
guix build: warning: failed to load '(gnu packages mate)':
ERROR: In procedure module-lookup: Unbound variable: gtk+
guix build: warning: failed to load '(gnu packages unrtf)':
ERROR: In procedure module-lookup: Unbound variable: coreutils
guix build: error: java-nss-certs-keystore: unknown package
~~~~~~~~~~~~~~~~~~~~~~~

Do you have an idea what’s going on here?  “(gnu packages certs)” is not
used by any other module.

~~ Ricardo

Comments

Ricardo Wurmus June 16, 2016, 7:12 a.m. UTC | #1
Ricardo Wurmus <ricardo.wurmus@mdc-berlin.de> writes:

> I noticed that IcedTea/OpenJDK does not actually generate a certificate
> store at build time — the store at “$out/lib/security/cacerts” is
> empty.  As a result, accessing websites via HTTPS fails.

With some modifications to the patch (and by moving it from java.scm to
certs.scm) I managed to build a keystore from nss-certs.  I confirmed
that it works by starting a Java application with these additional
options:

    -Djavax.net.debug=ssl
    -Djavax.net.ssl.trustStore=/gnu/store/62j3i7666wa3hwrlsgzjnx766fs4j06g-java-nss-certs-keystore-3.23/lib/security/cacerts

(Unfortunately, it is not deterministic yet.)

To make this available without the trustStore option I would need to
convert my package into a build phase for the icedtea packages.
However, I cannot do this as using the “certs” module in the “java”
module breaks Guix.

> As soon as I add
>
>      #:use-module (gnu packages certs)
>
> to the module definition of “(gnu packages java)” Guix complains with
> errors that are usually indicative of a module loop.  Attached is a
> patch to master.
>
> Here are the errors I get when trying to build the package:
>
> ~~~~~~~~~~~~~~~~~~~~~~~
> ./pre-inst-env guix build java-nss-certs-keystore
> guix build: warning: failed to load '(gnu packages abiword)':
> ERROR: In procedure module-lookup: Unbound variable: nss
> guix build: warning: failed to load '(gnu packages avr)':
> ERROR: In procedure module-lookup: Unbound variable: gnu-make
> guix build: warning: failed to load '(gnu packages bioinformatics)':
> ERROR: In procedure module-lookup: Unbound variable: perl-libwww
> guix build: warning: failed to load '(gnu packages make-bootstrap)':
> ERROR: no binding `%final-inputs' in module (gnu packages commencement)
> guix build: warning: failed to load '(gnu packages mate)':
> ERROR: In procedure module-lookup: Unbound variable: gtk+
> guix build: warning: failed to load '(gnu packages unrtf)':
> ERROR: In procedure module-lookup: Unbound variable: coreutils
> guix build: error: java-nss-certs-keystore: unknown package
> ~~~~~~~~~~~~~~~~~~~~~~~

Any hints as to how I can debug this?

~~ Ricardo
diff mbox

Patch

From d59da0b155d7fc246811edaf0ee3673cdd705ce2 Mon Sep 17 00:00:00 2001
From: Ricardo Wurmus <rekado@elephly.net>
Date: Wed, 15 Jun 2016 09:23:00 +0200
Subject: [PATCH] WIP: java certs

---
 gnu/packages/java.scm | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index e165193..69cf43d 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -24,8 +24,10 @@ 
   #:use-module (guix download)
   #:use-module (guix utils)
   #:use-module (guix build-system ant)
+  #:use-module (guix build-system trivial)
   #:use-module (guix build-system gnu)
   #:use-module (gnu packages)
+  #:use-module (gnu packages certs)
   #:use-module (gnu packages attr)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages base)
@@ -47,6 +49,7 @@ 
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages mit-krb5)
+  #:use-module (gnu packages tls)
   #:use-module (gnu packages xml)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages zip)
@@ -840,6 +843,87 @@  build process and its dependencies, whereas Make uses Makefile format.")
 
 (define-public icedtea icedtea-7)
 
+(define-public java-nss-certs-keystore
+  (package
+    (name "java-nss-certs-keystore")
+    (version (package-version nss-certs))
+    (source #f)
+    (build-system trivial-build-system)
+    (arguments
+     `(#:modules ((guix build utils)
+                  (ice-9 rdelim)
+                  (ice-9 popen))
+       #:builder
+       (begin
+         (use-modules (guix build utils)
+                      (ice-9 rdelim)
+                      (ice-9 popen))
+         (let* ((target-dir (string-append %output "/lib/security/"))
+                (keystore   (string-append target-dir "cacerts"))
+                (certs-dir  (string-append
+                             (assoc-ref %build-inputs "nss-certs")
+                             "/etc/ssl/certs/"))
+                (now        (current-time)))
+
+           (define (valid? cert)
+             (let ((enddate (let* ((port (open-pipe* OPEN_READ
+                                                     "openssl"
+                                                     "x509" "-enddate"
+                                                     "-in" cert))
+                                   (str  (read-line port)))
+                              (close-pipe port)
+                              (string->date str "~b ~d ~H:~M:~S ~Y"))))
+               (time>? (date->time-utc enddate) now)))
+
+           (define (extract-cert file target)
+             (call-with-input-file file
+               (lambda (in)
+                 (call-with-output-file target
+                   (lambda (out)
+                     (let loop ((line (read-line in 'concat))
+                                (copying? #f))
+                       (cond
+                        ((eof-object? line) #t)
+                        ((string-prefix? "-----BEGIN" line)
+                         (display line out)
+                         (loop (read-line in 'concat) #t))
+                        ((string-prefix? "-----END" line)
+                         (display line out)
+                         #t)
+                        (else
+                         (when copying? (display line out))
+                         (loop (read-line in 'concat) copying?)))))))))
+
+           (define (import-cert cert)
+             (let ((tmp (tmpfile)))
+               (extract-cert cert tmp)
+               (let ((port (open-pipe* OPEN_WRITE
+                                       (which "keytool")
+                                       "-import"
+                                       "-alias" (basename cert)
+                                       "-keystore" keystore
+                                       "-storepass" "changeit"
+                                       "-file" tmp)))
+                 (display "yes\n" port)
+                 (when (not (eqv? 0 (status:exit-val (close-pipe port))))
+                   (error "Failed to import certificate.")))
+               (delete-file tmp)))
+
+           (mkdir-p target-dir)
+           (for-each import-cert
+                     (filter valid? (find-files certs-dir "\\.pem$")))
+           #t))))
+    (inputs
+     `(("nss-certs" ,nss-certs)))
+    (native-inputs
+     `(("jre" ,icedtea)
+       ("openssl" ,openssl)
+       ("coreutils" ,coreutils)))
+    (home-page "TODO")
+    (synopsis "TODO")
+    (description "TODO")
+    (license (package-license nss-certs))))
+
 (define-public java-xz
   (package
    (name "java-xz")
-- 
2.8.3