summaryrefslogtreecommitdiff
path: root/trust/token.c
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-01-24 11:34:47 +0100
committerStef Walter <stefw@gnome.org>2013-02-05 14:54:46 +0100
commit5147d71466455b3d087b3f3a7472a35e8216c55a (patch)
tree4b81eee35b7d0ec877a34c4fde06478d700a3960 /trust/token.c
parent603c7d4eb996f51178ccc9d235597497bbb2c7a4 (diff)
downloadp11-kit-5147d71466455b3d087b3f3a7472a35e8216c55a.tar.gz
Add basic trust module
This is based off the roots-store from gnome-keyring and loads certificates from a root directory and exposes them as PKCS#11 objects.
Diffstat (limited to 'trust/token.c')
-rw-r--r--trust/token.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/trust/token.c b/trust/token.c
new file mode 100644
index 0000000..8a607f0
--- /dev/null
+++ b/trust/token.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2012 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"
+
+#include "attrs.h"
+#include "compat.h"
+#include "debug.h"
+#include "errno.h"
+#include "library.h"
+#include "module.h"
+#include "parser.h"
+#include "pkcs11.h"
+#include "token.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct _p11_token {
+ p11_parser *parser;
+ p11_dict *objects;
+ const char *anchor_paths;
+ const char *other_paths;
+ const char *certificate_paths;
+ int loaded;
+};
+
+static void
+on_parser_object (CK_ATTRIBUTE *attrs,
+ void *user_data)
+{
+ CK_OBJECT_HANDLE object;
+ CK_OBJECT_HANDLE *key;
+ p11_token *token = user_data;
+
+ object = p11_module_next_id ();
+
+ key = memdup (&object, sizeof (object));
+ return_if_fail (key != NULL);
+
+ if (!p11_dict_set (token->objects, key, attrs))
+ return_if_reached ();
+}
+
+static int
+loader_load_file (p11_token *token,
+ const char *filename,
+ struct stat *sb,
+ int flags)
+{
+ int ret;
+
+ ret = p11_parse_file (token->parser, filename, flags,
+ on_parser_object, token);
+
+ return ret == P11_PARSE_SUCCESS ? 1 : 0;
+}
+
+static int
+loader_load_directory (p11_token *token,
+ const char *directory,
+ int flags)
+{
+ struct dirent *dp;
+ struct stat sb;
+ char *path;
+ int total = 0;
+ int ret;
+ DIR *dir;
+
+ /* First we load all the modules */
+ dir = opendir (directory);
+ if (!dir) {
+ p11_message ("couldn't list directory: %s: %s",
+ directory, strerror (errno));
+ return 0;
+ }
+
+ /* We're within a global mutex, so readdir is safe */
+ while ((dp = readdir (dir)) != NULL) {
+ path = strconcat (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);
+
+ } else if (!S_ISDIR (sb.st_mode)) {
+ ret = loader_load_file (token, path, &sb, flags);
+ return_val_if_fail (ret > 0, ret);
+ total += ret;
+ }
+
+ free (path);
+ }
+
+ closedir (dir);
+ return total;
+}
+
+static int
+loader_load_path (p11_token *token,
+ const char *path,
+ int flags)
+{
+ struct stat sb;
+
+ if (stat (path, &sb) < 0) {
+ if (errno == ENOENT) {
+ p11_message ("trust certificate path does not exist: %s",
+ path);
+ } else {
+ p11_message ("cannot access trust certificate path: %s: %s",
+ path, strerror (errno));
+ }
+
+ return 0;
+ }
+
+ if (S_ISDIR (sb.st_mode))
+ return loader_load_directory (token, path, flags);
+ else
+ return loader_load_file (token, path, &sb, flags);
+}
+
+static int
+loader_load_paths (p11_token *token,
+ const char *paths,
+ int flags)
+{
+ const char *pos;
+ int total = 0;
+ char *path;
+ int ret;
+
+ while (paths) {
+ pos = strchr (paths, ':');
+ if (pos == NULL) {
+ path = strdup (paths);
+ paths = NULL;
+ } else {
+ path = strndup (paths, pos - paths);
+ paths = pos + 1;
+ }
+
+ return_val_if_fail (path != NULL, -1);
+
+ if (path[0] != '\0') {
+ /* We don't expect this to fail except for in strange circumstances */
+ ret = loader_load_path (token, path, flags);
+ if (ret < 0)
+ return_val_if_reached (-1);
+ total += ret;
+ }
+
+ free (path);
+ }
+
+ return total;
+}
+
+int
+p11_token_load (p11_token *token)
+{
+ int anchors;
+ int other;
+
+ if (token->loaded)
+ return 0;
+ token->loaded = 1;
+
+ anchors = loader_load_paths (token, token->anchor_paths, P11_PARSE_FLAG_ANCHOR);
+ if (anchors < 0)
+ return anchors;
+
+ other = loader_load_paths (token, token->other_paths, P11_PARSE_FLAG_NONE);
+ if (other < 0)
+ return other;
+
+ return anchors + other;
+}
+
+p11_dict *
+p11_token_objects (p11_token *token)
+{
+ return token->objects;
+}
+
+void
+p11_token_free (p11_token *token)
+{
+ if (!token)
+ return;
+
+ p11_dict_free (token->objects);
+ p11_parser_free (token->parser);
+ free (token);
+}
+
+p11_token *
+p11_token_new (const char *anchor_paths,
+ const char *other_paths)
+{
+ p11_token *token;
+
+ token = calloc (1, sizeof (p11_token));
+ return_val_if_fail (token != NULL, NULL);
+
+ token->parser = p11_parser_new ();
+ return_val_if_fail (token->parser != NULL, NULL);
+
+ token->objects = p11_dict_new (p11_dict_ulongptr_hash,
+ p11_dict_ulongptr_equal,
+ free, p11_attrs_free);
+ return_val_if_fail (token->objects != NULL, NULL);
+
+ token->anchor_paths = anchor_paths;
+ token->other_paths = other_paths;
+ token->loaded = 0;
+
+ return token;
+}