]> granicus.if.org Git - p11-kit/commitdiff
Add enable-in and disable-in options to module config
authorStef Walter <stefw@gnome.org>
Sun, 1 Apr 2012 19:53:04 +0000 (21:53 +0200)
committerStef Walter <stefw@gnome.org>
Sun, 1 Apr 2012 19:53:04 +0000 (21:53 +0200)
 * These can be used to load certain modules in certain
   programs, or prevent loading in others.
 * Useful for a key manager like seahorse, so we can load
   extra modules (think NSS) that other modules shouldn't
   load.

.gitignore
configure.ac
doc/p11-kit-config.xml
doc/p11-kit-sections.txt
p11-kit/modules.c
p11-kit/p11-kit.h
p11-kit/private.h
p11-kit/util.c
tests/Makefile.am
tests/progname-test.c [new file with mode: 0644]

index 84864232fa39946ba70461d83a9223906f8f35bf..77f2789f549fefdc9bb6bedc77ecee7e8dfd47b2 100644 (file)
@@ -77,6 +77,8 @@ temp.txt
 /tests/p11-test
 /tests/pin-test
 /tests/print-messages
+/tests/print-progname
+/tests/progname-test
 /tests/ptr-array-test
 /tests/conf-test
 /tests/uri-test
index 720c95d2638162f5a851b08497272412b344c0a1..401265f7b7c422c42563285b430cff07c500ac54 100644 (file)
@@ -6,6 +6,8 @@ AC_INIT([p11-kit],
        [p11-kit],
        [http://p11-glue.freedesktop.org/p11-kit.html])
 
+AC_USE_SYSTEM_EXTENSIONS
+
 # ------------------------------------------------------------------------------
 # p11-kit libtool versioning
 # CURRENT : REVISION : AGE
@@ -31,7 +33,6 @@ LT_INIT([dlopen disable-static])
 AC_PROG_CC
 AC_PROG_CPP
 AM_PROG_CC_C_O
-AC_USE_SYSTEM_EXTENSIONS
 
 LINGUAS=""
 AM_GNU_GETTEXT([external], [need-ngettext])
@@ -66,6 +67,15 @@ if test "$os_unix" = "yes"; then
                [AC_MSG_ERROR([could not find dlopen])])
        AC_CHECK_MEMBERS([struct dirent.d_type],,,[#include <dirent.h>])
        AC_CHECK_HEADERS([err.h])
+       AC_CHECK_FUNCS([getprogname getexecname])
+
+       # Check if these are declared and/or available to link against
+       AC_CHECK_DECLS([program_invocation_short_name])
+       AC_LINK_IFELSE([AC_LANG_SOURCE([extern char *program_invocation_short_name; void main() { }])],
+               [AC_DEFINE(HAVE_PROGRAM_INVOCATION_SHORT_NAME, [1], [Whether program_invocation_short_name available])])
+       AC_CHECK_DECLS([__progname])
+       AC_LINK_IFELSE([AC_LANG_SOURCE([extern char *__progname; void main() { }])],
+               [AC_DEFINE(HAVE___PROGNAME, [1], [Whether __progname available])])
 fi
 
 # ------------------------------------------------------------------------------
index 7c28f86a366e8b5e03c2443a6b7239ede6ce0aea..11fb41f93708b5fc6c86c79564a51b59fa75a811 100644 (file)
@@ -140,8 +140,35 @@ critical: yes
                                        <para>This argument is optional and defaults to <literal>no</literal>.</para>
                                </listitem>
                        </varlistentry>
+                       <varlistentry>
+                               <term>enable-in:</term>
+                               <listitem>
+                                       <para>A comma and/or space separated list of names of programs that
+                                       this module should only be loaded in. The module will not be loaded
+                                       for other programs using p11-kit. The base name of the process executable
+                                       should be used here, for example
+                                       <literal>seahorse, ssh</literal>.</para>
+                                       <para>This is not a security feature. The argument is optional. If
+                                       not present, then any process will load the module.</para>
+                               </listitem>
+                       </varlistentry>
+                       <varlistentry>
+                               <term>disable-in:</term>
+                               <listitem>
+                                       <para>A comma and/or space separated list of names of programs that
+                                       this module should not be loaded in. The module will be loaded for any
+                                       other programs using p11-kit. The base name of the process
+                                       executable should be used here, for example
+                                       <literal>firefox, thunderbird-bin</literal>.</para>
+                                       <para>This is not a security feature. The argument is optional. If
+                                       not present, then any process will load the module.</para>
+                               </listitem>
+                       </varlistentry>
                </variablelist>
 
+               <para>Do not specify both <literal>enable-in</literal> and <literal>disable-in</literal>
+               for the same module.</para>
+
                <para>Other fields may be present, but it is recommended that field names
                that are not specified in this document start with a <literal>x-</literal>
                prefix.</para>
index 37fceb50cadafcd77967cd1f434becb1c7f96f4f..bdd0434c0718b8d602ddcd2238a2424c164bb00c 100644 (file)
@@ -81,6 +81,7 @@ p11_kit_uri_type_t
 
 <SECTION>
 <FILE>p11-kit-future</FILE>
+p11_kit_set_progname
 p11_kit_be_quiet
 p11_kit_message
 </SECTION>
\ No newline at end of file
index 047a2ca6688e2ec89856a25c2d96cb8906267c2e..f059097db346743c866ddae0697054c9e530e007 100644 (file)
@@ -47,6 +47,7 @@
 #include <sys/types.h>
 
 #include <assert.h>
+#include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
 #include <limits.h>
@@ -336,6 +337,61 @@ expand_module_path (const char *filename)
        return path;
 }
 
+static int
+is_list_delimiter (char ch)
+{
+       return ch == ',' ||  isspace (ch);
+}
+
+static int
+is_string_in_list (const char *list,
+                   const char *string)
+{
+       const char *where;
+
+       where = strstr (list, string);
+       if (where == NULL)
+               return 0;
+
+       /* Has to be at beginning/end of string, and delimiter before/after */
+       if (where != list && !is_list_delimiter (*(where - 1)))
+               return 0;
+
+       where += strlen (string);
+       return (*where == '\0' || is_list_delimiter (*where));
+}
+
+static int
+is_module_enabled_unlocked (const char *name,
+                            hashmap *config)
+{
+       const char *progname;
+       const char *enable_in;
+       const char *disable_in;
+       int enable;
+
+       enable_in = _p11_hash_get (config, "enable-in");
+       disable_in = _p11_hash_get (config, "disable-in");
+
+       /* Defaults to enabled if neither of these are set */
+       if (!enable_in && !disable_in)
+               return 1;
+
+       progname = _p11_get_progname_unlocked ();
+       if (enable_in && disable_in)
+               _p11_message ("module '%s' has both enable-in and disable-in options", name);
+       if (enable_in)
+               enable = (progname != NULL && is_string_in_list (enable_in, progname));
+       else if (disable_in)
+               enable = (progname == NULL || !is_string_in_list (disable_in, progname));
+
+       _p11_debug ("%s module '%s' running in '%s'",
+                   enable ? "enabled" : "disabled",
+                   name,
+                   progname ? progname : "(null)");
+       return enable;
+}
+
 static CK_RV
 take_config_and_load_module_unlocked (char **name, hashmap **config)
 {
@@ -349,6 +405,9 @@ take_config_and_load_module_unlocked (char **name, hashmap **config)
        assert (config);
        assert (*config);
 
+       if (!is_module_enabled_unlocked (*name, *config))
+               return CKR_OK;
+
        module_filename = _p11_hash_get (*config, "module");
        if (module_filename == NULL) {
                _p11_debug ("no module path for module, skipping: %s", *name);
@@ -832,8 +891,22 @@ _p11_kit_registered_modules_unlocked (void)
        if (result) {
                _p11_hash_iterate (gl.modules, &iter);
                while (_p11_hash_next (&iter, NULL, (void **)&mod)) {
-                       if (mod->ref_count && mod->name)
+
+                       /*
+                        * We don't include unreferenced modules. We don't include
+                        * modules that have been initialized but aren't in the
+                        * registry. These have a NULL name.
+                        *
+                        * In addition we check again that the module isn't disabled
+                        * using enable-in or disable-in. This is because a caller
+                        * can change the progname we recognize the process as after
+                        * having initialized. This is a corner case, but want to make
+                        * sure to cover it.
+                        */
+                       if (mod->ref_count && mod->name &&
+                           is_module_enabled_unlocked (mod->name, mod->config)) {
                                result[i++] = mod->funcs;
+                       }
                }
        }
 
index cf84db63fda718be3d205fc9ec433c78dbfe47fb..77cf1b5a1a41d46348074ea1523eac9f95a80d9c 100644 (file)
@@ -80,6 +80,8 @@ char*                    p11_kit_space_strdup              (const unsigned char
 
 #ifdef P11_KIT_FUTURE_UNSTABLE_API
 
+void                     p11_kit_set_progname              (const char *progname);
+
 void                     p11_kit_be_quiet                  (void);
 
 const char*              p11_kit_message                   (void);
index d23c1e65f1c707e626ca403d9d73bce700b0a13b..36acb7e2d5f292805a04949a99e1e72bf51f6a73 100644 (file)
@@ -92,4 +92,8 @@ void        _p11_kit_clear_message                              (void);
 
 void        _p11_kit_default_message                            (CK_RV rv);
 
+const char * _p11_get_progname_unlocked                         (void);
+
+void        _p11_set_progname_unlocked                          (const char *progname);
+
 #endif /* __P11_KIT_PRIVATE_H__ */
index c04b6360cc0877ec944c8a5b7bb6dfeff9a9128f..fd7708a1f640b552a5bda0870d419cccb11fd370 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2011 Collabora Ltd
+ * Copyright (c) 2012 Stef Walter
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +32,7 @@
  *
  *
  * CONTRIBUTORS
- *  Stef Walter <stef@memberwebs.com>
+ *  Stef Walter <stef@thewalter.net>
  */
 
 #include "config.h"
@@ -246,6 +247,14 @@ _p11_kit_default_message (CK_RV rv)
        }
 }
 
+static void
+uninit_common (void)
+{
+       _p11_debug ("uninitializing library");
+
+       _p11_set_progname_unlocked (NULL);
+}
+
 #ifdef OS_UNIX
 
 static pthread_key_t thread_local = 0;
@@ -277,10 +286,47 @@ _p11_library_init (void)
 void
 _p11_library_uninit (void)
 {
+       uninit_common ();
+
        pthread_key_delete (thread_local);
        _p11_mutex_uninit (&_p11_mutex);
 }
 
+#if defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) && !HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+extern char *program_invocation_short_name;
+#endif
+
+#if defined (HAVE___PROGNAME) && !HAVE_DECL___PROGNAME
+extern char *__progname;
+#endif
+
+static char *
+get_default_progname (void)
+{
+       const char *name;
+
+#if defined (HAVE_GETPROGNAME)
+       name = getprogname();
+#elif defined (HAVE_GETEXECNAME)
+       const char *p;
+       name = getexecname();
+       p = strrchr (name ? name : "", '/');
+       if (p != NULL)
+               name = p + 1;
+#elif defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME)
+       name = program_invocation_short_name;
+#elif defined (HAVE___PROGNAME)
+       name = __progname;
+#else
+       #error No way to retrieve program name from p11-kit library
+#endif
+
+       if (name == NULL)
+               return NULL;
+
+       return strdup (name);
+}
+
 #endif /* OS_UNIX */
 
 #ifdef OS_WIN32
@@ -331,7 +377,7 @@ _p11_library_uninit (void)
 {
        LPVOID data;
 
-       _p11_debug ("uninitializing library");
+       uninit_common ();
 
        if (thread_local != TLS_OUT_OF_INDEXES) {
                data = TlsGetValue (thread_local);
@@ -376,4 +422,69 @@ DllMain (HINSTANCE instance,
        return TRUE;
 }
 
+extern char **__argv;
+
+static char *
+get_default_progname (void)
+{
+       const char *name;
+       const char *p;
+       char *progname;
+       size_t length;
+
+       name = __argv[0];
+       if (name == NULL)
+               return NULL;
+
+       p = strrchr (name, '\\');
+       if (p != NULL)
+               name = p + 1;
+
+       progname = strdup (name);
+       length = strlen (progname);
+       if (length > 4 && _stricmp(progname + (length - 4), ".exe"))
+               progname[length - 4] = '\0';
+
+       return progname;
+}
+
 #endif /* OS_WIN32 */
+
+/* This is the progname that we think of this process as. */
+char *_p11_my_progname = NULL;
+
+/**
+ * p11_kit_set_progname:
+ * @progname: the program base name
+ *
+ * Set the program base name that is used by the <literal>enable-in</literal>
+ * and <literal>disable-in</literal> module configuration options.
+ *
+ * Normally this is automatically calculated from the program's argument list.
+ * You would usually call this before initializing p11-kit modules.
+ */
+void
+p11_kit_set_progname (const char *progname)
+{
+       _p11_library_init_once ();
+
+       _p11_lock ();
+       _p11_set_progname_unlocked (progname);
+       _p11_unlock ();
+}
+
+void
+_p11_set_progname_unlocked (const char *progname)
+{
+       /* We can be called with NULL, to cleanup memory usage */
+       free (_p11_my_progname);
+       _p11_my_progname = progname ? strdup (progname) : NULL;
+}
+
+const char *
+_p11_get_progname_unlocked (void)
+{
+       if (_p11_my_progname == NULL)
+               _p11_my_progname = get_default_progname ();
+       return _p11_my_progname;
+}
index 819b74a214e575fcfd71f2b91dcd7c65e28c398e..0400045cb94e3afa9f7fa60eee4bf10c30137aed 100644 (file)
@@ -13,6 +13,7 @@ LDADD = \
 CHECK_PROGS = \
        hash-test \
        ptr-array-test \
+       progname-test \
        conf-test \
        uri-test \
        pin-test \
@@ -28,6 +29,7 @@ conf_test_SOURCES = conf-test.c $(cutestfiles)
 hash_test_SOURCES = hash-test.c $(cutestfiles)
 pin_test_SOURCES = pin-test.c $(cutestfiles)
 ptr_array_test_SOURCES = ptr-array-test.c $(cutestfiles)
+progname_test_SOURCES = progname-test.c $(cutestfiles)
 test_init_SOURCES = \
        test-init.c \
        mock-module.c mock-module.h $(cutestfiles)
diff --git a/tests/progname-test.c b/tests/progname-test.c
new file mode 100644 (file)
index 0000000..1e42056
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012 Stefan Walter
+ *
+ * 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 <stef@thewalter.net>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "p11-kit/uri.h"
+#include "p11-kit/p11-kit.h"
+#include "p11-kit/private.h"
+
+static void
+test_progname_default (CuTest *tc)
+{
+       const char *progname;
+
+       progname = _p11_get_progname_unlocked ();
+       CuAssertStrEquals (tc, "progname-test", progname);
+}
+
+static void
+test_progname_set (CuTest *tc)
+{
+       const char *progname;
+
+       p11_kit_set_progname ("love-generation");
+
+       progname = _p11_get_progname_unlocked ();
+       CuAssertStrEquals (tc, "love-generation", progname);
+
+       _p11_set_progname_unlocked (NULL);
+
+       progname = _p11_get_progname_unlocked ();
+       CuAssertStrEquals (tc, "progname-test", progname);
+}
+
+/* Defined in util.c */
+extern char *_p11_my_progname;
+
+static void
+test_progname_uninit_clears (CuTest *tc)
+{
+       _p11_set_progname_unlocked ("love-generation");
+       CuAssertStrEquals (tc, "love-generation", _p11_my_progname);
+
+       /* Inititialize should clear above variable */
+       _p11_library_uninit ();
+
+       CuAssertPtrEquals (tc, NULL, _p11_my_progname);
+}
+
+int
+main (void)
+{
+       CuString *output = CuStringNew ();
+       CuSuite* suite = CuSuiteNew ();
+       int ret;
+
+       _p11_library_init ();
+
+       SUITE_ADD_TEST (suite, test_progname_default);
+       SUITE_ADD_TEST (suite, test_progname_set);
+
+       /* This test should be last, as it uninitializes the library */
+       SUITE_ADD_TEST (suite, test_progname_uninit_clears);
+
+       CuSuiteRun (suite);
+       CuSuiteSummary (suite, output);
+       CuSuiteDetails (suite, output);
+       printf ("%s\n", output->buffer);
+       ret = suite->failCount;
+       CuSuiteDelete (suite);
+       CuStringDelete (output);
+       return ret;
+}