summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Williamson <awilliam@redhat.com>2015-01-13 20:52:20 -0800
committerStef Walter <stefw@redhat.com>2015-01-14 13:36:47 +0100
commita6df1f21e42a3b57448eb6897b976ac8883908eb (patch)
tree78d0379a31c7370907086535c4fe1cc2159991ff
parentb65e3148a8ea2d54b17a8be617bbdcb026c49fcd (diff)
downloadp11-kit-a6df1f21e42a3b57448eb6897b976ac8883908eb.tar.gz
trust: Add pem-directory-hash extract format
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
-rw-r--r--doc/manual/trust.xml6
-rw-r--r--trust/extract-openssl.c76
-rw-r--r--trust/extract-pem.c49
-rw-r--r--trust/extract.c17
-rw-r--r--trust/extract.h8
-rw-r--r--trust/test-bundle.c35
6 files changed, 139 insertions, 52 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..a32d032 100644
--- a/trust/extract-pem.c
+++ b/trust/extract-pem.c
@@ -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;
+}
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"