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