]> granicus.if.org Git - p11-kit/commitdiff
trust: Add pem-directory-hash extract format
authorAdam Williamson <awilliam@redhat.com>
Wed, 14 Jan 2015 04:52:20 +0000 (20:52 -0800)
committerStef Walter <stefw@redhat.com>
Wed, 14 Jan 2015 12:36:47 +0000 (13:36 +0100)
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).

Initially by: Ludwig Nussel <ludwig.nussel@suse.de>

Signed-off-by: Stef Walter <stefw@redhat.com>
 * Added header, fixed compiler warnings

doc/manual/trust.xml
trust/extract-openssl.c
trust/extract-pem.c
trust/extract.c
trust/extract.h
trust/test-bundle.c

index efb66c16e389805d7e15a257daaa3162c73ed3a3..05f27268837f762ae96d08e3fe2fe793d8d6387d 100644 (file)
@@ -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>
index d622d7ad798ffb10bd76c1c7aeca9d54347b2b71..327133910efea6931779a9a89329782ce4562f92 100644 (file)
@@ -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);
index 1e1c8572670655fc441dab8c2ddcd3a19f8c6654..a32d0329f5a5f8541073149c60a3aee08749d202 100644 (file)
@@ -40,6 +40,7 @@
 #include "debug.h"
 #include "extract.h"
 #include "message.h"
+#include "path.h"
 #include "pem.h"
 #include "save.h"
 
@@ -98,15 +99,18 @@ p11_extract_pem_bundle (p11_enumerate *ex,
        return ret;
 }
 
-bool
-p11_extract_pem_directory (p11_enumerate *ex,
-                           const char *destination)
+static bool
+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 +125,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, name, ".pem");
+               ret = p11_save_write (file, buf.data, buf.len);
 
-               file = p11_save_open_file_in (dir, filename, ".pem");
-               free (filename);
+               if (!p11_save_finish_file (file, &path, ret))
+                       ret = false;
 
-               ret = p11_save_write_and_finish (file, buf.data, buf.len);
+               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 +158,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 = extract_pem_directory (ex, destination, false);
+       return ret;
+}
+
+bool
+p11_extract_pem_directory_hash (p11_enumerate *ex,
+                           const char *destination)
+{
+       bool ret = true;
+       ret = extract_pem_directory (ex, destination, true);
+       return ret;
+}
index a0082703fb766d447d4143adad93641d2043dfb9..80b5e7238802e099db002429a41a52f9c12ac5b2 100644 (file)
@@ -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,
index ca14238dc6a32260ad1b02745c0a21da5795816f..2664ba0e556dbf726fd2469b02a648b625e4e83a 100644 (file)
@@ -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_ */
index a12d8a116e16a88bf82a1857b1c23faa4f747b62..3af7277c6a6a4c18d7e865e9626cf9a47b56139b 100644 (file)
@@ -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"