[PATCH] libcreds patch

Markku Savela (none) msa at moth.iki.fi
Thu Jan 14 03:58:19 PST 2010


From: Markku Savela <msa at moth.iki.fi>

---
 bus/config-parser.c |   58 +++++++++++++++++++++++++++++++----
 bus/policy.c        |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++
 bus/policy.h        |   14 ++++++++
 configure.in        |   23 +++++++++++++-
 4 files changed, 169 insertions(+), 9 deletions(-)

diff --git a/bus/config-parser.c b/bus/config-parser.c
index d8ae459..e487a71 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -20,6 +20,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+#ifdef DBUS_BUS_ENABLE_CREDS
+#include <err.h>
+#include <limits.h>
+#include <sys/creds.h>
+#endif
 #include "config-parser-common.h"
 #include "config-parser.h"
 #include "test.h"
@@ -40,6 +45,9 @@ typedef enum
   POLICY_MANDATORY,
   POLICY_USER,
   POLICY_GROUP,
+#ifdef DBUS_BUS_ENABLE_CREDS
+  POLICY_CREDS,
+#endif
   POLICY_CONSOLE
 } PolicyType;
 
@@ -968,6 +976,9 @@ start_busconfig_child (BusConfigParser   *parser,
       const char *context;
       const char *user;
       const char *group;
+#ifdef DBUS_BUS_ENABLE_CREDS
+      const char *creds;
+#endif
       const char *at_console;
 
       if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
@@ -985,17 +996,20 @@ start_busconfig_child (BusConfigParser   *parser,
                               "context", &context,
                               "user", &user,
                               "group", &group,
+#ifdef DBUS_BUS_ENABLE_CREDS
+                              "creds", &creds,
+#endif
                               "at_console", &at_console,
                               NULL))
         return FALSE;
 
-      if (((context && user) ||
-           (context && group) ||
-           (context && at_console)) ||
-           ((user && group) ||
-           (user && at_console)) ||
-           (group && at_console) ||
-          !(context || user || group || at_console))
+      if ((context != NULL) +
+          (user != NULL) +
+          (group != NULL) +
+#ifdef DBUS_BUS_ENABLE_CREDS
+          (creds != NULL) +
+#endif
+          (at_console != NULL) != 1)
         {
           dbus_set_error (error, DBUS_ERROR_FAILED,
                           "<policy> element must have exactly one of (context|user|group|at_console) attributes");
@@ -1044,6 +1058,22 @@ start_busconfig_child (BusConfigParser   *parser,
             _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
                         group);          
         }
+#ifdef DBUS_BUS_ENABLE_CREDS
+      else if (creds != NULL)
+        {
+          creds_type_t type;
+          creds_value_t value;
+          type = creds_str2creds(creds, &value);
+          if (type != CREDS_BAD && (value & ~CREDS_MASK) == 0)
+            {
+              e->d.policy.type = POLICY_CREDS;
+              e->d.policy.gid_uid_or_at_console = CREDS_KEY(type,value);
+            }
+          else
+            _dbus_warn("Unable to translate credential \"%s\" in message bus configuration file\n",
+                       creds);
+        }
+#endif
       else if (at_console != NULL)
         {
            dbus_bool_t t;
@@ -1615,7 +1645,21 @@ append_rule_from_element (BusConfigParser   *parser,
             goto nomem;
           break;
         
+#ifdef DBUS_BUS_ENABLE_CREDS
+        case POLICY_CREDS:
+          if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "<%s> rule cannot be per-group because it has bus-global semantics",
+                              element_name);
+              goto failed;
+            }
+          if (!bus_policy_append_creds_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
+                                            rule))
+            goto nomem;
+          break;
 
+#endif
         case POLICY_CONSOLE:
           if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
                                                rule))
diff --git a/bus/policy.c b/bus/policy.c
index bc1d2d9..cf72622 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -21,6 +21,10 @@
  *
  */
 
+#ifdef DBUS_BUS_ENABLE_CREDS
+#include <limits.h>
+#include <sys/creds.h>
+#endif
 #include "policy.h"
 #include "services.h"
 #include "test.h"
@@ -129,6 +133,9 @@ struct BusPolicy
   DBusList *mandatory_rules;       /**< Mandatory policy rules */
   DBusHashTable *rules_by_uid;     /**< per-UID policy rules */
   DBusHashTable *rules_by_gid;     /**< per-GID policy rules */
+#ifdef DBUS_BUS_ENABLE_CREDS
+  DBusHashTable *rules_by_creds;   /**< per-CREDS policy rules */
+#endif
   DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
   DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
 };
@@ -180,6 +187,15 @@ bus_policy_new (void)
   if (policy->rules_by_gid == NULL)
     goto failed;
 
+#ifdef DBUS_BUS_ENABLE_CREDS
+  policy->rules_by_creds = _dbus_hash_table_new (DBUS_HASH_ULONG,
+                                                 NULL,
+                                                 free_rule_list_func);
+  if (policy->rules_by_creds == NULL)
+    goto failed;
+
+#endif  
+
   return policy;
   
  failed:
@@ -229,6 +245,14 @@ bus_policy_unref (BusPolicy *policy)
           _dbus_hash_table_unref (policy->rules_by_gid);
           policy->rules_by_gid = NULL;
         }
+
+#ifdef DBUS_BUS_ENABLE_CREDS
+      if (policy->rules_by_creds)
+        {
+          _dbus_hash_table_unref (policy->rules_by_creds);
+          policy->rules_by_creds = NULL;
+        }
+#endif
       
       dbus_free (policy);
     }
@@ -320,6 +344,37 @@ bus_policy_create_client_policy (BusPolicy      *policy,
 
       dbus_free (groups);
     }
+
+#ifdef DBUS_BUS_ENABLE_CREDS
+  if (_dbus_hash_table_get_n_entries (policy->rules_by_creds) > 0)
+    {
+      unsigned long pid;
+      creds_t creds;
+      DBusHashIter iter;
+
+      if (!dbus_connection_get_unix_process_id(connection, &pid))
+        goto failed;
+      creds = creds_gettask(pid);
+      if (creds == NULL)
+        goto failed;
+      _dbus_hash_iter_init(policy->rules_by_creds, &iter);
+      while (_dbus_hash_iter_next(&iter))
+        {
+          unsigned long id = _dbus_hash_iter_get_ulong_key (&iter);
+          DBusList **list = _dbus_hash_iter_get_value(&iter);
+
+          if (list != NULL && creds_have_p(creds, CREDS_TYPE(id), CREDS_VALUE(id)))
+            {
+              if (!add_list_to_client(list, client))
+                {
+                  creds_free(creds);
+                  goto nomem;
+                }
+            }
+        }
+      creds_free(creds);
+    }
+#endif
   
   if (dbus_connection_get_unix_user (connection, &uid))
     {
@@ -575,6 +630,28 @@ bus_policy_append_group_rule (BusPolicy      *policy,
   return TRUE;
 }
 
+#ifdef DBUS_BUS_ENABLE_CREDS
+dbus_bool_t
+bus_policy_append_creds_rule (BusPolicy      *policy,
+                              long           cid,
+                              BusPolicyRule  *rule)
+{
+  DBusList **list;
+
+  list = get_list (policy->rules_by_creds, cid);
+
+  if (list == NULL)
+    return FALSE;
+
+  if (!_dbus_list_append (list, rule))
+    return FALSE;
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+}
+#endif
+
 dbus_bool_t
 bus_policy_append_console_rule (BusPolicy      *policy,
                                 dbus_bool_t     at_console,
@@ -683,6 +760,12 @@ bus_policy_merge (BusPolicy *policy,
   if (!merge_id_hash (policy->rules_by_gid,
                       to_absorb->rules_by_gid))
     return FALSE;
+#ifdef DBUS_BUS_ENABLE_CREDS
+
+  if (!merge_id_hash (policy->rules_by_creds,
+                      to_absorb->rules_by_creds))
+    return FALSE;
+#endif
 
   return TRUE;
 }
diff --git a/bus/policy.h b/bus/policy.h
index 1782dbf..ca8b805 100644
--- a/bus/policy.h
+++ b/bus/policy.h
@@ -128,6 +128,20 @@ dbus_bool_t      bus_policy_append_user_rule      (BusPolicy        *policy,
 dbus_bool_t      bus_policy_append_group_rule     (BusPolicy        *policy,
                                                    dbus_gid_t        gid,
                                                    BusPolicyRule    *rule);
+#ifdef DBUS_BUS_ENABLE_CREDS
+/* ..to enable use of the hash lists with long key, define some
+   constants to pack creds type and value into a long. This is
+   a temp solution, should really have a hashlist with two longs
+   as a key */
+#define CREDS_MASK (~0UL >> 3)
+#define CREDS_SHIFT (CHAR_BIT * sizeof(long) - 3)
+#define CREDS_KEY(type,value) (((value) & CREDS_MASK) | ((type) << CREDS_SHIFT))
+#define CREDS_TYPE(hashkey) (((hashkey) & ~CREDS_MASK) >> CREDS_SHIFT)
+#define CREDS_VALUE(hashkey) ((hashkey) & CREDS_MASK)
+dbus_bool_t      bus_policy_append_creds_rule     (BusPolicy        *policy,
+                                                   long              cid,
+                                                   BusPolicyRule    *rule);
+#endif
 dbus_bool_t      bus_policy_append_console_rule   (BusPolicy        *policy,
                                                    dbus_bool_t        at_console,
                                                    BusPolicyRule    *rule);
diff --git a/configure.in b/configure.in
index 1f2c896..1fee781 100644
--- a/configure.in
+++ b/configure.in
@@ -112,6 +112,7 @@ AC_ARG_ENABLE(inotify, AS_HELP_STRING([--enable-inotify],[build with inotify sup
 AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support]),enable_kqueue=$enableval,enable_kqueue=auto)
 AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
 AC_ARG_ENABLE(userdb-cache, AS_HELP_STRING([--enable-userdb-cache],[build with userdb-cache support]),enable_userdb_cache=$enableval,enable_userdb_cache=yes)
+AC_ARG_ENABLE(creds, AS_HELP_STRING([--enable-creds],[add process credentials based policy checks (linux only)]),enable_creds=$enableval,enable_creds=auto)
 
 AC_ARG_WITH(xml, AS_HELP_STRING([--with-xml=[libxml/expat]],[XML library to use]))
 AC_ARG_WITH(init-scripts, AS_HELP_STRING([--with-init-scripts=[redhat]],[Style of init scripts to install]))
@@ -889,6 +890,24 @@ if test x$have_libaudit = xyes ; then
     AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support])
 fi
 
+# creds checks
+if test x$enable_creds = xno ; then
+    have_creds=no;
+else
+    have_creds=yes;
+    AC_CHECK_HEADERS(sys/creds.h, have_creds=yes, have_creds=no)
+    if test x$have_creds = xyes ; then
+        AC_CHECK_LIB(creds, creds_gettask, 
+                 have_creds=yes, have_libcreds=no)
+    fi
+fi
+
+AM_CONDITIONAL(DBUS_BUS_ENABLE_CREDS, test x$have_creds = xyes)
+if test x$have_creds = xyes ; then
+    CREDS_LIBS="-lcreds"
+    CREDS_CFLAGS="-DDBUS_BUS_ENABLE_CREDS"
+fi
+
 # Check for ADT API
 AC_MSG_CHECKING(for ADT API)
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -928,8 +947,8 @@ DBUS_CLIENT_LIBS="$THREAD_LIBS $NETWORK_libs"
 AC_SUBST(DBUS_CLIENT_CFLAGS)
 AC_SUBST(DBUS_CLIENT_LIBS)
 
-DBUS_BUS_CFLAGS="$XML_CFLAGS"
-DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $INTLLIBS $THREAD_LIBS $ADT_LIBS $NETWORK_libs"
+DBUS_BUS_CFLAGS="$XML_CFLAGS $CREDS_CFLAGS"
+DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $INTLLIBS $THREAD_LIBS $ADT_LIBS $NETWORK_libs $CREDS_LIBS"
 AC_SUBST(DBUS_BUS_CFLAGS)
 AC_SUBST(DBUS_BUS_LIBS)
 
-- 
1.6.3.3



More information about the dbus mailing list