[PATCH] add pem-directory-hash extract format
Stef Walter
stefw at redhat.com
Wed Jan 14 04:41:25 PST 2015
Thanks. Merged to master.
I've credited Ludwig to the commit message, since Adam said the patch
came from him as well ... and also fixed a few compiler warnings.
Stef
On 14.01.2015 05:52, Adam Williamson wrote:
> 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"
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.freedesktop.org/archives/p11-glue/attachments/20150114/f4455f69/attachment.sig>
More information about the p11-glue
mailing list