[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