This allows extraction of a directory of standard PEM files
with the OpenSSL hash symlinks; this is a format used by
some popular platforms (Debian's /etc/ssl/certs is in this
form, and OpenSUSE provides it for compatibility).
---
 doc/manual/trust.xml    |  6 +++-
 trust/extract-openssl.c | 76 ++++++++++++++++++++++++++-----------------------
 trust/extract-pem.c     | 46 +++++++++++++++++++++++++-----
 trust/extract.c         | 17 ++++++-----
 trust/extract.h         |  8 ++++++
 trust/test-bundle.c     | 35 +++++++++++++++++++++++
 6 files changed, 137 insertions(+), 51 deletions(-)

diff --git a/doc/manual/trust.xml b/doc/manual/trust.xml
index efb66c1..05f2726 100644
--- a/doc/manual/trust.xml
+++ b/doc/manual/trust.xml
@@ -270,7 +270,11 @@ $ trust extract --format=x509-directory 
--filter=ca-anchors /path/to/directory
                                </varlistentry>
                                <varlistentry>
                                        
<term><option>pem-directory</option></term>
-                                       <listitem><para>Directory PEM files 
each containing one certifiacte</para></listitem>
+                                       <listitem><para>Directory of PEM files 
each containing one certificate</para></listitem>
+                               </varlistentry>
+                               <varlistentry>
+                                       
<term><option>pem-directory-hash</option></term>
+                                       <listitem><para>Directory of PEM files 
each containing one certificate, with hash symlinks</para></listitem>
                                </varlistentry>
                                <varlistentry>
                                        
<term><option>openssl-bundle</option></term>
diff --git a/trust/extract-openssl.c b/trust/extract-openssl.c
index d622d7a..3271339 100644
--- a/trust/extract-openssl.c
+++ b/trust/extract-openssl.c
@@ -587,6 +587,45 @@ symlink_for_subject_old_hash (p11_enumerate *ex)
 
 #endif /* OS_UNIX */
 
+/*
+ * The OpenSSL style c_rehash stuff
+ *
+ * Different versions of openssl build these hashes differently
+ * so output both of them. Shouldn't cause confusion, because
+ * multiple certificates can hash to the same link anyway,
+ * and this is the reason for the trailing number after the dot.
+ *
+ * The trailing number is incremented p11_save_symlink_in() if it
+ * conflicts with something we've already written out.
+ *
+ * On Windows no symlinks.
+ */
+bool
+p11_openssl_symlink (p11_enumerate *ex,
+                     p11_save_dir *dir,
+                     const char *filename)
+{
+       bool ret = true;
+#ifdef OS_UNIX
+       char *linkname;
+
+       linkname = symlink_for_subject_hash (ex);
+       if (linkname) {
+               ret = p11_save_symlink_in (dir, linkname, ".0", filename);
+               free (linkname);
+       }
+
+       if (ret) {
+               linkname = symlink_for_subject_old_hash (ex);
+               if (linkname) {
+                       ret = p11_save_symlink_in (dir, linkname, ".0", 
filename);
+                       free (linkname);
+               }
+       }
+#endif /* OS_UNIX */
+       return ret;
+}
+
 bool
 p11_extract_openssl_directory (p11_enumerate *ex,
                                const char *destination)
@@ -601,10 +640,6 @@ p11_extract_openssl_directory (p11_enumerate *ex,
        char *name;
        CK_RV rv;
 
-#ifdef OS_UNIX
-       char *linkname;
-#endif
-
        dir = p11_save_open_directory (destination, ex->flags);
        if (dir == NULL)
                return false;
@@ -637,38 +672,7 @@ p11_extract_openssl_directory (p11_enumerate *ex,
                                if (ret)
                                        filename = p11_path_base (path);
                        }
-
-                       /*
-                        * The OpenSSL style c_rehash stuff
-                        *
-                        * Different versions of openssl build these hashes 
differently
-                        * so output both of them. Shouldn't cause confusion, 
because
-                        * multiple certificates can hash to the same link 
anyway,
-                        * and this is the reason for the trailing number after 
the dot.
-                        *
-                        * The trailing number is incremented 
p11_save_symlink_in() if it
-                        * conflicts with something we've already written out.
-                        *
-                        * On Windows no symlinks.
-                        */
-
-#ifdef OS_UNIX
-                       if (ret) {
-                               linkname = symlink_for_subject_hash (ex);
-                               if (linkname) {
-                                       ret = p11_save_symlink_in (dir, 
linkname, ".0", filename);
-                                       free (linkname);
-                               }
-                       }
-
-                       if (ret) {
-                               linkname = symlink_for_subject_old_hash (ex);
-                               if (linkname) {
-                                       ret = p11_save_symlink_in (dir, 
linkname, ".0", filename);
-                                       free (linkname);
-                               }
-                       }
-#endif /* OS_UNIX */
+                       ret = p11_openssl_symlink(ex, dir, filename);
 
                        free (filename);
                        free (path);
diff --git a/trust/extract-pem.c b/trust/extract-pem.c
index 1e1c857..6d8c662 100644
--- a/trust/extract-pem.c
+++ b/trust/extract-pem.c
@@ -99,14 +99,17 @@ p11_extract_pem_bundle (p11_enumerate *ex,
 }
 
 bool
-p11_extract_pem_directory (p11_enumerate *ex,
-                           const char *destination)
+_p11_extract_pem_directory (p11_enumerate *ex,
+                           const char *destination,
+                           bool hash)
 {
        p11_save_file *file;
        p11_save_dir *dir;
        p11_buffer buf;
        bool ret = true;
        char *filename;
+       char *path;
+       char *name;
        CK_RV rv;
 
        dir = p11_save_open_directory (destination, ex->flags);
@@ -121,14 +124,25 @@ p11_extract_pem_directory (p11_enumerate *ex,
                if (!p11_pem_write (ex->cert_der, ex->cert_len, "CERTIFICATE", 
&buf))
                        return_val_if_reached (false);
 
-               filename = p11_enumerate_filename (ex);
-               return_val_if_fail (filename != NULL, false);
+               name = p11_enumerate_filename (ex);
+               return_val_if_fail (name != NULL, false);
+
+               path = NULL;
 
-               file = p11_save_open_file_in (dir, filename, ".pem");
-               free (filename);
+               file = p11_save_open_file_in (dir, name, ".pem");
+               ret = p11_save_write (file, buf.data, buf.len);
 
-               ret = p11_save_write_and_finish (file, buf.data, buf.len);
+               if (!p11_save_finish_file (file, &path, ret))
+                       ret = false;
 
+               if (ret && hash) {
+                       filename = p11_path_base (path);
+                       ret = p11_openssl_symlink(ex, dir, filename);
+                       free (filename);
+               }
+
+               free (path);
+               free (name);
                if (!ret)
                        break;
        }
@@ -143,3 +157,21 @@ p11_extract_pem_directory (p11_enumerate *ex,
        p11_save_finish_directory (dir, ret);
        return ret;
 }
+
+bool
+p11_extract_pem_directory (p11_enumerate *ex,
+                           const char *destination)
+{
+       bool ret = true;
+       ret = _p11_extract_pem_directory (ex, destination, false);
+       return ret;
+}
+
+bool
+p11_extract_pem_directory_hash (p11_enumerate *ex,
+                           const char *destination)
+{
+       bool ret = true;
+       ret = _p11_extract_pem_directory (ex, destination, true);
+       return ret;
+}
diff --git a/trust/extract.c b/trust/extract.c
index a008270..80b5e72 100644
--- a/trust/extract.c
+++ b/trust/extract.c
@@ -44,6 +44,7 @@
 #include "pkcs11x.h"
 #include "save.h"
 #include "tool.h"
+#include "digest.h"
 
 #include "p11-kit/iter.h"
 #include "p11-kit/pkcs11.h"
@@ -77,6 +78,7 @@ format_argument (const char *optarg,
                { "x509-directory", p11_extract_x509_directory, },
                { "pem-bundle", p11_extract_pem_bundle, },
                { "pem-directory", p11_extract_pem_directory },
+               { "pem-directory-hash", p11_extract_pem_directory_hash },
                { "java-cacerts", p11_extract_jks_cacerts },
                { "openssl-bundle", p11_extract_openssl_bundle },
                { "openssl-directory", p11_extract_openssl_directory },
@@ -198,13 +200,14 @@ p11_trust_extract (int argc,
                },
                { opt_format,
                  "format to extract to\n"
-                 "  x509-file         DER X.509 certificate file\n"
-                 "  x509-directory    directory of X.509 certificates\n"
-                 "  pem-bundle        file containing multiple PEM blocks\n"
-                 "  pem-directory     directory of PEM files\n"
-                 "  openssl-bundle    OpenSSL specific PEM bundle\n"
-                 "  openssl-directory directory of OpenSSL specific files\n"
-                 "  java-cacerts      java keystore cacerts file",
+                 "  x509-file           DER X.509 certificate file\n"
+                 "  x509-directory      directory of X.509 certificates\n"
+                 "  pem-bundle          file containing multiple PEM blocks\n"
+                 "  pem-directory       directory of PEM files\n"
+                 "  pem-directory-hash  directory of PEM files with hash 
links\n"
+                 "  openssl-bundle      OpenSSL specific PEM bundle\n"
+                 "  openssl-directory   directory of OpenSSL specific files\n"
+                 "  java-cacerts        java keystore cacerts file",
                  "type"
                },
                { opt_purpose,
diff --git a/trust/extract.h b/trust/extract.h
index ca14238..2664ba0 100644
--- a/trust/extract.h
+++ b/trust/extract.h
@@ -39,6 +39,7 @@
 
 #include "enumerate.h"
 #include "pkcs11.h"
+#include "save.h"
 
 enum {
        /* These overlap with the flags in save.h, so start higher */
@@ -60,6 +61,9 @@ bool            p11_extract_pem_bundle         (p11_enumerate 
*ex,
 bool            p11_extract_pem_directory      (p11_enumerate *ex,
                                                 const char *destination);
 
+bool            p11_extract_pem_directory_hash (p11_enumerate *ex,
+                                                const char *destination);
+
 bool            p11_extract_jks_cacerts        (p11_enumerate *ex,
                                                 const char *destination);
 
@@ -75,4 +79,8 @@ int             p11_trust_extract              (int argc,
 int             p11_trust_extract_compat       (int argc,
                                                 char *argv[]);
 
+/* from extract-openssl.c but also used in extract-pem.c */
+bool            p11_openssl_symlink            (p11_enumerate *ex,
+                                                p11_save_dir *dir,
+                                                const char *filename);
 #endif /* P11_EXTRACT_H_ */
diff --git a/trust/test-bundle.c b/trust/test-bundle.c
index a12d8a1..3af7277 100644
--- a/trust/test-bundle.c
+++ b/trust/test-bundle.c
@@ -217,6 +217,39 @@ test_directory_empty (void)
        test_check_directory (test.directory, (NULL, NULL));
 }
 
+static void
+test_directory_hash (void)
+{
+       bool ret;
+
+       mock_module_add_object (MOCK_SLOT_ONE_ID, cacert3_authority_attrs);
+       mock_module_add_object (MOCK_SLOT_ONE_ID, cacert3_authority_attrs);
+
+       p11_kit_iter_add_filter (test.ex.iter, certificate_filter, 1);
+       p11_kit_iter_begin_with (test.ex.iter, &test.module, 0, 0);
+
+       /* Yes, this is a race, and why you shouldn't build software as root */
+       if (rmdir (test.directory) < 0)
+               assert_not_reached ();
+
+       ret = p11_extract_pem_directory_hash (&test.ex, test.directory);
+       assert_num_eq (true, ret);
+
+       test_check_directory (test.directory, ("Cacert3_Here.pem", 
"Cacert3_Here.1.pem",
+#ifdef OS_UNIX
+                                           "e5662767.1", "e5662767.0", 
"590d426f.1", "590d426f.0",
+#endif
+                                           NULL));
+       test_check_file (test.directory, "Cacert3_Here.pem", SRCDIR 
"/trust/fixtures/cacert3.pem");
+       test_check_file (test.directory, "Cacert3_Here.1.pem", SRCDIR 
"/trust/fixtures/cacert3.pem");
+#ifdef OS_UNIX
+       test_check_symlink (test.directory, "e5662767.0", "Cacert3_Here.pem");
+       test_check_symlink (test.directory, "e5662767.1", "Cacert3_Here.1.pem");
+       test_check_symlink (test.directory, "590d426f.0", "Cacert3_Here.pem");
+       test_check_symlink (test.directory, "590d426f.1", "Cacert3_Here.1.pem");
+#endif
+}
+
 int
 main (int argc,
       char *argv[])
@@ -229,9 +262,11 @@ main (int argc,
        p11_test (test_file_without, "/pem/test_file_without");
        p11_test (test_directory, "/pem/test_directory");
        p11_test (test_directory_empty, "/pem/test_directory_empty");
+       p11_test (test_directory_hash, "/pem/test_directory_hash");
        return p11_test_run (argc, argv);
 }
 
 #include "enumerate.c"
 #include "extract-pem.c"
+#include "extract-openssl.c"
 #include "save.c"
-- 
2.2.1

_______________________________________________
p11-glue mailing list
p11-glue@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/p11-glue

Reply via email to