diff options
Diffstat (limited to 'tools/extract-info.c')
-rw-r--r-- | tools/extract-info.c | 455 |
1 files changed, 0 insertions, 455 deletions
diff --git a/tools/extract-info.c b/tools/extract-info.c deleted file mode 100644 index 133b1cd..0000000 --- a/tools/extract-info.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (c) 2013, Red Hat Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * Author: Stef Walter <stefw@redhat.com> - */ - -#include "config.h" - -#define P11_DEBUG_FLAG P11_DEBUG_TOOL - -#include "attrs.h" -#include "debug.h" -#include "oid.h" -#include "dict.h" -#include "extract.h" -#include "message.h" -#include "pkcs11.h" -#include "pkcs11x.h" -#include "x509.h" - -#include <stdlib.h> -#include <string.h> - -static p11_dict * -load_stapled_extensions (CK_FUNCTION_LIST_PTR module, - CK_SLOT_ID slot_id, - CK_ATTRIBUTE *id) -{ - CK_OBJECT_CLASS extension = CKO_X_CERTIFICATE_EXTENSION; - CK_ATTRIBUTE *attrs; - P11KitIter *iter; - CK_RV rv = CKR_OK; - p11_dict *stapled; - - CK_ATTRIBUTE match[] = { - { CKA_CLASS, &extension, sizeof (extension) }, - { CKA_ID, id->pValue, id->ulValueLen }, - }; - - CK_ATTRIBUTE template[] = { - { CKA_OBJECT_ID, }, - { CKA_X_CRITICAL, }, - { CKA_VALUE, }, - }; - - stapled = p11_dict_new (p11_attr_hash, - (p11_dict_equals)p11_attr_equal, - NULL, p11_attrs_free); - - /* No ID to use, just short circuit */ - if (!id->pValue || !id->ulValueLen) - return stapled; - - iter = p11_kit_iter_new (NULL); - p11_kit_iter_add_filter (iter, match, 2); - p11_kit_iter_begin_with (iter, module, slot_id, 0); - - while (rv == CKR_OK) { - rv = p11_kit_iter_next (iter); - if (rv == CKR_OK) { - attrs = p11_attrs_buildn (NULL, template, 3); - rv = p11_kit_iter_load_attributes (iter, attrs, 3); - if (rv == CKR_OK || rv == CKR_ATTRIBUTE_TYPE_INVALID) { - /* CKA_OBJECT_ID is the first attribute, use it as the key */ - if (!p11_dict_set (stapled, attrs, attrs)) - return_val_if_reached (NULL); - rv = CKR_OK; - } else { - p11_attrs_free (attrs); - } - } - } - - if (rv != CKR_OK && rv != CKR_CANCEL) { - p11_message ("couldn't load stapled extensions for certificate: %s", p11_kit_strerror (rv)); - p11_dict_free (stapled); - stapled = NULL; - } - - p11_kit_iter_free (iter); - return stapled; -} - -static bool -extract_purposes (p11_extract_info *ex) -{ - CK_ATTRIBUTE oid = { CKA_OBJECT_ID, - (void *)P11_OID_EXTENDED_KEY_USAGE, - sizeof (P11_OID_EXTENDED_KEY_USAGE) }; - const unsigned char *ext = NULL; - unsigned char *alloc = NULL; - CK_ATTRIBUTE *attrs; - size_t ext_len; - - if (ex->stapled) { - attrs = p11_dict_get (ex->stapled, &oid); - if (attrs != NULL) - ext = p11_attrs_find_value (attrs, CKA_VALUE, &ext_len); - } - - if (ext == NULL && ex->cert_asn) { - alloc = p11_x509_find_extension (ex->cert_asn, P11_OID_EXTENDED_KEY_USAGE, - ex->cert_der, ex->cert_len, &ext_len); - ext = alloc; - } - - /* No such extension, match anything */ - if (ext == NULL) - return true; - - ex->purposes = p11_x509_parse_extended_key_usage (ex->asn1_defs, ext, ext_len); - - free (alloc); - return ex->purposes != NULL; -} - -static bool -should_collapse_certificate (p11_extract_info *ex, - CK_ATTRIBUTE *value) -{ - CK_ATTRIBUTE *attrs; - - if (!(ex->flags & P11_EXTRACT_COLLAPSE)) - return false; - - if (!ex->already_seen) { - ex->already_seen = p11_dict_new (p11_attr_hash, p11_attr_equal, - NULL, p11_attrs_free); - return_val_if_fail (ex->already_seen != NULL, true); - } - - if (p11_dict_get (ex->already_seen, value)) - return true; - - attrs = p11_attrs_build (NULL, value, NULL); - return_val_if_fail (attrs != NULL, true); - - if (!p11_dict_set (ex->already_seen, attrs, attrs)) - return_val_if_reached (true); - - return false; -} - -static bool -check_trust_flags_match (p11_extract_info *ex) -{ - CK_BBOOL boolv; - int flags = 0; - - /* If no extract trust flags, then just continue */ - if (!(ex->flags & (P11_EXTRACT_ANCHORS | P11_EXTRACT_BLACKLIST))) - return true; - - if (p11_attrs_find_bool (ex->attrs, CKA_TRUSTED, &boolv) && boolv) - flags |= P11_EXTRACT_ANCHORS; - if (p11_attrs_find_bool (ex->attrs, CKA_X_DISTRUSTED, &boolv) && boolv) - flags |= P11_EXTRACT_BLACKLIST; - - /* Any of the flags can match */ - if (flags & ex->flags) - return true; - - return false; -} - -static bool -extract_certificate (P11KitIter *iter, - p11_extract_info *ex) -{ - char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; - CK_ATTRIBUTE *attr; - - CK_ULONG type; - - /* Don't even bother with not X.509 certificates */ - if (!p11_attrs_find_ulong (ex->attrs, CKA_CERTIFICATE_TYPE, &type)) - type = (CK_ULONG)-1; - if (type != CKC_X_509) { - p11_debug ("skipping non X.509 certificate"); - return false; - } - - attr = p11_attrs_find_valid (ex->attrs, CKA_VALUE); - if (!attr || !attr->pValue) { - p11_debug ("skipping certificate without a value"); - return false; - } - - /* - * If collapsing and have already seen this certificate, and shouldn't - * process it even again during this extract procedure. - */ - if (should_collapse_certificate (ex, attr)) { - p11_debug ("skipping certificate that has already been seen"); - return false; - } - - /* - * We do these checks after collapsing, so that blacklisted certificates - * mask out anchors even if we're not exporting blacklisted stuff. - */ - if (!check_trust_flags_match (ex)) { - p11_debug ("skipping certificate that doesn't match trust flags"); - return false; - } - - ex->cert_der = attr->pValue; - ex->cert_len = attr->ulValueLen; - ex->cert_asn = p11_asn1_decode (ex->asn1_defs, "PKIX1.Certificate", - ex->cert_der, ex->cert_len, message); - - if (!ex->cert_asn) { - p11_message ("couldn't parse certificate: %s", message); - return false; - } - - return true; -} - -static bool -extract_info (P11KitIter *iter, - p11_extract_info *ex) -{ - CK_ATTRIBUTE *attr; - CK_RV rv; - - static CK_ATTRIBUTE attr_types[] = { - { CKA_ID, }, - { CKA_CLASS, }, - { CKA_CERTIFICATE_TYPE, }, - { CKA_LABEL, }, - { CKA_VALUE, }, - { CKA_SUBJECT, }, - { CKA_ISSUER, }, - { CKA_TRUSTED, }, - { CKA_CERTIFICATE_CATEGORY }, - { CKA_X_DISTRUSTED }, - { CKA_INVALID, }, - }; - - ex->attrs = p11_attrs_dup (attr_types); - rv = p11_kit_iter_load_attributes (iter, ex->attrs, p11_attrs_count (ex->attrs)); - - /* The attributes couldn't be loaded */ - if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID && rv != CKR_ATTRIBUTE_SENSITIVE) { - p11_message ("couldn't load attributes: %s", p11_kit_strerror (rv)); - return false; - } - - /* No class attribute, very strange, just skip */ - if (!p11_attrs_find_ulong (ex->attrs, CKA_CLASS, &ex->klass)) - return false; - - /* If a certificate then */ - if (ex->klass != CKO_CERTIFICATE) { - p11_message ("skipping non-certificate object"); - return false; - } - - if (!extract_certificate (iter, ex)) - return false; - - attr = p11_attrs_find_valid (ex->attrs, CKA_ID); - if (attr) { - ex->stapled = load_stapled_extensions (p11_kit_iter_get_module (iter), - p11_kit_iter_get_slot (iter), - attr); - if (!ex->stapled) - return false; - } - - if (!extract_purposes (ex)) - return false; - - return true; -} - -static void -extract_clear (p11_extract_info *ex) -{ - ex->klass = (CK_ULONG)-1; - - p11_attrs_free (ex->attrs); - ex->attrs = NULL; - - asn1_delete_structure (&ex->cert_asn); - ex->cert_der = NULL; - ex->cert_len = 0; - - p11_dict_free (ex->stapled); - ex->stapled = NULL; - - p11_array_free (ex->purposes); - ex->purposes = NULL; -} - -CK_RV -p11_extract_info_load_filter (P11KitIter *iter, - CK_BBOOL *matches, - void *data) -{ - p11_extract_info *ex = data; - int i; - - extract_clear (ex); - - /* Try to load the certificate and extensions */ - if (!extract_info (iter, ex)) { - *matches = CK_FALSE; - return CKR_OK; - } - - /* - * Limit to certain purposes. Note that the lack of purposes noted - * on the certificate means they match any purpose. This is the - * behavior of the ExtendedKeyUsage extension. - */ - if (ex->limit_to_purposes && ex->purposes) { - *matches = CK_FALSE; - for (i = 0; i < ex->purposes->num; i++) { - if (p11_dict_get (ex->limit_to_purposes, ex->purposes->elem[i])) { - *matches = CK_TRUE; - break; - } - } - } - - return CKR_OK; -} - -void -p11_extract_info_init (p11_extract_info *ex) -{ - memset (ex, 0, sizeof (p11_extract_info)); - ex->asn1_defs = p11_asn1_defs_load (); - return_if_fail (ex->asn1_defs != NULL); -} - -void -p11_extract_info_cleanup (p11_extract_info *ex) -{ - extract_clear (ex); - - p11_dict_free (ex->limit_to_purposes); - ex->limit_to_purposes = NULL; - - p11_dict_free (ex->already_seen); - ex->already_seen = NULL; - - p11_dict_free (ex->asn1_defs); - ex->asn1_defs = NULL; -} - -void -p11_extract_info_limit_purpose (p11_extract_info *ex, - const char *purpose) -{ - char *value; - - if (!ex->limit_to_purposes) { - ex->limit_to_purposes = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL); - return_if_fail (ex->limit_to_purposes != NULL); - } - - value = strdup (purpose); - return_if_fail (value != NULL); - - if (!p11_dict_set (ex->limit_to_purposes, value, value)) - return_if_reached (); -} - -static char * -extract_label (p11_extract_info *extract) -{ - CK_ATTRIBUTE *attr; - - /* Look for a label and just use that */ - attr = p11_attrs_find_valid (extract->attrs, CKA_LABEL); - if (attr && attr->pValue && attr->ulValueLen) - return strndup (attr->pValue, attr->ulValueLen); - - /* For extracting certificates */ - if (extract->klass == CKO_CERTIFICATE) - return strdup ("certificate"); - - return strdup ("unknown"); -} - -#define FILENAME_CHARS \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_" - -char * -p11_extract_info_filename (p11_extract_info *extract) -{ - char *label; - int i; - - label = extract_label (extract); - return_val_if_fail (label != NULL, NULL); - - for (i = 0; label[i] != '\0'; i++) { - if (strchr (FILENAME_CHARS, label[i]) == NULL) - label[i] = '_'; - } - - return label; -} - -char * -p11_extract_info_comment (p11_extract_info *ex, - bool first) -{ - char *comment; - char *label; - - if (!(ex->flags & P11_EXTRACT_COMMENT)) - return NULL; - - label = extract_label (ex); - if (!asprintf (&comment, "%s# %s\n", - first ? "" : "\n", - label ? label : "")) - return_val_if_reached (NULL); - - free (label); - return comment; -} |