summaryrefslogtreecommitdiff
path: root/trust
diff options
context:
space:
mode:
Diffstat (limited to 'trust')
-rw-r--r--trust/builder.c3
-rw-r--r--trust/extract-info.c86
-rw-r--r--trust/index.c18
-rw-r--r--trust/index.h6
-rw-r--r--trust/module.c5
-rw-r--r--trust/parser.c124
-rw-r--r--trust/parser.h7
-rw-r--r--trust/tests/test-extract.c28
-rw-r--r--trust/tests/test-parser.c184
-rw-r--r--trust/tests/test-token.c255
-rw-r--r--trust/tests/test-trust.c75
-rw-r--r--trust/tests/test-trust.h28
-rw-r--r--trust/token.c331
-rw-r--r--trust/token.h3
14 files changed, 746 insertions, 407 deletions
diff --git a/trust/builder.c b/trust/builder.c
index bfbc42d..f325be6 100644
--- a/trust/builder.c
+++ b/trust/builder.c
@@ -322,7 +322,8 @@ type_der_cert (p11_builder *builder,
{ CKA_MODIFIABLE, CREATE | WANT, type_bool }, \
{ CKA_PRIVATE, CREATE, type_bool }, \
{ CKA_LABEL, CREATE | MODIFY | WANT, type_utf8 }, \
- { CKA_X_GENERATED, CREATE }
+ { CKA_X_GENERATED, CREATE }, \
+ { CKA_X_ORIGIN, NONE } \
static CK_ATTRIBUTE *
common_populate (p11_builder *builder,
diff --git a/trust/extract-info.c b/trust/extract-info.c
index a645d31..ec25bc1 100644
--- a/trust/extract-info.c
+++ b/trust/extract-info.c
@@ -143,46 +143,66 @@ extract_purposes (p11_extract_info *ex)
}
static bool
-should_collapse_certificate (p11_extract_info *ex,
- CK_ATTRIBUTE *value)
+check_blacklisted (P11KitIter *iter,
+ CK_ATTRIBUTE *cert)
{
- CK_ATTRIBUTE *attrs;
+ CK_OBJECT_HANDLE dummy;
+ CK_FUNCTION_LIST *module;
+ CK_SESSION_HANDLE session;
+ CK_BBOOL distrusted = CK_TRUE;
+ CK_ULONG have;
+ CK_RV rv;
- if (!(ex->flags & P11_EXTRACT_COLLAPSE))
- return false;
+ CK_ATTRIBUTE match[] = {
+ { CKA_VALUE, cert->pValue, cert->ulValueLen },
+ { CKA_X_DISTRUSTED, &distrusted, sizeof (distrusted) },
+ };
+
+ module = p11_kit_iter_get_module (iter);
+ session = p11_kit_iter_get_session (iter);
- 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);
+ rv = (module->C_FindObjectsInit) (session, match, 2);
+ if (rv == CKR_OK) {
+ rv = (module->C_FindObjects) (session, &dummy, 1, &have);
+ (module->C_FindObjectsFinal) (session);
}
- if (p11_dict_get (ex->already_seen, value))
+ if (rv != CKR_OK) {
+ p11_message ("couldn't check if certificate is on blacklist");
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;
+ if (have == 0) {
+ p11_debug ("anchor is not on blacklist");
+ return false;
+ } else {
+ p11_debug ("anchor is on blacklist");
+ return true;
+ }
}
static bool
-check_trust_flags_match (p11_extract_info *ex)
+check_trust_flags (P11KitIter *iter,
+ p11_extract_info *ex,
+ CK_ATTRIBUTE *cert)
{
- CK_BBOOL boolv;
+ CK_BBOOL trusted;
+ CK_BBOOL distrusted;
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)
+ if (p11_attrs_find_bool (ex->attrs, CKA_TRUSTED, &trusted) &&
+ trusted && !check_blacklisted (iter, cert)) {
flags |= P11_EXTRACT_ANCHORS;
- if (p11_attrs_find_bool (ex->attrs, CKA_X_DISTRUSTED, &boolv) && boolv)
+ }
+
+ if (p11_attrs_find_bool (ex->attrs, CKA_X_DISTRUSTED, &distrusted) &&
+ distrusted) {
flags |= P11_EXTRACT_BLACKLIST;
+ }
/* Any of the flags can match */
if (flags & ex->flags)
@@ -218,20 +238,28 @@ extract_certificate (P11KitIter *iter,
* 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;
+ if (ex->flags & P11_EXTRACT_COLLAPSE) {
+ if (!ex->already_seen) {
+ ex->already_seen = p11_dict_new (p11_attr_hash, p11_attr_equal,
+ p11_attrs_free, NULL);
+ return_val_if_fail (ex->already_seen != NULL, true);
+ }
+
+ if (p11_dict_get (ex->already_seen, attr))
+ 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)) {
+ if (!check_trust_flags (iter, ex, attr)) {
p11_debug ("skipping certificate that doesn't match trust flags");
return false;
}
+ if (ex->already_seen) {
+ if (!p11_dict_set (ex->already_seen,
+ p11_attrs_build (NULL, attr, NULL), "x"))
+ return_val_if_reached (true);
+ }
+
ex->cert_der = attr->pValue;
ex->cert_len = attr->ulValueLen;
ex->cert_asn = p11_asn1_decode (ex->asn1_defs, "PKIX1.Certificate",
diff --git a/trust/index.c b/trust/index.c
index c8632cc..4de65c9 100644
--- a/trust/index.c
+++ b/trust/index.c
@@ -154,6 +154,7 @@ is_indexable (p11_index *index,
case CKA_VALUE:
case CKA_OBJECT_ID:
case CKA_ID:
+ case CKA_X_ORIGIN:
return true;
}
@@ -566,13 +567,18 @@ p11_index_replace_all (p11_index *index,
handles = p11_index_find_all (index, match, -1);
rv = index_replacev (index, handles, key,
- (CK_ATTRIBUTE **)replace->elem,
- replace->num);
+ replace ? (CK_ATTRIBUTE **)replace->elem : NULL,
+ replace ? replace->num : 0);
- for (i = 0; i < replace->num; i++) {
- if (!replace->elem[i]) {
- p11_array_remove (replace, i);
- i--;
+ if (rv == CKR_OK) {
+ if (replace)
+ p11_array_clear (replace);
+ } else {
+ for (i = 0; replace && i < replace->num; i++) {
+ if (!replace->elem[i]) {
+ p11_array_remove (replace, i);
+ i--;
+ }
}
}
diff --git a/trust/index.h b/trust/index.h
index a221178..2f44d0c 100644
--- a/trust/index.h
+++ b/trust/index.h
@@ -38,6 +38,7 @@
#include "array.h"
#include "compat.h"
#include "pkcs11.h"
+#include "pkcs11x.h"
/*
* A boolean value which denotes whether we auto generated
@@ -48,6 +49,11 @@
*/
#define CKA_X_GENERATED (CKA_X_VENDOR + 8000)
+/*
+ * A string pointing to the filename from which this was loaded.
+ */
+#define CKA_X_ORIGIN (CKA_X_VENDOR + 8001)
+
typedef struct _p11_index p11_index;
typedef CK_RV (* p11_index_build_cb) (void *data,
diff --git a/trust/module.c b/trust/module.c
index 5f8692b..22e288c 100644
--- a/trust/module.c
+++ b/trust/module.c
@@ -1110,8 +1110,11 @@ sys_C_SetAttributeValue (CK_SESSION_HANDLE handle,
if (rv == CKR_OK)
rv = check_index_writable (session, index);
- if (rv == CKR_OK)
+ if (rv == CKR_OK) {
+ if (index == p11_token_index (session->token))
+ p11_token_reload (session->token, attrs);
rv = p11_index_set (index, object, template, count);
+ }
}
p11_unlock ();
diff --git a/trust/parser.c b/trust/parser.c
index 21b693b..c5cbe15 100644
--- a/trust/parser.c
+++ b/trust/parser.c
@@ -64,11 +64,11 @@
#include <unistd.h>
struct _p11_parser {
- p11_index *index;
p11_asn1_cache *asn1_cache;
p11_dict *asn1_defs;
p11_persist *persist;
char *basename;
+ p11_array *parsed;
int flags;
};
@@ -131,114 +131,20 @@ populate_trust (p11_parser *parser,
return p11_attrs_build (attrs, &trusted, &distrust, NULL);
}
-static bool
-lookup_cert_duplicate (p11_index *index,
- CK_ATTRIBUTE *attrs,
- CK_OBJECT_HANDLE *handle,
- CK_ATTRIBUTE **dupl)
-{
- CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
- CK_ATTRIBUTE *value;
-
- CK_ATTRIBUTE match[] = {
- { CKA_VALUE, },
- { CKA_CLASS, &klass, sizeof (klass) },
- { CKA_INVALID },
- };
-
- /*
- * TODO: This will need to be adapted when we support reload on
- * the fly, but for now since we only load once, we can assume
- * that any certs already present in the index are duplicates.
- */
-
- value = p11_attrs_find_valid (attrs, CKA_VALUE);
- if (value != NULL) {
- memcpy (match, value, sizeof (CK_ATTRIBUTE));
- *handle = p11_index_find (index, match, -1);
- if (*handle != 0) {
- *dupl = p11_index_lookup (index, *handle);
- return true;
- }
- }
-
- return false;
-}
-
-static char *
-pull_cert_label (CK_ATTRIBUTE *attrs)
-{
- char *label;
- size_t len;
-
- label = p11_attrs_find_value (attrs, CKA_LABEL, &len);
- if (label)
- label = strndup (label, len);
-
- return label;
-}
-
-static int
-calc_cert_priority (CK_ATTRIBUTE *attrs)
-{
- CK_BBOOL boolv;
-
- enum {
- PRI_UNKNOWN,
- PRI_TRUSTED,
- PRI_DISTRUST
- };
-
- if (p11_attrs_find_bool (attrs, CKA_X_DISTRUSTED, &boolv) && boolv)
- return PRI_DISTRUST;
- else if (p11_attrs_find_bool (attrs, CKA_TRUSTED, &boolv) && boolv)
- return PRI_TRUSTED;
-
- return PRI_UNKNOWN;
-}
-
static void
sink_object (p11_parser *parser,
CK_ATTRIBUTE *attrs)
{
- CK_OBJECT_HANDLE handle;
CK_OBJECT_CLASS klass;
- CK_ATTRIBUTE *dupl;
- char *label;
- CK_RV rv;
-
- /* By default not replacing anything */
- handle = 0;
if (p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
klass == CKO_CERTIFICATE) {
attrs = populate_trust (parser, attrs);
return_if_fail (attrs != NULL);
-
- if (lookup_cert_duplicate (parser->index, attrs, &handle, &dupl)) {
-
- /* This is not a good place to be for a well configured system */
- label = pull_cert_label (dupl);
- p11_message ("duplicate '%s' certificate found in: %s",
- label ? label : "?", parser->basename);
- free (label);
-
- /*
- * Nevertheless we provide predictable behavior about what
- * overrides what. If we have a lower or equal priority
- * to what's there, then just go away, otherwise replace.
- */
- if (calc_cert_priority (attrs) <= calc_cert_priority (dupl)) {
- p11_attrs_free (attrs);
- return;
- }
- }
}
- /* If handle is zero, this just adds */
- rv = p11_index_replace (parser->index, handle, attrs);
- if (rv != CKR_OK)
- p11_message ("couldn't load file into objects: %s", parser->basename);
+ if (!p11_array_push (parser->parsed, attrs))
+ return_if_reached ();
}
static CK_ATTRIBUTE *
@@ -636,8 +542,6 @@ on_pem_block (const char *type,
p11_parser *parser = user_data;
int ret;
- p11_index_batch (parser->index);
-
if (strcmp (type, "CERTIFICATE") == 0) {
ret = parse_der_x509_certificate (parser, contents, length);
@@ -649,8 +553,6 @@ on_pem_block (const char *type,
ret = P11_PARSE_SUCCESS;
}
- p11_index_finish (parser->index);
-
if (ret != P11_PARSE_SUCCESS)
p11_message ("Couldn't parse PEM block of type %s", type);
}
@@ -714,18 +616,18 @@ static parser_func all_parsers[] = {
};
p11_parser *
-p11_parser_new (p11_index *index,
- p11_asn1_cache *asn1_cache)
+p11_parser_new (p11_asn1_cache *asn1_cache)
{
p11_parser parser = { 0, };
- return_val_if_fail (index != NULL, NULL);
return_val_if_fail (asn1_cache != NULL, NULL);
- parser.index = index;
parser.asn1_defs = p11_asn1_cache_defs (asn1_cache);
parser.asn1_cache = asn1_cache;
+ parser.parsed = p11_array_new (p11_attrs_free);
+ return_val_if_fail (parser.parsed != NULL, NULL);
+
return memdup (&parser, sizeof (parser));
}
@@ -734,9 +636,17 @@ p11_parser_free (p11_parser *parser)
{
return_if_fail (parser != NULL);
p11_persist_free (parser->persist);
+ p11_array_free (parser->parsed);
free (parser);
}
+p11_array *
+p11_parser_parsed (p11_parser *parser)
+{
+ return_val_if_fail (parser != NULL, NULL);
+ return parser->parsed;
+}
+
int
p11_parse_memory (p11_parser *parser,
const char *filename,
@@ -749,15 +659,15 @@ p11_parse_memory (p11_parser *parser,
int i;
return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
+ return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
+ p11_array_clear (parser->parsed);
base = p11_path_base (filename);
parser->basename = base;
parser->flags = flags;
for (i = 0; all_parsers[i] != NULL; i++) {
- p11_index_batch (parser->index);
ret = (all_parsers[i]) (parser, data, length);
- p11_index_finish (parser->index);
if (ret != P11_PARSE_UNRECOGNIZED)
break;
diff --git a/trust/parser.h b/trust/parser.h
index ca41d26..f956fb9 100644
--- a/trust/parser.h
+++ b/trust/parser.h
@@ -55,8 +55,7 @@ enum {
typedef struct _p11_parser p11_parser;
-p11_parser * p11_parser_new (p11_index *index,
- p11_asn1_cache *asn1_cache);
+p11_parser * p11_parser_new (p11_asn1_cache *asn1_cache);
void p11_parser_free (p11_parser *parser);
@@ -70,4 +69,6 @@ int p11_parse_file (p11_parser *parser,
const char *filename,
int flags);
-#endif
+p11_array * p11_parser_parsed (p11_parser *parser);
+
+#endif /* P11_PARSER_H_ */
diff --git a/trust/tests/test-extract.c b/trust/tests/test-extract.c
index b121b21..ddb4a49 100644
--- a/trust/tests/test-extract.c
+++ b/trust/tests/test-extract.c
@@ -380,13 +380,18 @@ test_duplicate_extract (void)
}
static void
-test_duplicate_collapse (void)
+test_duplicate_distrusted (void)
{
CK_ATTRIBUTE certificate = { CKA_CLASS, &certificate_class, sizeof (certificate_class) };
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_X_DISTRUSTED, NULL, 0 },
+ };
+
+ CK_BBOOL val;
CK_RV rv;
- mock_module_add_object (MOCK_SLOT_ONE_ID, cacert3_trusted);
mock_module_add_object (MOCK_SLOT_ONE_ID, cacert3_distrusted);
+ mock_module_add_object (MOCK_SLOT_ONE_ID, cacert3_trusted);
test.ex.flags = P11_EXTRACT_COLLAPSE;
p11_kit_iter_add_callback (test.iter, p11_extract_info_load_filter, &test.ex, NULL);
@@ -396,6 +401,12 @@ test_duplicate_collapse (void)
rv = p11_kit_iter_next (test.iter);
assert_num_eq (CKR_OK, rv);
+ rv = p11_kit_iter_load_attributes (test.iter, attrs, 1);
+ assert_num_eq (CKR_OK, rv);
+ assert (p11_attrs_findn_bool (attrs, 1, CKA_X_DISTRUSTED, &val));
+ assert_num_eq (val, CK_TRUE);
+ free (attrs[0].pValue);
+
rv = p11_kit_iter_next (test.iter);
assert_num_eq (CKR_CANCEL, rv);
}
@@ -404,7 +415,6 @@ static void
test_trusted_match (void)
{
CK_ATTRIBUTE certificate = { CKA_CLASS, &certificate_class, sizeof (certificate_class) };
- CK_BBOOL boolv;
CK_RV rv;
mock_module_add_object (MOCK_SLOT_ONE_ID, cacert3_trusted);
@@ -416,13 +426,6 @@ test_trusted_match (void)
p11_kit_iter_begin_with (test.iter, &test.module, 0, 0);
rv = p11_kit_iter_next (test.iter);
- assert_num_eq (CKR_OK, rv);
-
- if (!p11_attrs_find_bool (test.ex.attrs, CKA_TRUSTED, &boolv))
- boolv = CK_FALSE;
- assert_num_eq (CK_TRUE, boolv);
-
- rv = p11_kit_iter_next (test.iter);
assert_num_eq (CKR_CANCEL, rv);
}
@@ -470,9 +473,6 @@ test_anytrust_match (void)
assert_num_eq (CKR_OK, rv);
rv = p11_kit_iter_next (test.iter);
- assert_num_eq (CKR_OK, rv);
-
- rv = p11_kit_iter_next (test.iter);
assert_num_eq (CKR_CANCEL, rv);
}
@@ -495,7 +495,7 @@ main (int argc,
p11_test (test_limit_to_purpose_match, "/extract/test_limit_to_purpose_match");
p11_test (test_limit_to_purpose_no_match, "/extract/test_limit_to_purpose_no_match");
p11_test (test_duplicate_extract, "/extract/test_duplicate_extract");
- p11_test (test_duplicate_collapse, "/extract/test_duplicate_collapse");
+ p11_test (test_duplicate_distrusted, "/extract/test-duplicate-distrusted");
p11_test (test_trusted_match, "/extract/test_trusted_match");
p11_test (test_distrust_match, "/extract/test_distrust_match");
p11_test (test_anytrust_match, "/extract/test_anytrust_match");
diff --git a/trust/tests/test-parser.c b/trust/tests/test-parser.c
index 2b60254..3eee984 100644
--- a/trust/tests/test-parser.c
+++ b/trust/tests/test-parser.c
@@ -51,24 +51,25 @@
struct {
p11_parser *parser;
+ p11_array *parsed;
p11_asn1_cache *cache;
- p11_index *index;
} test;
static void
setup (void *unused)
{
- test.index = p11_index_new (NULL, NULL, NULL);
test.cache = p11_asn1_cache_new ();
- test.parser = p11_parser_new (test.index, test.cache);
+ test.parser = p11_parser_new (test.cache);
assert_ptr_not_null (test.parser);
+
+ test.parsed = p11_parser_parsed (test.parser);
+ assert_ptr_not_null (test.parsed);
}
static void
teardown (void *unused)
{
p11_parser_free (test.parser);
- p11_index_free (test.index);
p11_asn1_cache_free (test.cache);
memset (&test, 0, sizeof (test));
}
@@ -85,12 +86,19 @@ static CK_ATTRIBUTE certificate_match[] = {
};
static CK_ATTRIBUTE *
-parsed_attrs (CK_ATTRIBUTE *match)
+parsed_attrs (CK_ATTRIBUTE *match,
+ int length)
{
- CK_OBJECT_HANDLE handle;
- handle = p11_index_find (test.index, certificate_match, -1);
- return p11_index_lookup (test.index, handle);
+ int i;
+
+ if (length < 0)
+ length = p11_attrs_count (match);
+ for (i = 0; i < test.parsed->num; i++) {
+ if (p11_attrs_matchn (test.parsed->elem[i], match, length))
+ return test.parsed->elem[i];
+ }
+ return NULL;
}
static void
@@ -114,9 +122,9 @@ test_parse_der_certificate (void)
assert_num_eq (P11_PARSE_SUCCESS, ret);
/* Should have gotten certificate */
- assert_num_eq (1, p11_index_size (test.index));
+ assert_num_eq (1, test.parsed->num);
- cert = parsed_attrs (certificate_match);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (expected, cert);
}
@@ -141,9 +149,9 @@ test_parse_pem_certificate (void)
assert_num_eq (P11_PARSE_SUCCESS, ret);
/* Should have gotten certificate */
- assert_num_eq (1, p11_index_size (test.index));
+ assert_num_eq (1, test.parsed->num);
- cert = parsed_attrs (certificate_match);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (expected, cert);
}
@@ -168,9 +176,9 @@ test_parse_p11_kit_persist (void)
assert_num_eq (P11_PARSE_SUCCESS, ret);
/* Should have gotten certificate */
- assert_num_eq (1, p11_index_size (test.index));
+ assert_num_eq (1, test.parsed->num);
- cert = parsed_attrs (certificate_match);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (expected, cert);
}
@@ -212,7 +220,6 @@ test_parse_openssl_trusted (void)
CK_ATTRIBUTE *cert;
CK_ATTRIBUTE *object;
- CK_OBJECT_HANDLE handle;
int ret;
int i;
@@ -225,18 +232,15 @@ test_parse_openssl_trusted (void)
* - 1 certificate
* - 2 stapled extensions
*/
- assert_num_eq (3, p11_index_size (test.index));
+ assert_num_eq (3, test.parsed->num);
/* The certificate */
- cert = parsed_attrs (certificate_match);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (expected[0], cert);
/* The other objects */
for (i = 1; expected[i]; i++) {
- handle = p11_index_find (test.index, expected[i], 2);
- assert (handle != 0);
-
- object = p11_index_lookup (test.index, handle);
+ object = parsed_attrs (expected[i], 2);
assert_ptr_not_null (object);
test_check_attrs (expected[i], object);
@@ -281,7 +285,6 @@ test_parse_openssl_distrusted (void)
CK_ATTRIBUTE *cert;
CK_ATTRIBUTE *object;
- CK_OBJECT_HANDLE handle;
int ret;
int i;
@@ -298,16 +301,13 @@ test_parse_openssl_distrusted (void)
* - 1 certificate
* - 2 stapled extensions
*/
- assert_num_eq (3, p11_index_size (test.index));
- cert = parsed_attrs (certificate_match);
+ assert_num_eq (3, test.parsed->num);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (expected[0], cert);
/* The other objects */
for (i = 1; expected[i]; i++) {
- handle = p11_index_find (test.index, expected[i], 2);
- assert (handle != 0);
-
- object = p11_index_lookup (test.index, handle);
+ object = parsed_attrs (expected[i], 2);
assert_ptr_not_null (object);
test_check_attrs (expected[i], object);
@@ -339,9 +339,9 @@ test_parse_anchor (void)
* Should have gotten:
* - 1 certificate
*/
- assert_num_eq (1, p11_index_size (test.index));
+ assert_num_eq (1, test.parsed->num);
- cert = parsed_attrs (certificate_match);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (cacert3, cert);
}
@@ -365,9 +365,9 @@ test_parse_thawte (void)
assert_num_eq (P11_PARSE_SUCCESS, ret);
/* Should have gotten certificate */
- assert_num_eq (1, p11_index_size (test.index));
+ assert_num_eq (1, test.parsed->num);
- cert = parsed_attrs (certificate_match);
+ cert = parsed_attrs (certificate_match, -1);
test_check_attrs (expected, cert);
}
@@ -401,124 +401,6 @@ test_parse_unrecognized (void)
p11_message_loud ();
}
-static void
-test_duplicate (void)
-{
- CK_ATTRIBUTE cacert3[] = {
- { CKA_CLASS, &certificate, sizeof (certificate) },
- { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
- { CKA_TRUSTED, &falsev, sizeof (falsev) },
- { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
- { CKA_INVALID },
- };
-
- CK_OBJECT_HANDLE *handles;
- CK_ATTRIBUTE *cert;
- int ret;
-
- ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der", 0);
- assert_num_eq (P11_PARSE_SUCCESS, ret);
-
- p11_message_quiet ();
-
- /* This shouldn't be added, should print a message */
- ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der", 0);
- assert_num_eq (P11_PARSE_SUCCESS, ret);
-
- assert (strstr (p11_message_last (), "duplicate") != NULL);
-
- p11_message_loud ();
-
- /* Should only be one certificate since the above two are identical */
- handles = p11_index_find_all (test.index, cacert3, 2);
- assert_ptr_not_null (handles);
- assert (handles[0] != 0);
- assert (handles[1] == 0);
-
- cert = p11_index_lookup (test.index, handles[0]);
- test_check_attrs (cacert3, cert);
-
- free (handles);
-}
-
-static void
-test_duplicate_priority (void)
-{
- CK_ATTRIBUTE cacert3[] = {
- { CKA_CLASS, &certificate, sizeof (certificate) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
- { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE trusted[] = {
- { CKA_CLASS, &certificate, sizeof (certificate) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
- { CKA_TRUSTED, &truev, sizeof (truev) },
- { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE distrust[] = {
- { CKA_CLASS, &certificate, sizeof (certificate) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
- { CKA_TRUSTED, &falsev, sizeof (falsev) },
- { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
- { CKA_INVALID },
- };
-
- CK_OBJECT_HANDLE *handles;
- CK_ATTRIBUTE *cert;
- int ret;
-
- ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der", 0);
- assert_num_eq (P11_PARSE_SUCCESS, ret);
-
- p11_message_quiet ();
-
- /* This shouldn't be added, should print a message */
- ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
- P11_PARSE_FLAG_ANCHOR);
- assert_num_eq (P11_PARSE_SUCCESS, ret);
-
- assert (strstr (p11_message_last (), "duplicate") != NULL);
-
- p11_message_loud ();
-
- /* We should now find the trusted certificate */
- handles = p11_index_find_all (test.index, cacert3, 2);
- assert_ptr_not_null (handles);
- assert (handles[0] != 0);
- assert (handles[1] == 0);
- cert = p11_index_lookup (test.index, handles[0]);
- test_check_attrs (trusted, cert);
- free (handles);
-
- /* Now add a distrutsed one, this should override the trusted */
-
- p11_message_quiet ();
-
- ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
- P11_PARSE_FLAG_BLACKLIST);
- assert_num_eq (P11_PARSE_SUCCESS, ret);
-
- p11_message_loud ();
-
- /* We should now find the distrusted certificate */
- handles = p11_index_find_all (test.index, cacert3, 2);
- assert_ptr_not_null (handles);
- assert (handles[0] != 0);
- assert (handles[1] == 0);
- cert = p11_index_lookup (test.index, handles[0]);
- test_check_attrs (distrust, cert);
- free (handles);
-}
-
int
main (int argc,
char *argv[])
@@ -533,7 +415,5 @@ main (int argc,
p11_test (test_parse_thawte, "/parser/parse_thawte");
p11_test (test_parse_invalid_file, "/parser/parse_invalid_file");
p11_test (test_parse_unrecognized, "/parser/parse_unrecognized");
- p11_test (test_duplicate, "/parser/duplicate");
- p11_test (test_duplicate_priority, "/parser/duplicate_priority");
return p11_test_run (argc, argv);
}
diff --git a/trust/tests/test-token.c b/trust/tests/test-token.c
index d372814..a518c9e 100644
--- a/trust/tests/test-token.c
+++ b/trust/tests/test-token.c
@@ -47,8 +47,14 @@
#include "message.h"
#include "token.h"
+static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
+static CK_BBOOL falsev = CK_FALSE;
+static CK_BBOOL truev = CK_TRUE;
+
struct {
p11_token *token;
+ p11_index *index;
+ char *directory;
} test;
static void
@@ -56,6 +62,19 @@ setup (void *path)
{
test.token = p11_token_new (333, path, "Label");
assert_ptr_not_null (test.token);
+
+ test.index = p11_token_index (test.token);
+ assert_ptr_not_null (test.token);
+}
+
+static void
+setup_temp (void *unused)
+{
+ test.directory = p11_path_expand ("$TEMP/test-module.XXXXXX");
+ if (!mkdtemp (test.directory))
+ assert_not_reached ();
+
+ setup (test.directory);
}
static void
@@ -66,15 +85,23 @@ teardown (void *path)
}
static void
+teardown_temp (void *unused)
+{
+ test_delete_directory (test.directory);
+ free (test.directory);
+ teardown (test.directory);
+}
+
+static void
test_token_load (void *path)
{
p11_index *index;
int count;
count = p11_token_load (test.token);
- assert_num_eq (7, count);
+ assert_num_eq (6, count);
- /* A certificate and trust object for each parsed object + builtin */
+ /* A certificate and trust object for each parsed object */
index = p11_token_index (test.token);
assert (((count - 1) * 2) + 1 <= p11_index_size (index));
}
@@ -82,10 +109,6 @@ test_token_load (void *path)
static void
test_token_flags (void *path)
{
- CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
- CK_BBOOL falsev = CK_FALSE;
- CK_BBOOL truev = CK_TRUE;
-
/*
* blacklist comes from the input/distrust.pem file. It is not in the blacklist
* directory, but is an OpenSSL trusted certificate file, and is marked
@@ -228,24 +251,8 @@ test_not_writable (void)
static void
test_writable_exists (void)
{
- char *directory;
- p11_token *token;
-
- directory = p11_path_expand ("$TEMP/test-module.XXXXXX");
- if (!mkdtemp (directory))
- assert_not_reached ();
-
- token = p11_token_new (333, directory, "Label");
-
/* A writable directory since we created it */
- assert (p11_token_is_writable (token));
-
- p11_token_free (token);
-
- if (rmdir (directory) < 0)
- assert_not_reached ();
-
- free (directory);
+ assert (p11_token_is_writable (test.token));
}
static void
@@ -276,6 +283,196 @@ test_writable_no_exist (void)
free (directory);
}
+static void
+test_load_already (void)
+{
+ CK_ATTRIBUTE cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ CK_OBJECT_HANDLE handle;
+ int ret;
+
+ test_write_file (test.directory, "test.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 1);
+ handle = p11_index_find (test.index, cert, -1);
+ assert (handle != 0);
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 0);
+ assert_num_eq (p11_index_find (test.index, cert, -1), handle);
+}
+
+static void
+test_load_unreadable (void)
+{
+ CK_ATTRIBUTE cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ int ret;
+
+ test_write_file (test.directory, "test.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 1);
+ assert (p11_index_find (test.index, cert, -1) != 0);
+
+ test_write_file (test.directory, "test.cer", "", 0);
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 0);
+ assert (p11_index_find (test.index, cert, -1) == 0);
+}
+
+static void
+test_load_gone (void)
+{
+ CK_ATTRIBUTE cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ int ret;
+
+ test_write_file (test.directory, "test.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 1);
+ assert (p11_index_find (test.index, cert, -1) != 0);
+
+ test_delete_file (test.directory, "test.cer");
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 0);
+ assert (p11_index_find (test.index, cert, -1) == 0);
+}
+
+static void
+test_load_found (void)
+{
+ CK_ATTRIBUTE cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ int ret;
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 0);
+ assert (p11_index_find (test.index, cert, -1) == 0);
+
+ test_write_file (test.directory, "test.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 1);
+ assert (p11_index_find (test.index, cert, -1) != 0);
+}
+
+static void
+test_reload_changed (void)
+{
+ CK_ATTRIBUTE cacert3[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE verisign[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_OBJECT_HANDLE handle;
+ int ret;
+
+ /* Just one file */
+ test_write_file (test.directory, "test.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 1);
+ handle = p11_index_find (test.index, cacert3, -1);
+ assert (handle != 0);
+
+ /* Replace the file with verisign */
+ test_write_file (test.directory, "test.cer", verisign_v1_ca,
+ sizeof (verisign_v1_ca));
+
+ /* Add another file with cacert3, but not reloaded */
+ test_write_file (test.directory, "another.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+
+ attrs = p11_index_lookup (test.index, handle);
+ assert_ptr_not_null (attrs);
+ p11_token_reload (test.token, attrs);
+
+ assert (p11_index_find (test.index, cacert3, -1) == 0);
+ assert (p11_index_find (test.index, verisign, -1) != 0);
+}
+
+static void
+test_reload_gone (void)
+{
+ CK_ATTRIBUTE cacert3[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE verisign[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_OBJECT_HANDLE handle;
+ int ret;
+
+ /* Just one file */
+ test_write_file (test.directory, "cacert3.cer", test_cacert3_ca_der,
+ sizeof (test_cacert3_ca_der));
+ test_write_file (test.directory, "verisign.cer", verisign_v1_ca,
+ sizeof (verisign_v1_ca));
+
+ ret = p11_token_load (test.token);
+ assert_num_eq (ret, 2);
+ handle = p11_index_find (test.index, cacert3, -1);
+ assert (handle != 0);
+ assert (p11_index_find (test.index, verisign, -1) != 0);
+
+ test_delete_file (test.directory, "cacert3.cer");
+ test_delete_file (test.directory, "verisign.cer");
+
+ attrs = p11_index_lookup (test.index, handle);
+ assert_ptr_not_null (attrs);
+ p11_token_reload (test.token, attrs);
+
+ assert (p11_index_find (test.index, cacert3, -1) == 0);
+ assert (p11_index_find (test.index, verisign, -1) != 0);
+}
+
int
main (int argc,
char *argv[])
@@ -283,16 +480,22 @@ main (int argc,
p11_fixture (setup, teardown);
p11_testx (test_token_load, SRCDIR "/input", "/token/load");
p11_testx (test_token_flags, SRCDIR "/input", "/token/flags");
-
- p11_fixture (setup, teardown);
p11_testx (test_token_path, "/wheee", "/token/path");
p11_testx (test_token_label, "/wheee", "/token/label");
p11_testx (test_token_slot, "/unneeded", "/token/slot");
p11_fixture (NULL, NULL);
p11_test (test_not_writable, "/token/not-writable");
- p11_test (test_writable_exists, "/token/writable-exists");
p11_test (test_writable_no_exist, "/token/writable-no-exist");
+ p11_fixture (setup_temp, teardown_temp);
+ p11_test (test_writable_exists, "/token/writable-exists");
+ p11_test (test_load_found, "/token/load-found");
+ p11_test (test_load_already, "/token/load-already");
+ p11_test (test_load_unreadable, "/token/load-unreadable");
+ p11_test (test_load_gone, "/token/load-gone");
+ p11_test (test_reload_changed, "/token/reload-changed");
+ p11_test (test_reload_gone, "/token/reload-gone");
+
return p11_test_run (argc, argv);
}
diff --git a/trust/tests/test-trust.c b/trust/tests/test-trust.c
index 33ba19e..fceaea7 100644
--- a/trust/tests/test-trust.c
+++ b/trust/tests/test-trust.c
@@ -324,3 +324,78 @@ test_check_directory_msg (const char *file,
p11_dict_free (files);
}
+
+void
+test_write_file_msg (const char *file,
+ int line,
+ const char *function,
+ const char *directory,
+ const char *name,
+ const void *contents,
+ size_t length)
+{
+ char *path;
+ FILE *f;
+
+ if (asprintf (&path, "%s/%s", directory, name) < 0)
+ assert_not_reached ();
+
+ f = fopen (path, "wb");
+ if (f == NULL) {
+ p11_test_fail (file, line, function, "Couldn't open file for writing: %s: %s",
+ path, strerror (errno));
+ }
+
+ if (fwrite (contents, 1, length, f) != length ||
+ fclose (f) != 0) {
+ p11_test_fail (file, line, function, "Couldn't write file: %s: %s",
+ path, strerror (errno));
+ }
+
+ free (path);
+}
+
+void
+test_delete_file_msg (const char *file,
+ int line,
+ const char *function,
+ const char *directory,
+ const char *name)
+{
+ char *path;
+
+ if (asprintf (&path, "%s/%s", directory, name) < 0)
+ assert_not_reached ();
+
+ if (unlink (path) < 0)
+ p11_test_fail (file, line, function, "Couldn't delete file: %s", path);
+
+ free (path);
+}
+
+void
+test_delete_directory_msg (const char *file,
+ int line,
+ const char *function,
+ const char *directory)
+{
+ struct dirent *dp;
+ DIR *dir;
+
+ dir = opendir (directory);
+ if (dir == NULL)
+ p11_test_fail (file ,line, function, "Couldn't open directory: %s", directory);
+
+ while ((dp = readdir (dir)) != NULL) {
+ if (strcmp (dp->d_name, ".") == 0 ||
+ strcmp (dp->d_name, "..") == 0)
+ continue;
+
+ test_delete_file_msg (file, line, function, directory, dp->d_name);
+ }
+
+ closedir (dir);
+
+ if (rmdir (directory) < 0)
+ p11_test_fail (file, line, function, "Couldn't remove directory: %s", directory);
+}
diff --git a/trust/tests/test-trust.h b/trust/tests/test-trust.h
index 18ca13c..4d2c5bf 100644
--- a/trust/tests/test-trust.h
+++ b/trust/tests/test-trust.h
@@ -344,4 +344,32 @@ void test_check_directory_msg (const char *file,
(test_check_directory_msg (__FILE__, __LINE__, __FUNCTION__, directory, \
test_check_directory_files files))
+#define test_write_file(directory, name, data, length) \
+ (test_write_file_msg (__FILE__, __LINE__, __FUNCTION__, directory, name, data, length))
+
+void test_write_file_msg (const char *file,
+ int line,
+ const char *function,
+ const char *directory,
+ const char *name,
+ const void *contents,
+ size_t length);
+
+#define test_delete_file(directory, name) \
+ (test_delete_file_msg (__FILE__, __LINE__, __FUNCTION__, directory, name))
+
+void test_delete_file_msg (const char *file,
+ int line,
+ const char *function,
+ const char *directory,
+ const char *name);
+
+#define test_delete_directory(directory) \
+ (test_delete_directory_msg (__FILE__, __LINE__, __FUNCTION__, directory))
+
+void test_delete_directory_msg (const char *file,
+ int line,
+ const char *function,
+ const char *directory);
+
#endif /* TEST_DATA_H_ */
diff --git a/trust/token.c b/trust/token.c
index c5991df..ec34f6c 100644
--- a/trust/token.c
+++ b/trust/token.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Red Hat Inc.
+ * Copyright (C) 2012-2013 Red Hat Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -58,48 +58,200 @@
#include <string.h>
struct _p11_token {
- p11_parser *parser;
- p11_index *index;
- p11_builder *builder;
- char *path;
- char *label;
- CK_SLOT_ID slot;
- int loaded;
+ p11_parser *parser; /* Parser we use to load files */
+ p11_index *index; /* Index we load objects into */
+ p11_builder *builder; /* Expands objects and applies policy */
+ p11_dict *loaded; /* stat structs for loaded files, track reloads */
+
+ char *path; /* Main path to load from */
+ char *anchors; /* Path to load anchors from */
+ char *blacklist; /* Path to load blacklist from */
+ char *label; /* The token label */
+ CK_SLOT_ID slot; /* The slot id */
bool checked_writable;
bool is_writable;
};
+static bool
+loader_is_necessary (p11_token *token,
+ const char *filename,
+ struct stat *sb)
+{
+ struct stat *last;
+
+ last = p11_dict_get (token->loaded, filename);
+
+ /* Never seen this before, load it */
+ if (last == NULL)
+ return true;
+
+ /*
+ * If any of these are different assume that the file
+ * needs to be reloaded
+ */
+ return (sb->st_mode != last->st_mode ||
+ sb->st_mtime != last->st_mtime ||
+ sb->st_size != last->st_size);
+}
+
+static void
+loader_was_loaded (p11_token *token,
+ const char *filename,
+ struct stat *sb)
+{
+ char *key;
+
+ key = strdup (filename);
+ return_if_fail (key != NULL);
+
+ sb = memdup (sb, sizeof (struct stat));
+ return_if_fail (sb != NULL);
+
+ /* Track the info about this file, so we don't reload unnecessarily */
+ if (!p11_dict_set (token->loaded, key, sb))
+ return_if_reached ();
+}
+
+static void
+loader_not_loaded (p11_token *token,
+ const char *filename)
+{
+ /* No longer track info about this file */
+ p11_dict_remove (token->loaded, filename);
+}
+
+static void
+loader_gone_file (p11_token *token,
+ const char *filename)
+{
+ CK_ATTRIBUTE origin[] = {
+ { CKA_X_ORIGIN, (void *)filename, strlen (filename) },
+ { CKA_INVALID },
+ };
+
+ CK_RV rv;
+
+ /* Remove everything at this origin */
+ rv = p11_index_replace_all (token->index, origin, CKA_INVALID, NULL);
+ return_if_fail (rv == CKR_OK);
+
+ /* No longer track info about this file */
+ loader_not_loaded (token, filename);
+}
+
static int
loader_load_file (p11_token *token,
const char *filename,
- struct stat *sb,
- int flags)
+ struct stat *sb)
{
+ CK_ATTRIBUTE origin[] = {
+ { CKA_X_ORIGIN, (void *)filename, strlen (filename) },
+ { CKA_INVALID },
+ };
+
+ CK_BBOOL modifiablev;
+
+ CK_ATTRIBUTE modifiable = {
+ CKA_MODIFIABLE,
+ &modifiablev,
+ sizeof (modifiablev)
+ };
+
+ p11_array *parsed;
+ CK_RV rv;
+ int flags;
int ret;
+ int i;
+
+ /* Check if this file is already loaded */
+ if (!loader_is_necessary (token, filename, sb))
+ return 0;
+
+ flags = P11_PARSE_FLAG_NONE;
+
+ /* If it's in the anchors subdirectory, treat as an anchor */
+ if (p11_path_prefix (filename, token->anchors))
+ flags = P11_PARSE_FLAG_ANCHOR;
+
+ /* If it's in the blacklist subdirectory, treat as a blacklist */
+ else if (p11_path_prefix (filename, token->blacklist))
+ flags = P11_PARSE_FLAG_BLACKLIST;
+
+ /* If the token is just one path, then assume they are anchors */
+ else if (strcmp (filename, token->path) == 0 && !S_ISDIR (sb->st_mode))
+ flags = P11_PARSE_FLAG_ANCHOR;
ret = p11_parse_file (token->parser, filename, flags);
switch (ret) {
case P11_PARSE_SUCCESS:
p11_debug ("loaded: %s", filename);
- return 1;
+ break;
case P11_PARSE_UNRECOGNIZED:
p11_debug ("skipped: %s", filename);
+ loader_gone_file (token, filename);
return 0;
default:
p11_debug ("failed to parse: %s", filename);
+ loader_gone_file (token, filename);
return 0;
}
+
+ /* TODO: We should check if in the right format */
+ modifiablev = CK_FALSE;
+
+ /* Update each parsed object with the origin */
+ parsed = p11_parser_parsed (token->parser);
+ for (i = 0; i < parsed->num; i++) {
+ parsed->elem[i] = p11_attrs_build (parsed->elem[i], origin, &modifiable, NULL);
+ return_val_if_fail (parsed->elem[i] != NULL, 0);
+ }
+
+ p11_index_batch (token->index);
+
+ /* Now place all of these in the index */
+ rv = p11_index_replace_all (token->index, origin, CKA_CLASS, parsed);
+
+ p11_index_finish (token->index);
+
+ if (rv != CKR_OK) {
+ p11_message ("couldn't load file into objects: %s", filename);
+ return 0;
+ }
+
+ loader_was_loaded (token, filename, sb);
+ return 1;
+}
+
+static int
+loader_load_if_file (p11_token *token,
+ const char *path)
+{
+ struct stat sb;
+
+ if (stat (path, &sb) < 0) {
+ if (errno == ENOENT) {
+ p11_message ("couldn't stat path: %s: %s",
+ path, strerror (errno));
+ }
+
+ } else if (!S_ISDIR (sb.st_mode)) {
+ return loader_load_file (token, path, &sb);
+ }
+
+ /* Perhaps the file became unloadable, so track properly */
+ loader_gone_file (token, path);
+ return 0;
}
static int
loader_load_directory (p11_token *token,
const char *directory,
- int flags)
+ p11_dict *present)
{
+ p11_dictiter iter;
struct dirent *dp;
- struct stat sb;
char *path;
int total = 0;
int ret;
@@ -110,6 +262,7 @@ loader_load_directory (p11_token *token,
if (!dir) {
p11_message ("couldn't list directory: %s: %s",
directory, strerror (errno));
+ loader_not_loaded (token, directory);
return 0;
}
@@ -118,81 +271,81 @@ loader_load_directory (p11_token *token,
path = p11_path_build (directory, dp->d_name, NULL);
return_val_if_fail (path != NULL, -1);
- if (stat (path, &sb) < 0) {
- p11_message ("couldn't stat path: %s", path);
+ ret = loader_load_if_file (token, path);
+ return_val_if_fail (ret >=0, -1);
+ total += ret;
- } else if (!S_ISDIR (sb.st_mode)) {
- ret = loader_load_file (token, path, &sb, flags);
- return_val_if_fail (ret >= 0, ret);
- total += ret;
- }
+ /* Make note that this file was seen */
+ p11_dict_remove (present, path);
free (path);
}
closedir (dir);
- return total;
-}
-static int
-loader_load_subdirectory (p11_token *token,
- const char *directory,
- const char *subdir,
- int flags)
-{
- struct stat sb;
- char *path;
- int ret = 0;
+ /* All other files that were present, not here now */
+ p11_dict_iterate (present, &iter);
+ while (p11_dict_next (&iter, (void **)&path, NULL))
+ loader_gone_file (token, path);
- if (asprintf (&path, "%s/%s", directory, subdir) < 0)
- return_val_if_reached (-1);
-
- if (stat (path, &sb) >= 0 && S_ISDIR (sb.st_mode))
- ret = loader_load_directory (token, path, flags);
-
- free (path);
- return ret;
+ return total;
}
static int
loader_load_path (p11_token *token,
const char *path)
{
+ p11_dictiter iter;
+ p11_dict *present;
+ char *filename;
struct stat sb;
int total;
int ret;
if (stat (path, &sb) < 0) {
- if (errno == ENOENT) {
- p11_message ("trust certificate path does not exist: %s",
- path);
- } else {
+ if (errno != ENOENT) {
p11_message ("cannot access trust certificate path: %s: %s",
path, strerror (errno));
}
-
+ loader_gone_file (token, path);
return 0;
}
if (S_ISDIR (sb.st_mode)) {
- total = 0;
- ret = loader_load_subdirectory (token, path, "anchors", P11_PARSE_FLAG_ANCHOR);
- return_val_if_fail (ret >= 0, ret);
- total += ret;
+ /* All the files we know about at this path */
+ present = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL);
+ p11_dict_iterate (token->loaded, &iter);
+ while (p11_dict_next (&iter, (void **)&filename, NULL)) {
+ if (p11_path_prefix (filename, path)) {
+ if (!p11_dict_set (present, filename, filename))
+ return_val_if_reached (-1);
+ }
+ }
- ret = loader_load_subdirectory (token, path, "blacklist", P11_PARSE_FLAG_BLACKLIST);
- return_val_if_fail (ret >= 0, ret);
- total += ret;
+ /* If the directory has changed, reload it */
+ if (loader_is_necessary (token, path, &sb)) {
+ ret = loader_load_directory (token, path, present);
- ret = loader_load_directory (token, path, P11_PARSE_FLAG_NONE);
- return_val_if_fail (ret >= 0, ret);
- total += ret;
+ /* Directory didn't change, but maybe files changed? */
+ } else {
+ total = 0;
+ p11_dict_iterate (present, &iter);
+ while (p11_dict_next (&iter, (void **)&filename, NULL)) {
+ ret = loader_load_if_file (token, filename);
+ return_val_if_fail (ret >= 0, ret);
+ total += ret;
+ }
+ }
+
+ p11_dict_free (present);
+ loader_was_loaded (token, path, &sb);
- return total;
} else {
- return loader_load_file (token, path, &sb, P11_PARSE_FLAG_ANCHOR);
+ ret = loader_load_file (token, path, &sb);
}
+
+ return ret;
}
static int
@@ -223,19 +376,49 @@ load_builtin_objects (p11_token *token)
int
p11_token_load (p11_token *token)
{
- int builtins;
- int count;
+ int total = 0;
+ int ret;
- if (token->loaded)
- return 0;
- token->loaded = 1;
+ ret = loader_load_path (token, token->path);
+ return_val_if_fail (ret >= 0, -1);
+ total += ret;
+
+ ret = loader_load_path (token, token->anchors);
+ return_val_if_fail (ret >= 0, -1);
+ total += ret;
+
+ ret = loader_load_path (token, token->blacklist);
+ return_val_if_fail (ret >= 0, -1);
+ total += ret;
+
+ return total;
+}
- builtins = load_builtin_objects (token);
+void
+p11_token_reload (p11_token *token,
+ CK_ATTRIBUTE *attrs)
+{
+ CK_ATTRIBUTE *attr;
+ struct stat sb;
+ char *origin;
- count = loader_load_path (token, token->path);
- return_val_if_fail (count >= 0, count);
+ attr = p11_attrs_find (attrs, CKA_X_ORIGIN);
+ if (attr == NULL)
+ return;
- return count + builtins;
+ origin = strndup (attr->pValue, attr->ulValueLen);
+ return_if_fail (origin != NULL);
+
+ if (stat (origin, &sb) < 0) {
+ if (errno == ENOENT) {
+ loader_gone_file (token, origin);
+ } else {
+ p11_message ("cannot access trust file: %s: %s",
+ origin, strerror (errno));
+ }
+ } else {
+ loader_load_file (token, origin, &sb);
+ }
}
void
@@ -247,7 +430,10 @@ p11_token_free (p11_token *token)
p11_index_free (token->index);
p11_parser_free (token->parser);
p11_builder_free (token->builder);
+ p11_dict_free (token->loaded);
free (token->path);
+ free (token->anchors);
+ free (token->blacklist);
free (token->label);
free (token);
}
@@ -273,18 +459,27 @@ p11_token_new (CK_SLOT_ID slot,
token->builder);
return_val_if_fail (token->index != NULL, NULL);
- token->parser = p11_parser_new (token->index,
- p11_builder_get_cache (token->builder));
+ token->parser = p11_parser_new (p11_builder_get_cache (token->builder));
return_val_if_fail (token->parser != NULL, NULL);
+ token->loaded = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, free);
+ return_val_if_fail (token->loaded != NULL, NULL);
+
token->path = strdup (path);
return_val_if_fail (token->path != NULL, NULL);
+ token->anchors = p11_path_build (token->path, "anchors", NULL);
+ return_val_if_fail (token->anchors != NULL, NULL);
+
+ token->blacklist = p11_path_build (token->path, "blacklist", NULL);
+ return_val_if_fail (token->blacklist != NULL, NULL);
+
token->label = strdup (label);
return_val_if_fail (token->label != NULL, NULL);
token->slot = slot;
- token->loaded = 0;
+
+ load_builtin_objects (token);
p11_debug ("token: %s: %s", token->label, token->path);
return token;
diff --git a/trust/token.h b/trust/token.h
index 49140bb..6d50c6c 100644
--- a/trust/token.h
+++ b/trust/token.h
@@ -49,6 +49,9 @@ void p11_token_free (p11_token *token);
int p11_token_load (p11_token *token);
+void p11_token_reload (p11_token *token,
+ CK_ATTRIBUTE *attrs);
+
p11_index * p11_token_index (p11_token *token);
const char * p11_token_get_path (p11_token *token);